Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 4 commits
  • 3 files changed
  • 0 comments
  • 1 contributor
Feb 27, 2012
Ed Wildgoose Change ugly API 0978f07
Ed Wildgoose Add some comments aa0712f
Ed Wildgoose The lazy parameter is changed to autoload_user to become a simple hoo…
…k which autoloads the user into the stash for us

Also introduce a function to force reloading of the user object
c7e31f5
Ed Wildgoose Introduce a current_user function - dramatically simplifies code and …
…almost everything else can be implemented using it.

Rename the "user" function and stash to "current_user" in line with other auth modules (!BREAKS COMPATIBILITY!).
Additionally rename user_exists to is_user_authenticated to better represent what it does.
97433d2
75  lib/Mojolicious/Plugin/Authentication.pm
@@ -11,58 +11,56 @@ sub register {
11 11
     die __PACKAGE__, ": missing 'validate_user' subroutine ref in parameters\n"
12 12
         unless $args->{validate_user} && ref($args->{validate_user}) eq 'CODE';
13 13
 
14  
-    my $lazy_mode         = $args->{lazy_mode}   || 0;
  14
+    my $autoload_user    = defined($args->{autoload_user}) ? $args->{autoload_user} : 1;
15 15
     my $session_key       = $args->{session_key} || 'auth_data';
16 16
     my $our_stash_key     = $args->{stash_key}   || '__authentication__';
17 17
     my $load_user_cb      = $args->{load_user};
18 18
     my $validate_user_cb  = $args->{validate_user};
19 19
 
  20
+    # Unconditionally load the user based on uid in session
20 21
     my $user_loader_sub = sub {
21 22
         my $c = shift;
22 23
 
23 24
         if (my $uid = $c->session($session_key)) {
24 25
             my $user = $load_user_cb->($c, $uid);
25 26
             if ($user) {
26  
-                $c->stash($our_stash_key => { user => $user });
  27
+                $c->stash($our_stash_key => { current_user => $user });
27 28
             }
28  
-            elsif ($lazy_mode) {
  29
+            else {
  30
+                # cache result that user does not exist
29 31
                 $c->stash($our_stash_key => { no_user => 1 });
30 32
             }
31 33
         }
32 34
     };
33 35
 
  36
+    # Fetch the current user object from the stash - loading it if not already loaded
34 37
     my $user_stash_extractor_sub = sub {
35 38
         my $c = shift;
36  
-        my $is_return_binary = shift || 0;
37 39
 
38  
-        if (
39  
-            $lazy_mode
40  
-            && !(
  40
+        if ( !(
41 41
                 defined($c->stash($our_stash_key))
42 42
                 && ($c->stash($our_stash_key)->{no_user}
43  
-                    || defined($c->stash($our_stash_key)->{user}))
  43
+                    || defined($c->stash($our_stash_key)->{current_user}))
  44
+              )
44 45
             )
45  
-          )
46 46
         {
47 47
             $user_loader_sub->($c);
48 48
         }
49 49
 
50 50
         my $user_def = defined($c->stash($our_stash_key))
51  
-                          && defined($c->stash($our_stash_key)->{user});
  51
+                          && defined($c->stash($our_stash_key)->{current_user});
52 52
 
53  
-        return $is_return_binary
54  
-          ? ($user_def ? 1 : 0)
55  
-          : ($user_def ? $c->stash($our_stash_key)->{user} : undef);
  53
+        return $user_def ? $c->stash($our_stash_key)->{current_user} : undef;
56 54
 
57 55
     };
58 56
 
59  
-    if (!$lazy_mode) {
  57
+    if ($autoload_user) {
60 58
         $app->hook(before_dispatch => $user_loader_sub);
61 59
     }
62 60
 
63 61
     $app->routes->add_condition(authenticated => sub {
64 62
         my ($r, $c, $captures, $required) = @_;
65  
-        return ($required && $c->user_exists) ? 1 : 0;
  63
+        return ($required && $c->is_user_authenticated) ? 1 : 0;
66 64
     });
67 65
 
68 66
     $app->routes->add_condition(signed => sub {
@@ -70,21 +68,31 @@ sub register {
70 68
         return ($required && $c->signature_exists) ? 1 : 0;
71 69
     });
72 70
 
73  
-    $app->helper(signature_exists => sub {
  71
+    my $current_user = sub {
74 72
         my $c = shift;
75  
-        return $c->session($session_key) ? 1 : 0;
  73
+        return $user_stash_extractor_sub->($c);
  74
+    };
  75
+
  76
+    $app->helper(reload_user => sub {
  77
+        my $c = shift;
  78
+        # Clear stash to force a reload of the user object
  79
+        delete $c->stash->{$our_stash_key};
  80
+        return $current_user->($c);
76 81
     });
77 82
 
78  
-    $app->helper(user_exists => sub {
  83
+    $app->helper(signature_exists => sub {
79 84
         my $c = shift;
80  
-        return $user_stash_extractor_sub->($c, 1);
  85
+        return $c->session($session_key) ? 1 : 0;
81 86
     });
82 87
 
83  
-    $app->helper(user => sub {
  88
+
  89
+    $app->helper(is_user_authenticated => sub {
84 90
         my $c = shift;
85  
-        return $user_stash_extractor_sub->($c);
  91
+        return defined($current_user->($c)) ? 1 : 0;
86 92
     });
87 93
 
  94
+    $app->helper(current_user => $current_user);
  95
+
88 96
     $app->helper(logout => sub {
89 97
         my $c = shift;
90 98
         delete $c->stash->{$our_stash_key};
@@ -95,8 +103,11 @@ sub register {
95 103
         my ($c, $user, $pass, $extradata) = @_;
96 104
         if (my $uid = $validate_user_cb->($c, $user, $pass, $extradata)) {
97 105
             $c->session($session_key => $uid);
98  
-            $c->stash->{$our_stash_key}->{user} = $load_user_cb->($c, $uid);
99  
-            return 1;
  106
+            # Clear stash to force reload of any already loaded user object
  107
+            delete $c->stash->{$our_stash_key};
  108
+            return 1 if defined( $current_user->($c) );
  109
+            # Failed to load user object. Perhaps some kind of race condition or other error?
  110
+            return;
100 111
         }
101 112
         return;
102 113
     });
@@ -113,7 +124,7 @@ Mojolicious::Plugin::Authentication - A plugin to make authentication a bit easi
113 124
     use Mojolicious::Plugin::Authentication
114 125
 
115 126
     $self->plugin('authentication' => {
116  
-        'lazy_mode' => 1,
  127
+        'autoload_user' => 1,
117 128
         'session_key' => 'wickedapp',
118 129
         'load_user' => sub { ... },
119 130
         'validate_user' => sub { ... },
@@ -130,14 +141,18 @@ Mojolicious::Plugin::Authentication - A plugin to make authentication a bit easi
130 141
 
131 142
 Authenticate will use the supplied C<load_user> and C<validate_user> subroutine refs to see whether a user exists with the given username and password, and will set up the session accordingly.  Returns true when the user has been successfully authenticated, false otherwise. You can pass additional data along in the extra_data hashref, it will be passed to your C<validate_user> subroutine as-is.
132 143
 
133  
-=head2 user_exists
  144
+=head2 is_user_authenticated
134 145
 
135  
-Returns true if an authenticated user exists, false otherwise.
  146
+Returns true if current_user() returns some valid object, false otherwise.
136 147
 
137  
-=head2 user
  148
+=head2 current_user
138 149
 
139 150
 Returns the user object as it was returned from the supplied C<load_user> subroutine ref.
140 151
 
  152
+=head2 reload_user
  153
+
  154
+Flushes the current user object and then returns user().
  155
+
141 156
 =head2 signature_exists
142 157
 
143 158
 Returns true if uid signature exist on the client side (in cookies), false otherwise.
@@ -160,7 +175,7 @@ The following options can be set for the plugin:
160 175
 
161 176
 =item session_key (optional) The name of the session key
162 177
 
163  
-=item lazy_mode (optional) Turn on 'lazy mode' - user data to be loaded only if it be used. May reduce site latency in some cases.
  178
+=item autoload_user (optional) Turn on/off automatic loading of user data - user data can be loaded only if it be used. May reduce site latency in some cases.
164 179
 
165 180
 =back 
166 181
 
@@ -222,7 +237,7 @@ If you want to be able to send people to a login page, you will have to use the
222 237
     my $members_only = $r->route('/members')->to(cb => sub {
223 238
         my $self = shift;
224 239
 
225  
-        $self->redirect_to('/login') and return 0 unless($self->user_exists);
  240
+        $self->redirect_to('/login') and return 0 unless($self->is_user_authenticated);
226 241
         return 1;
227 242
     });
228 243
 
@@ -250,7 +265,7 @@ And in your Auth controller you would put:
250 265
 
251 266
     sub check {
252 267
         my $self = shift;
253  
-        $self->redirect_to('/login') and return 0 unless($self->user_exists);
  268
+        $self->redirect_to('/login') and return 0 unless($self->is_user_authenticated);
254 269
         return 1;
255 270
     });
256 271
 
3  t/01-functional.t
@@ -13,6 +13,7 @@ use Mojolicious::Lite;
13 13
 use Test::Mojo;
14 14
 
15 15
 plugin 'authentication', {
  16
+    autoload_user => 1,
16 17
     load_user => sub {
17 18
         my $self = shift;
18 19
         my $uid  = shift;
@@ -59,7 +60,7 @@ post '/login2' => sub {
59 60
 
60 61
 get '/authonly' => sub {
61 62
     my $self = shift;
62  
-    $self->render(text => ($self->user_exists) ? 'authenticated' : 'not authenticated');
  63
+    $self->render(text => ($self->is_user_authenticated) ? 'authenticated' : 'not authenticated');
63 64
 };
64 65
 
65 66
 get '/condition/authonly' => (authenticated => 1) => sub {
4  t/02-functional_lazy.t
@@ -13,7 +13,7 @@ use Mojolicious::Lite;
13 13
 use Test::Mojo;
14 14
 
15 15
 plugin 'authentication', {
16  
-    lazy_mode => 1,
  16
+    autoload_user => 0,
17 17
     load_user => sub {
18 18
         my $self = shift;
19 19
         my $uid  = shift;
@@ -53,7 +53,7 @@ post '/login' => sub {
53 53
 
54 54
 get '/authonly' => sub {
55 55
     my $self = shift;
56  
-    $self->render( text => ( $self->user_exists )
  56
+    $self->render( text => ( $self->is_user_authenticated )
57 57
         ? 'authenticated'
58 58
         : 'not authenticated' );
59 59
 };

No commit comments for this range

Something went wrong with that request. Please try again.