如何在Mojolicous中使用`find`获取完整路径?

时间:2016-12-01 14:35:32

标签: perl mojolicious

我有注册REST路由的快捷方式,例如Mojolicious::Plugin::RESTRoutes

my $r = $self->routes;
$r->add_shortcut( resource =>  \&resource );

我还有一些under路由来检查用户访问级别:

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 } );

当我创建资源时:

my $uResource =  $user->resource( 'users' );

我接下来的路线:

$ myapp.pl routes
/               *                 # under for guest
/               *                 # under for user
  +/users       *       users
    +/          GET     "list_users"
    +/create    GET     "create_user"
    +/          POST    "store_user"
    +/:id       GET     "show_user"
    +/:id/edit  GET     "edit_user"
    +/:id       PUT     "update_user"
    +/:id       DELETE  "delete_user"
/               *                       # under for admin

不,我想调整其中一些来限制访问:

$guest->add_child( $user->find( 'create_user' ) );
$admin->add_child( $user->find( 'list_users'  ) );
$admin->add_child( $user->find( 'delete_user' ) );

现在我得到了这条路线:

$ myapp.pl routes
/               *                        # under for guest
  +/create      GET     "create_user"
/               *                        # under for user
  +/users       *       users
    +/          POST    "store_user"
    +/:id       GET     "show_user"
    +/:id/edit  GET     "edit_user"
    +/:id       PUT     "update_user"
/               *                        # under for admin
  +/            GET     "list_users"    
  +/:id         DELETE  "delete_user"

正如您所看到的,只有路线的最后部分已从user移至guest / admin
因为我在这里使用$user而不是$uResource 我希望路线+/users也匹配

$ myapp.pl routes
/               *                        # under for guest
  +/users       *       users
    +/create    GET     "create_user"
/               *                        # under for user
  +/users       *       users
    +/          POST    "store_user"
    +/:id       GET     "show_user"
    +/:id/edit  GET     "edit_user"
    +/:id       PUT     "update_user"
/               *                        # under for admin
  +/users       *       users
    +/          GET     "list_users"    
    +/:id       DELETE  "delete_user"

这完全如下:

$guest->any( "/users" )->add_child( $user->find( 'create_user' ) );
$admin->any( "/users" )->add_child( $user->find( 'list_users'  ) );
$admin->any( "/users" )->add_child( $user->find( 'delete_user' ) );

有没有办法自动添加/users

1 个答案:

答案 0 :(得分:0)

我只是创建了不同的快捷方式。消息来源:

my $r = $self->routes;
$r->add_shortcut( resource   =>  \&resource   );
$r->add_shortcut( privileged =>  \&privileged );


# Each time someone make query we setup cookie and check his access level
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 } );

$user->privileged( 'users',  CS => $guest,  LD => $admin );


sub privileged {
    my( $r, $name, %restriction ) =  @_;
    my $singular =  Lingua::EN::Inflect::PL( $name );

    # Prefix for resource
    $r =  $r->any( "/$name" )->to( "$singular#" );

    my %api =  (()
        # Order definition has not matter each part of resource has unique path
        # type       #method       #path        #action    #route name
        ,L =>  [ $r, [ "GET"    ], "/",         '#index',  "list_$name"       ]
        ,C =>  [ $r, [ "GET"    ], '/create',   '#create', "create_$singular" ]
        ,S =>  [ $r, [ "POST"   ], '/',         '#store',  "store_$singular"  ]
        ,R =>  [ $r, [ "GET"    ], '/:id',      '#show',   "show_$singular"   ]
        ,E =>  [ $r, [ "GET"    ], '/:id/edit', '#edit',   "edit_$singular"   ]
        ,U =>  [ $r, [ "PUT"    ], '/:id',      '#update', "update_$singular" ]
        ,D =>  [ $r, [ "DELETE" ], '/:id',      '#delete', "delete_$singular" ]
    );

    # CS => $guest,  REU => $user,  LD => $admin  translated into:
    # $api{ C => [ $guest ...],  S => [ $guest ... ], ..., D => [ $admin ... ] }
    for my $level ( keys %restriction ) {
        # Prefix for resource
        my $r =  $restriction{ $level }->any( "/$name" )->to( "$singular#" );

        for my $resource ( split //, $level ) {
            $api{ $resource }[0] =  $r;
        }
    }


    # Create route for all resouces: LCSREUD
    for my $resource ( keys %api ) {
        my( $guard, $method, $path, $action, $rname ) =  @{ $api{ $resource } };
        $guard->any( $method, $path, $rname )->to( $action );
    }


    return;
}

有什么建议吗?