Hi David,
>
> The original goes like this:
>
> my $r = $self->routes;
>
> What you want to do is this:
>
> my $routes = $self->routes;
> my $r = $routes->bridge('/')->to('auto#after_office_hours_checker');
>
>
> That is a great suggestion that resolves one issue in a smarter way than
> invalidating the cookies. Thanks.
>
> There is a second issue that resetting the application secret helps with:
> Creating a moving target with respect to the MD5 hash that signs the
> cookies. I still think I'd like to update the secret at a regular (and
> after-hours) interval.
>
True, it does do that, although on the other hand you could do that with a
cron job too. If you use one of the Config plugins that ships with
Mojolicious, you can read the configuration, and use a configuration value to
set the secret. Then just set up a cron job that changes the secret to
something random every X days or however you want to set that up.
> As for your bridge suggestion, I've currently got this sort of a set of routes:
>
> $r->any('/login')->to( controller => 'user', action => 'login' )
> ->name('login');
> $r->any('/')->to( controller => 'user', action => 'welcome' )
> ->name('welcome');
> $r->any('/:controller/:action')->over( authenticated => 1 )->to(
> controller => $app->stash('controller'),
> action => $app->stash('action')
> );
>
> ...letting URI's automatically bind to their controllers, but only once a
> user has passed the authentication (provided by
> Mojolicious::Plugin::Authentication, and Class::User::DBI). Would my 'over'
> clause change the nature of your bridge?
Yes, you'd want to move that to the bridge as well, so your bridge code would do:
sub the_bridge {
my $self = shift;
if($self->is_user_authenticated) {
# code for the office hours, user setup, etc. etc. here
} else {
# emulate 'over' behaviour and...
$self->render(text => 'Not Found', status => 404);
}
}
The "over" authentication bit will effectively 404 anything for a
non-authenticated user so we can emulate that, or you can just pop up a page
telling people they need to go log in or otherwise contact someone or do
something. It's theoretically also possible to put the office hour check into
the load_user callback although you won't be able to give any specific
feedback as to why someone can't log in at that point.
>
> I thank you for your response. Setting up an effective routing strategy
> seems to be one of the bigger parts of the learning curve here. :)
Well, it's the same as with Perl, there's always more than one way to do it
which is why I put the routing condition thing into
Mojolicious::Plugin::Authentication. I'm a bridge guy, I dig them and use them
for a lot of things, but I know other people like using routing conditions
since it saves on a few calls here and there. However, the routing condition
(in my head anyway) was always meant as a quick shortcut to enable
authenticated access to bits of site that might fall outside a global "member"
area - or to select different outputs for the same page.
Side-tracking: Imagine this:
$r->route('/')->over(authenticated => 1)->to('foo#baz');
$r->route('/')->to('foo#bar');
If I'm not mistaken (going off the top of my head here) if the user isn't
authenticated the first route won't match, but the second one will. And vice
versa, if the user is authenticated, the first one will match and the 2nd one
won't match.
So, back on track, personally I think bridges are the way to go, because it's
relatively easy to chain them up, and it can be a real benefit if you want to
do things like, "/user/<user_id>", you can bridge /user to a sub that finds
out a) if that user exists, and b) if the current user is allowed to see it,
then add a '/' route to the bridge to render the content you need.
Take my ramblings with a grain of salt though, this way works for me since it
was similar to what Catalyst's chained routes do and that's where I came from,
so there might be a much better/cleaner/shinier way of doing it, but this
works for me, as always though: YMMV :)