[dancer-users] 2018 Dancer Advent Calendar

John Stoffel john at stoffel.org
Mon Oct 15 03:42:03 BST 2018


Johannes,
Thanks for posting this, now I hate to be a jerk, but some comments
inside it would be helpful.  You know Dancer much better than I do,
and what's obvious to you, isn't to those of us who don't use it all
the time.

For example, the 'if (ref $Roles eq '') { ... }' could use some
explanation in the code if possible.



Johannes> Somehing like that?
Johannes> ------------------- cut here -------------------------
Johannes> # ------------- 
Johannes> # Main MyFancyApp.pm
Johannes> # -------------
Johannes> use utf8;
Johannes> package MyFancyApp;
Johannes> use Dancer2;
Johannes> use Dancer2::Plugin::DBIC;
Johannes> use Dancer2::Plugin::Auth::Tiny;
Johannes> use Dancer2::Plugin::Deferred;
Johannes> use YAML;
Johannes> use Cache::Memcached;

Johannes> our $VERSION = '0.1';

Johannes> prefix undef;

Johannes> # ------------- 
Johannes> # Inside each controller that requires authentication 
Johannes> # (may be better in a Dancer::Plugin::Auth::Tiny::MySpecialAuthExtension?)
Johannes> # -------------
Johannes> Dancer2::Plugin::Auth::Tiny->extend(
Johannes>   role => sub {
Johannes>     my ($dsl, $Roles, $coderef) = @_;
Johannes>     if ( ref $Roles eq '' ) {
Johannes>         $Roles = [ $Roles ];
Johannes>     }
Johannes>     return sub {
Johannes>         my $SessionData = $dsl->app->session->read('User');
Johannes>         if ( grep { $SessionData->{'Roles'}->{$_} } @{$Roles} ) {
Johannes>             goto $coderef;
Johannes>         }
Johannes>         else {
Johannes>             $dsl->app->redirect('/auth/login');
Johannes>         }
Johannes>     };
Johannes>   }
Johannes> );

Johannes> # Paths start that way
Johannes> get '' => needs role => ['Root', 'Admin',  ] => sub {
Johannes> }
Johannes> # ---------------
Johannes> # Authentication part
Johannes> # ---------------

Johannes> use utf8;
Johannes> package MyFancyApp::Auth::Login;
Johannes> use Dancer2 appname => 'MyFancyApp';
Johannes> use Dancer2::Plugin::DBIC;
Johannes> use Dancer2::Plugin::Auth::Tiny;
Johannes> use Dancer2::Plugin::Deferred;
Johannes> use Dancer2::Plugin::Passphrase;

Johannes> prefix '/auth';

Johannes> post '/login' => sub {

Johannes>     my %Param = params;
Johannes>     my $Login = $Param{login};


Johannes>     # If the login doesn't contain a dot and characters before and after
Johannes>     # Login failed => display username unknown in class alert-warning and redirect to auto login again
Johannes>     if ( $Login !~ /(.+)\.(.+)/ ) {
Johannes>             deferred error => 'Username unknown.';
Johannes>             deferred class => 'alert-warning';
Johannes>             redirect '/auth/login';
Johannes>     };

Johannes>     my $Ident  = $1;
Johannes>     my $User = $2;

Johannes>     my $Password = $Param{password};
Johannes>     my $PasswordHashed = passphrase( 
Johannes>              $Password 
Johannes>          )->generate;

Johannes>     $RS = schema('default')->resultset('User')->search(
Johannes>         {
Johannes>             'company.ident' => $Ident,
Johannes>             'login'         => $User,
Johannes>             'password'      => $PasswordHashed,
Johannes>         },
Johannes>         {
Johannes>             join => 'company',
Johannes>         },
Johannes>     );

Johannes>     if ( ! $RS ) {
Johannes>             deferred error => 'Username or password incorect.';
Johannes>             deferred class => 'alert-warning';
Johannes>             redirect '/auth/login';
Johannes>     }

Johannes>     my $CompanyID = $RS->company->id;
Johannes>     my $UserID = $RS->id;
Johannes>     my %Roles;
Johannes>     for my $Role ( $RS->user_roles->all ) {
Johannes>         $Roles{$Role->role->name} = 1;
Johannes>     }
    
session-> write(
Johannes>         'User' , {
Johannes>             User      => $Login, 
Johannes>             Ident     => $Ident,
Johannes>             Login     => $User,
Johannes>             Roles     => \%Roles,
Johannes>             CompanyID => $CompanyID,
Johannes>             UserID    => $UserID,
Johannes>         },
Johannes>     );

Johannes>     my $SessionData = session->read('User');
    
Johannes>     return redirect params->{return_url} || '/';
Johannes> }; 

Johannes> post '/logout' => sub {

Johannes>     my %Param = params;
session-> delete('User');

Johannes>     deferred error => 'Logout successful.';
Johannes>     deferred class => 'alert-success';
  
Johannes>     return redirect  '/auth/login';
Johannes> }; 
Johannes> # ---------------
Johannes> # Config
Johannes> # ---------------
Johannes> # Inside config.yml
Johannes> session: Memcached
Johannes> engines:
Johannes>   session:
Johannes>     Memcached:
Johannes>       memcached_servers: 
Johannes>         - 127.0.0.1:11211
Johannes>         - /var/sock/memcached
Johannes> plugins:
Johannes>   Auth::Tiny:
Johannes>     login_route: /auth/login
Johannes> ------------------- cut here -------------------------
>> Am 11.10.2018 um 22:31 schrieb John Stoffel <john at stoffel.org>:
>> 
>> 
>> What I'd love to see if an example of CRUD with Authentication, in a
>> skeleton format so I can steal it for my own needs.  I'm too
>> dumb/busy/lazy to make it all work myself.  *grin*
>> _______________________________________________
>> dancer-users mailing list
>> dancer-users at dancer.pm
>> http://lists.preshweb.co.uk/mailman/listinfo/dancer-users

Johannes> _______________________________________________
Johannes> dancer-users mailing list
Johannes> dancer-users at dancer.pm
Johannes> http://lists.preshweb.co.uk/mailman/listinfo/dancer-users


More information about the dancer-users mailing list