2012-08-09 27 views
6

我有以下代碼:如何將多個方法添加到多重路線的方法中?

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

鑑於路線我能得到通過認證檢查 即使用Mojolicious ::插件::驗證設置用戶路徑。

我想添加另一個'over'到該路線。

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

雖然這看起來會覆蓋已驗證的'over'。

我想分手的路線與名稱類似:

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

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

這並沒有在所有的工作雖然。 'over'都沒有被訪問。

我的路由類似於/ user,/ item,使用MojoX :: JSON :: RPC :: Service設置。 所以,我沒有像/ user /:id這樣的東西來設置子路由(不太確定) 所有路由都是/ user,通過參數發送。

我有像一個條件:

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

即在$ R- '訪問'>路線( '/用戶') - >過(存取=> 1);

總之,使用航線時,做工精細:

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

但我無法添加第二個途徑。

那麼,我在設置這些具有多個條件的路線時缺少什麼? 是否可以向單個路由/路由名稱添加多個條件?

+0

我注意到我在實施RBAC的同樣的事情。我希望獲得基於特權的訪問授權,以表現得像樹,這意味着鏈接。沒有解決。我想這就是爲什麼他們給了我們橋樑。 :) – DavidO 2012-08-17 03:40:03

+1

我的問題是,我有一個'add_condition'路由修飾符中的路由,如上面的代碼所示。所以,我無法與他們建立聯繫。我想我可以將這個條件作爲一個函數移動到一個模塊中,並使用一個橋。事實上,我把它放在了一個before_dispatch掛鉤中。 – jmcneirney 2012-08-17 17:17:48

回答

2

你可以只在本次測試使用over兩個條件,如:

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 

上的Perl 5.12.1做工精細這裏Mojolicious 3.38 - @DavidO是對的,也許橋可以更好地完成這項工作。:)

0

在我來說,我使用兩種方法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'); 

在這個例子中,當任何路由匹配一些under將被稱爲

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

您可以用指定action之前看您的controller將會運行另一個動作:auth#check_levelmanage#check_level

在每一個這些額外的動作,你只是比較stash->{ required_level }session->{ required_level }您設置當授權用戶

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我當然可以使用cb或只是CODEREF被「關閉同」到控制器的動作:

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

但我更喜歡->to('controller#action')語法。它看起來好多了

0

如果我們使用這個黑客怎麼辦?

$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'); 
相關問題