Mojolicious-Plugin-Loco
view release on metacpan or search on metacpan
lib/Mojolicious/Plugin/Loco.pod view on Meta::CPAN
=head1 NAME
Mojolicious::Plugin::Loco - launch a web browser; easy local GUI
=head1 VERSION
version 0.008
=head1 SYNOPSIS
use Mojolicious::Lite;
plugin 'Loco';
get '/' => "index";
post '/kick-me' => sub {
my $c = shift;
return if $c->loco->csrf_fail;
# system q(cat /dev/urandom | fdisk);
my $bcount = ++$c->session->{bruises};
$c->flash(msg => "Ok, that hurt. ($bcount)");
$c->redirect_to('/');
};
post '/quit' => sub { shift->loco->quit; };
app->secrets(['I am the very model of a modern major general'.rand()]);
app->start;
__DATA__
@@ index.html.ep
% layout 'default';
<h1>Ready!</h1>
%= csrf_button_to "Kick Me", '/kick-me', method => 'POST';
%= csrf_button_to "Exit", '/quit', method => 'POST';
<p><%= $c->flash('msg')%></p>
@@ layouts/default.html.ep
<!DOCTYPE html><html><head>
%= $c->loco->jsload; # needs to be on every page
%= content_for 'head';
</head><body>
%= content
</body>
</html>
Save to C<myapp.pl>, and then
perl myapp.pl daemon
=head1 DESCRIPTION
This plugin allows writing low-effort desktop applications using L<Mojolicious> (even cross-platform ones if your code is sufficiently portable).
When run as a L<daemon|Mojolicious::Command::daemon> listening on an explicit port, the plugin launches an internet browser, passing an initial URL and seed so that subsequent requests from that browser can be distinguished. Client-side javascript t...
For applications making changes to the filesystem / local machine state, or handling sensitive data or anything else that matters, please see L</"SECURITY CONSIDERATIONS">
This module is currently experimental; the API may change without notice.
=head1 OPTIONS
=head2 config_key
Key of the configuration hash (C<app-E<gt>config>) containing plugin option values. Default is C<'loco'>. If false, then C<app-E<gt>config> is not consulted.
=head2 initial_wait
How many seconds for the server to wait for the initial browser window to finish loading before giving up and shutting down. Zero means wait forever. Default is 15.
=head2 final_wait
How many seconds for the server to wait after the last browser window ceases communicating before shutting down (we do not rely on C<window.unload>). Default is 3.
Since javascript timer events from backgrounded/hidden tabs/windows are typically throttled in current browsers, reducing this below 2 will most likely make the application terminate prematurely if all windows are hidden or minimized.
=head2 entry
URI path for the entry point of your application (i.e., what to display in the initial brower window). Default is C</>.
=head2 api_path
URI path prefix reserved for use by this plugin. Endpoints needed by this module live here; this is also where the required javascript file(s) are served from. Default is C</hb/>; it can be pretty much anything as long as it's distinct from what th...
=head2 browser
Which browser (executable file) to run. If false (C<0> or C<''>) then no browser will be invoked. If a subroutine reference, then it is assumed that calling it with a URI as first argument will launch something useful. Default is for L<Browser::Op...
=head2 allow_other_sessions
If false (default), L<$c-E<gt>validation-E<gt>csrf_protect|Mojolicious::Validator::Validation#csrf_protect> fails on any session other than the one started from the initial browser launched. Requests doing this check are then blocked from all other ...
If true, L<$c-E<gt>validation-E<gt>csrf_protect|Mojolicious::Validator::Validation#csrf_protect> will behave in the default manner, and you will need to check L</loco-E<gt>id> explicitly.
Read L</"SECURITY CONSIDERATIONS"> if you think you might want to set this.
=head1 HELPERS
=head2 loco->config
Get or set plugin configuration L<options|/OPTIONS>. Note that most values are only meaningful prior to server start so changing them thereafter won't affect anything.
$c->loco->config # -> full hash of settings
$c->loco->config('final_wait') # -> 3
$c->loco->config(final_wait => 200) # -> $c, sets final_wait
$c->loco->config({final_wait => 200}) # -> same
app->config('loco')->{final_wait} = 200 # same effect if config_key not changed
=head2 loco->id
Get or set the session id (for the purposes of this plugin). By default, this is 1 for the launched browser's session and undefined for all others.
=head2 loco->csrf_fail
Renders an HTTP 400 reply and returns true unless C<csrf_token> validation succeeds. If L</allow_other_sessions> is false, this implicitly also checks L</loco-E<gt>id>.
return if $c->loco->csrf_fail;
=head2 loco->id_fail
Renders an HTTP 400 reply and returns true unless there is a nonzero session id.
return if $c->loco->id_fail;
=head2 loco->quit
Stop the server and render a final page if necessary. This implicitly calls L</loco-E<gt>csrf_fail> and checks L</loco-E<gt>id>.
=head2 loco->jsload
Loads whatever javascript needs to be in the <head> section of every page to be displayed in the browser window. You most likely want this in your default layout.
%= $c->loco->jsload;
Or you can be more elaborate
%= $c->loco->jsload( jquery => 'https://code.jquery.com/jquery-3.3.1.min.js', begin
.on_hb(function(h) {
// do something on every heartbeat
$('#heartbeat').html(h);
})
% end );
Options for L</loco-E<gt>jsload> include
=head3 jquery
URL to be loading jquery from. Default is to use the jquery version included in the Mojolicious distribution. Specifying an empty string C<''> suppresses jquery loading entirely, if you have already loaded it as part of some other package.
=head3 nofinish
Suppress the default C<on_finish> handler.
=head3 begin
Final C<begin> block, if provided, will be assumed to be javascript code to further configure the heartbeat object (code is preceded by C<$().heartbeat()>), typically to add C<on_hb> or C<on_finish> handlers
=head1 SECURITY CONSIDERATIONS
In a typical desktop application, traffic between the user interface and the application code will be invisible to remote attackers and code running in different processes. Structuring your application as a Mojolicious server with UI provided by an ...
What follows is a (necessarily incomplete) listing of vulnerabilities you may need to address.
=over
=item Listening on Network-accessible Interfaces/Ports
Using a listening point that is network accessible means the server will (at least initially) accept incoming connection attempts from untrusted remote sites unless you have a reliable firewall to block these. If, in addition, L</allow_other_session...
By default, Mojolicious servers listen at C<http://*:3000>, where C<*> means all available interfaces, so you need to change this (C<localhost>, C<127.0.0.1>, or C<[::1]>) using either C<$ENV{MOJO_LISTEN}> or the C<-l> command line argument that the ...
=item Cross-Site Scripting
Style-sheets or script pages served by your application should not reveal application secrets (e.g., the current C<csrf_token>).
Pages/templates should not incorporate scripts from untrusted sources.
Use a browser that enforces domain restrictions so that HTML page content and cookies are not observable from scripts running in other domains (most current browsers do this correctly).
=item Cross-Site Request Forgery
Since any webpage may potentially contain links, buttons, or forms targeting your application, you should use and check C<csrf_token> on any requests that change application state, write to the local filesystem, or otherwise make use of privileges be...
=item Access From Other Local Processes
With this plugin loaded, C<< $c->validation->csrf_protect >> will fail on sessions other from the one created by the browser launched.
If, however you choose to L</allow_other_sessions> then it is assumed you have some independent means of authenticating them. Your application will be receiving requests from other local processes (including other browsers you may have installed). ...
=over
=item *
You are concurrently running instances of alternative/out-dated browsers with cross-site scripting vulnerabiliities visiting untrusted sites that can exploit them.
=item *
There are other local users on your machine.
=item *
Your application runs setuid or otherwise invokes elevated privileges (which could then be used by other processes to bypass various protections).
=back
=back
=head1 METHODS
L<Mojolicious::Plugin::Loco> inherits all methods from
L<Mojolicious::Plugin> and implements the following new ones.
=head2 register
$plugin->register($app, entry => '/', initial_wait => 15);
Register plugin in L<Mojolicious> application. Key-value pairs give default L<option|/OPTIONS> values for this application. Everything other than L</config_key> may be overridden in the L<application configuration|Mojolicious#config>.
=head1 SEE ALSO
( run in 1.816 second using v1.01-cache-2.11-cpan-5837b0d9d2c )