add persist_in_session config option
Alexander Hartmaier [Tue, 24 Nov 2015 13:38:44 +0000 (14:38 +0100)]
to allow storing of user and its roles in the session without hitting the LDAP
store on each request

sorry, no tests yet!

Changes
README
lib/Catalyst/Authentication/Store/LDAP.pm
lib/Catalyst/Authentication/Store/LDAP/Backend.pm
lib/Catalyst/Authentication/Store/LDAP/User.pm

diff --git a/Changes b/Changes
index 693f9af..8d7d47e 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,4 +1,6 @@
   - Document how to limit the attributes returned from the LDAP search
+  - Add persist_in_session config option to allow storing of user and its
+    roles in the session without hitting the LDAP store on each request
 
 1.015 20 February 2015
   - Escape special characters in user/role names
diff --git a/README b/README
index d72cb63..ca4dbf3 100644 (file)
--- a/README
+++ b/README
@@ -43,6 +43,7 @@ SYNOPSIS
                      attrs => [qw( distinguishedname name mail )],
                    },
                    user_results_filter => sub { return shift->pop_entry },
+                   persist_in_session  => 'all',
                  },
                },
              },
@@ -273,6 +274,21 @@ CONFIGURATION OPTIONS
     *bindpw* fields. If this is set to false, then the role search will
     instead be performed when bound as the user you authenticated as.
 
+  persist_in_session
+    Can take one of the following values, defaults to undefined:
+
+   undefined
+    Only store the username in the session and lookup the user and its roles
+    on every request. That was how the module worked until version 1.015 and
+    is also the default for backwards compatibility.
+
+   all
+    Store the user object and its roles in the session and never look it up
+    in the store after login.
+
+    NOTE: It's recommended to limit the user attributes fetched from LDAP
+    using user_search_options / attrs to not exhaust the session store..
+
   entry_class
     The name of the class of LDAP entries returned. This class should exist
     and is expected to be a subclass of Net::LDAP::Entry
index 275e763..3c74e47 100644 (file)
@@ -66,6 +66,7 @@ Catalyst::Authentication::Store::LDAP
                  attrs => [qw( distinguishedname name mail )],
                },
                user_results_filter => sub { return shift->pop_entry },
+               persist_in_session  => 'all',
              },
            },
          },
@@ -313,6 +314,24 @@ by binding to the directory with the details in the I<binddn> and I<bindpw>
 fields. If this is set to false, then the role search will instead be
 performed when bound as the user you authenticated as.
 
+=head2 persist_in_session
+
+Can take one of the following values, defaults to undefined:
+
+=head3 undefined
+
+Only store the username in the session and lookup the user and its roles
+on every request. That was how the module worked until version 1.015 and is
+also the default for backwards compatibility.
+
+=head3 all
+
+Store the user object and its roles in the session and never look it up in
+the store after login.
+
+B<NOTE:> It's recommended to limit the user attributes fetched from LDAP
+using L<user_search_options> / attrs to not exhaust the session store..
+
 =head2 entry_class
 
 The name of the class of LDAP entries returned. This class should
index 7da9dd6..e23c77f 100644 (file)
@@ -50,6 +50,7 @@ Catalyst::Authentication::Store::LDAP::Backend
                 'deref' => 'always',
             },
             'role_search_as_user' => 0,
+            'persist_in_session'  => 'all',
     );
 
     our $users = Catalyst::Authentication::Store::LDAP::Backend->new(\%config);
@@ -88,6 +89,7 @@ BEGIN {
             role_filter role_scope role_field role_value
             role_search_options start_tls start_tls_options
             user_results_filter user_class role_search_as_user
+            persist_in_session
             )
     );
 }
@@ -450,8 +452,13 @@ Returns get_user() for I<id>.
 =cut
 
 sub from_session {
-    my ( $self, $c, $id ) = @_;
-    $self->get_user( $id, $c );
+    my ( $self, $c, $frozenuser ) = @_;
+
+    if ( $self->persist_in_session eq 'all' ) {
+        return $self->user_class->new( $self, $frozenuser->{user}, $c, $frozenuser->{_roles} );
+    }
+
+    return $self->get_user( $frozenuser, $c );
 }
 
 1;
index 1451c64..79c4f37 100644 (file)
@@ -74,11 +74,11 @@ Returns a L<Catalyst::Authentication::Store::LDAP::User> object.
 =cut
 
 sub new {
-    my ( $class, $store, $user, $c ) = @_;
+    my ( $class, $store, $user, $c, $roles ) = @_;
 
     return unless $user;
 
-    bless { store => $store, user => $user, }, $class;
+    bless { store => $store, user => $user, _roles => $roles }, $class;
 }
 
 =head2 id
@@ -164,12 +164,19 @@ sub roles {
 
 =head2 for_session
 
-Returns the User object, stringified.
+Returns the user for persistence in the session depending on the
+persist_in_session config option.
 
 =cut
 
 sub for_session {
     my $self = shift;
+
+    if ( $self->store->persist_in_session eq 'all' ) {
+        # use the roles accessor to ensure the roles are fetched
+        return { user => $self->user, _roles => [ $self->roles ] };
+    }
+
     return $self->stringify;
 }