2012-08-09 7 views
6

Tengo el siguiente código:¿Cómo agrego más de uno sobre el método a una ruta mojolicious?

$r->find('user')->via('post')->over(authenticated => 1); 

Teniendo en cuenta que la ruta que pueda llegar a la ruta de usuario pasa a través de la comprobación de que es autenticado configuración utilizando Mojolicious :: Plugin :: autenticación.

Quiero agregar otro 'sobre' a esa ruta.

$r->find('user')->via('post')->over(authenticated => 1)->over(access => 1); 

Sin embargo, parece anular el autenticado 'over'.

he intentado romper las rutas con nombres como:

my $auth = $r->route('/')->over(authenticated => 1) 
    ->name('Authenticated Route'); 

$access = $auth->route('/user')->over(access => 1)->name('USER_ACCESS'); 

que no funcionaron en absoluto sin embargo. Ninguno de los "over" está siendo accedido.

Mis rutas son cosas como/usuario,/elemento, configurado con MojoX :: JSON :: RPC :: Service. Por lo tanto, no tengo cosas como/user /: id para configurar subrutas. (No estoy seguro de que importe) Todas las rutas son como/usuario, enviadas con parámetros.

Tengo una condición como:

$r->add_condition(
    access => sub { 
     # do some stuff 
    }, 
); 

que es el 'acceso' en $ r-> ruta ('/ user') -> sobre (acceso => ​​1);

En resumen, las rutas funcionan bien cuando se utiliza:

$r->find('user')->via('post')->over(authenticated => 1); 

pero soy incapaz de agregar una segunda ruta.

Entonces, ¿qué me falta al configurar estas rutas con múltiples condiciones? ¿Es posible agregar múltiples condiciones a una sola ruta/route_name?

+0

Me di cuenta de lo mismo cuando estaba implementando RBAC. Quería concesiones de acceso basadas en privilegios para comportarme como un árbol, lo que significaría encadenamientos. No funcionó. Supongo que es por eso que nos dieron puentes. :) – DavidO

+1

Mi problema es que tengo la ruta en un modificador de ruta 'add_condition', como se muestra en mi código anterior. Entonces, no pude unirme a ellos. Supongo que podría mover la condición a un módulo, como una función, y usar un puente. Tal como está, lo coloqué en un gancho antes del envío. – jmcneirney

Respuesta

2

sólo puede utilizar tanto en condiciones en over como en esta prueba:

use Mojolicious::Lite; 

# dummy conditions storing their name and argument in the stash 
for my $name (qw(foo bar)) { 
    app->routes->add_condition($name => sub { 
     my ($route, $controller, $to, @args) = @_; 
     $controller->stash($name => $args[0]); 
    }); 
} 

# simple foo and bar dump action 
sub dump { 
    my $self = shift; 
    $self->render_text(join ' ' => map {$self->stash($_)} qw(foo bar)); 
} 

# traditional route with multiple 'over' 
app->routes->get('/frst')->over(foo => 'yo', bar => 'works')->to(cb => \&dump); 

# lite route with multiple 'over' 
get '/scnd' => (foo => 'hey', bar => 'cool') => \&dump; 

# test the lite app above 
use Test::More tests => 4; 
use Test::Mojo; 

my $t = Test::Mojo->new; 

# test first route 
$t->get_ok('/frst')->content_is('yo works'); 
$t->get_ok('/scnd')->content_is('hey cool'); 

__END__ 
1..4 
ok 1 - get /frst 
ok 2 - exact match for content 
ok 3 - get /scnd 
ok 4 - exact match for content 

funciona bien aquí con Mojolicious 3.38 por Perl 5.12.1 - @DavidO es correcta, puede que los puentes pueden hacer el trabajo mejor.:)

0

En mi caso utilizo dos métodos: under

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

$guest->get('/')->to('main#index'); 
$user->get('/user')->to('user#show'); 
$super_admin = $admin->under->to('manage#check_level', { super_admin => 100 }); 
$super_admin->get('/delete_everything')->to('system#shutdown'); 

En este ejemplo, cuando cualquiera de rutas coinciden con alguna under se llamará

'/' -> auth#check_level -> main_index 
'/user' -> auth#check_level { required_level => 100 } -> 'user#show' 
'/delete_everything' -> auth#check_level { required_level => 200 } -> 'manage#check_level', { super_admin => 100 } -> 'system#shutdown' 

Como se puede ver antes de destino en action su controller se ejecutará otra acción llamada: auth#check_level y manage#check_level

En cada uno de esas acciones adicionales que simplemente comparar stash->{ required_level } con session->{ required_level } ha configurado cuando se autorice usuario

package YourApp::Controller::Manage; 

sub check_level { 
    my $self = shift; 

    my $user_have = $self->session->{ required_level }; 
    my $we_require = $self->stash->{ required_level }; 
    # 'system#shutdown' will be called if user has required level 
    return 1 if $user_have >= $we_require; 


    $self->redirect_to('/you_have_no_access_rights'); 
    return 0; #This route will not match. 'system#shutdown' will not be called 
} 

PS Por supuesto me permite usar cb o simplemente CODEREF que se "cierra misma" al controlador de acción:

$r->under({ cb => \&YourApp::Controller::auth::check_level }); 
$r->under(\&YourApp::Controller::auth::check_level); # "same" 

Pero prefiero la sintaxis ->to('controller#action'). Se ve mucho mejor

0

¿Qué pasa si usamos este truco?

$r->add_condition(
     chain => sub { 
      my ($route, $controller, $captures, $conditions) = @_; 

      my $routes = $route; 
      while (not $routes->isa('Mojolicious::Routes')) { 
       $routes = $routes->parent; 
      } 

      for my $c (@$conditions) { 
       my $sub = $routes->conditions->{$c}; 
       return 0 unless $sub->($route, $controller, $captures); 
      } 

      return 1; 
     }, 
    ); 

    ... 
$r->get('/')->over(chain => ['condition1', 'condition2'])->to(cb => \&foo)->name('bar'); 
Cuestiones relacionadas