2012-08-09 9 views
6

Ich habe den folgenden Code:Wie füge ich mehr als eine Übermethode zu einer mojolicious Route hinzu?

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

diesen Weg Da ich an den Benutzer Weg bekommen durch den authentifizierten Check vorbei , dass das Setup Mojolicious Verwendung ist :: Plugin :: Authentifizierung.

Ich möchte ein weiteres "over" zu dieser Route hinzufügen.

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

Das scheint jedoch "über" authentifiziert überschreiben.

Ich habe versucht, die Routen mit Namen wie Zerschlagung:

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

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

Das ist nicht überhaupt obwohl nicht funktioniert. Keines der "Over" wird erreicht.

Meine Routen sind Dinge wie/user,/item, eingerichtet mit MojoX :: JSON :: RPC :: Service. So, ich habe keine Dinge wie/user /: ID, um Unterrouten einzurichten. (Nicht sicher, dass das wichtig ist) Alle Routen sind wie/Benutzer, mit Parametern gesendet.

Ich habe eine Bedingung wie bekommt:

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

, dass der 'Zugang' in $ r-> Route ('/ user') ist -> über (access => 1);

Kurz gesagt, die Routen gut funktionieren bei der Verwendung von:

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

Aber ich bin nicht in der Lage eine zweite Route hinzufügen.

Also, was fehlt mir bei der Einrichtung dieser Routen mit mehreren Bedingungen? Können mehrere Bedingungen zu einer einzelnen Route/route_name hinzugefügt werden?

+0

Ich habe die gleiche Sache bemerkt, wo ich RBAC implementierte. Ich wollte Zugriffsberechtigungen basierend auf Privilegien, um sich wie ein Baum zu verhalten, was Verkettungen bedeuten würde. Hat nicht geklappt. Ich denke, deshalb haben sie uns Brücken gegeben. :) – DavidO

+1

Mein Problem war, dass ich die Route in einem 'add_condition' Routenmodifikator habe, wie in meinem Code oben gezeigt. Also konnte ich nicht mit ihnen reden. Ich denke, ich könnte die Bedingung als Funktion in ein Modul verschieben und eine Brücke benutzen. So wie es ist, habe ich es in einen before_dispatch hook gesetzt. – jmcneirney

Antwort

2

Sie können nur beide Bedingungen in over wie in diesem Test verwenden:

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 

Werke hier gut mit Mojolicious 3,38 auf Perl 5.12.1 - @DavidO richtig ist, vielleicht können Brücken besser die Arbeit machen.:)

0

In meinem Fall verwende ich zwei under Methoden:

$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'); 

In diesem Beispiel, wenn eine der Routen einige under übereinstimmen

'/' -> 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' 

genannt werden, wie Sie vor dem Ziel sehen action in Ihre controller wird eine andere Aktion ausgeführt werden: auth#check_level und manage#check_level

In jedem dieser zusätzlichen Aktionen vergleichen Sie nur stash->{ required_level } mit session->{ required_level } Sie haben, wenn eine Autorisierung gesetzt Benutzer

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 Natürlich kann ich cb oder nur CODEREF verwenden, die „schließen same“ werden Maßnahmen zur Steuerung:

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

Aber ich bevorzuge ->to('controller#action') Syntax. Es sieht viel besser aus

0

Was ist, wenn wir diesen Hack verwenden?

$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'); 
Verwandte Themen