6

次のコードがあります。

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

そのルートを考えると、Mojolicious::Plugin::Authentication を使用してセットアップされた認証済みチェックを通過するユーザー ルートに到達できます。

そのルートに別の「オーバー」を追加したい。

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

ただし、認証された「オーバー」をオーバーライドするようです。

次のような名前でルートを分割してみました。

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

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

しかし、それはまったく機能しませんでした。どちらのオーバーもアクセスされていません。

私のルートは、MojoX::JSON::RPC::Service を使用して設定された /user、/item などです。したがって、サブルートを設定するための /user/:id のようなものはありません。

次のような条件があります。

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

$r->route('/user')->over(access => 1); の 'access' です。

つまり、以下を使用すると、ルートは正常に機能します。

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

しかし、2 番目のルートを追加できません。

では、これらのルートを複数の条件で設定する際に何が欠けているのでしょうか? 単一のルート /route_name に複数の条件を追加することはできますか?

4

3 に答える 3

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 で問題なく動作します。:)

于 2012-09-05T15:17:43.473 に答える
0

私の場合、次の 2 つの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れます。controllerauth#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もちろん、コントローラーアクションと「ほぼ同じ」であるcborを使用することもできます:CODEREF

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

しかし、私は->to( 'controller#action' )構文を好みます。それははるかに良く見えます

于 2016-12-04T19:03:08.487 に答える