9

I am looking for a clean and simple example of how to use the "under" functionality in a "Mojolicious" application. All the examples I find are dealing with "Mojolicious::Lite" (which I don't use). For example I listened to the screencast here http://mojocasts.com/e3 and I think I understand the concept of the under functionality. But I don't use "Mojolicious::Lite", so it seems that I can't follow the example directly. I keep on failing trying to adopt the Lite-example for non-Lite style. (That's probably also because I'm still kind of new to the framework)

The relevant code looks like this:

# Router
my $r = $self->routes;

# Normal route to controller
$r->get('/') ->to('x#a');
$r->get('/y')->to('y#b');
$r->any('/z')->to('z#c');

So all of this routes need to be protected by user/pass. I tried to do something like this:

$r->under = sub { return 1 if ($auth) };

But this does not compile and I just can't find an example matching this code-style... Can anybody give me the right hint or link here? And please forgive me if this is somewhere in the docs... they might be complete, but they lack understandable examples for simple minded guys like me :-P

Boris Däppen
  • 1,136
  • 7
  • 20
  • 1
    It seems like I should look for solutions using "over" or "bridge"..? The bridge-example also uses a auth-usecase: http://mojolicio.us/perldoc/Mojolicious/Routes/Route#bridge – Boris Däppen Oct 16 '12 at 13:03
  • 1
    I found an example for "under" in this context: http://mojolicio.us/perldoc/Mojolicious/Routes/Route#under – Boris Däppen Oct 16 '12 at 13:05

3 Answers3

15

The analogous code to the Lite-examples looks like this:

# Router
my $r = $self->routes;

# This route is public
$r->any('/login')->to('login#form');

# this sub does the auth-stuff
# you can use stuff like: $self->param('password')
# to check user/pw and return true if fine
my $auth = $r->under( sub { return 1 } );

# This routes are protected
$auth->get ('/') ->to('x#a');
$auth->post('/y')->to('y#b');
$auth->any ('/z')->to('z#c');

Hopes this helps anybody!

(Solution found here: http://mojolicio.us/perldoc/Mojolicious/Routes/Route#under)

Boris Däppen
  • 1,136
  • 7
  • 20
3

I am doing it like this - in a full mojo (not lite) app:

in the startup method

$self->_add_routes_authorization();

# only users of type 'cashier' will have access to routes starting with /cashier
my $cashier_routes = $r->route('/cashier')->over( user_type => 'cashier' );
$cashier_routes->route('/bank')->to('cashier#bank');

# only users of type 'client' will have access to routes starting with /user
my $user_routes = $r->route('/user')->over( user_type => 'client' );
$user_routes->get('/orders')->to('user#orders');

below in the main app file:

sub _add_routes_authorization {
  my $self = shift;

  $self->routes->add_condition(
    user_type => sub {
      my ( $r, $c, $captures, $user_type ) = @_;

      # Keep the weirdos out!
      # $self->user is the current logged in user, as a DBIC instance
      return
        if ( !defined( $self->user )
        || $self->user->user_type()->type() ne $user_type );

      # It's ok, we know him
      return 1;
    }
  );

  return;
}

I hope this helps

Tudor Constantin
  • 24,065
  • 7
  • 44
  • 66
0

I use this scenario in my application:

my $guest =  $r->under->to( "auth#check_level" );
my $user  =  $r->under->to( "auth#check_level", { required_level =>  100 } );
my $admin =  $r->under->to( "auth#check_level", { required_level =>  200 } );


$guest->get ( '/login'  )->to( 'auth#login'  );
$user ->get ( '/users/profile' )->to( 'user#show' );

After this all children routes of $r will go over check_level subroutine:

sub check_level {
    my( $self ) =  @_;

    # GRANT   If we do not require any access privilege
    my $rl =  $self->stash->{ required_level };
    return 1   if !$rl;

    # GRANT   If logged in user has required level OR we raise user level one time
    my $sl =  $self->session->{ user_level };
    my $fl =  $self->flash( 'user_level' );
    return 1   if $sl >= $rl  ||  $fl && $fl >= $rl;

    # RESTRICT 
    $self->render( 'auth/login',  status => 403 );
    return 0;
}
Eugen Konkov
  • 15,716
  • 7
  • 69
  • 107