6fa764fb5b669366cdd559e28617013df22cb122
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Authentication / Store / Minimal.pm
1 package Catalyst::Authentication::Store::Minimal;
2
3 use strict;
4 use warnings;
5
6 use Catalyst::Authentication::User::Hash;
7 use Scalar::Util qw( blessed );
8 use base qw/Class::Accessor::Fast/;
9
10 BEGIN {
11     __PACKAGE__->mk_accessors(qw/userhash/);
12 }
13
14 sub new {
15     my ( $class, $config, $app, $realm) = @_;
16
17     bless { userhash => $config->{'users'} }, $class;
18 }
19
20 sub from_session {
21         my ( $self, $c, $id ) = @_;
22
23         return $id if ref $id;
24
25         $self->find_user( { id => $id } );
26 }
27
28 ## this is not necessarily a good example of what find_user can do, since all we do is   
29 ## look up with the id anyway.  find_user can be used to locate a user based on other 
30 ## combinations of data.  See C::P::Authentication::Store::DBIx::Class for a better example
31 sub find_user {
32     my ( $self, $userinfo, $c ) = @_;
33
34     my $id = $userinfo->{'id'};
35     
36     $id ||= $userinfo->{'username'};
37     
38     return unless exists $self->userhash->{$id};
39
40     my $user = $self->userhash->{$id};
41
42     #print STDERR "FOO1! " . ref($user) . " - ". Scalar::Util::blessed($user) . "\n";
43
44     if ( ref($user) eq "HASH") {
45         $user->{id} ||= $id;
46         return bless $user, "Catalyst::Authentication::User::Hash";
47     } elsif ( ref($user) && blessed($user) && $user->isa('Catalyst::Authentication::User::Hash')) {
48         return $user;
49     } else {
50         Catalyst::Exception->throw( "The user '$id' must be a hash reference or an " .
51                 "object of class Catalyst::Authentication::User::Hash");
52     }
53     return $user;
54 }
55
56 sub user_supports {
57     my $self = shift;
58
59     # choose a random user
60     scalar keys %{ $self->userhash };
61     ( undef, my $user ) = each %{ $self->userhash };
62
63     $user->supports(@_);
64 }
65
66 ## Backwards compatibility
67 #
68 # This is a backwards compatible routine.  get_user is specifically for loading a user by it's unique id
69 # find_user is capable of doing the same by simply passing { id => $id }  
70 # no new code should be written using get_user as it is deprecated.
71 sub get_user {
72     my ( $self, $id ) = @_;
73     $self->find_user({id => $id});
74 }
75
76 ## backwards compatibility
77 sub setup {
78     my $c = shift;
79
80     ### If a user does 'use Catalyst qw/Authentication::Store::Minimal/'
81     ### he will be proxied on to this setup routine (and only then --
82     ### non plugins should NOT have their setup routine invoked!)
83     ### Beware what we pass to the 'new' routine; it wants
84     ### a config has with a top level key 'users'. New style
85     ### configs do not have this, and split by realms. If we
86     ### blindly pass this to new, we will 1) overwrite what we
87     ### already passed and 2) make ->userhash undefined, which
88     ### leads to:
89     ###  Can't use an undefined value as a HASH reference at
90     ###  lib/Catalyst/Authentication/Store/Minimal.pm line 38.
91     ###
92     ### So only do this compatibility call if:
93     ### 1) we have a {users} config directive 
94     ###
95     ### Ideally we could also check for:
96     ### 2) we don't already have a ->userhash
97     ### however, that's an attribute of an object we can't 
98     ### access =/ --kane
99     
100     my $cfg = $c->config->{'Plugin::Authentication'}->{users}
101                 ? $c->config->{'Plugin::Authentication'}
102                 : undef;
103
104     $c->default_auth_store( __PACKAGE__->new( $cfg, $c ) ) if $cfg;
105     
106         $c->NEXT::setup(@_);
107 }
108
109 __PACKAGE__;
110
111 __END__
112
113 =pod
114
115 =head1 NAME
116
117 Catalyst::Authentication::Store::Minimal - Minimal authentication store
118
119 =head1 SYNOPSIS
120
121     # you probably just want Store::Minimal under most cases,
122     # but if you insist you can instantiate your own store:
123
124     use Catalyst::Authentication::Store::Minimal;
125
126     use Catalyst qw/
127         Authentication
128     /;
129
130     __PACKAGE__->config->{'Plugin::Authentication'} = 
131                     {  
132                         default_realm => 'members',
133                         realms => {
134                             members => {
135                                 credential => {
136                                     class => 'Password',
137                                     password_field => 'password',
138                                     password_type => 'clear'
139                                 },
140                                 store => {
141                                     class => 'Minimal',
142                                         users = {
143                                             bob => {
144                                                 password => "s00p3r",                                       
145                                                 editor => 'yes',
146                                                 roles => [qw/edit delete/],
147                                             },
148                                             william => {
149                                                 password => "s3cr3t",
150                                                 roles => [qw/comment/],
151                                             }
152                                         }                       
153                                     }
154                                 }
155                         }
156                     };
157
158     
159 =head1 DESCRIPTION
160
161 This authentication store lets you create a very quick and dirty user
162 database in your application's config hash.
163
164 You will need to include the Authentication plugin, and at least one Credential
165 plugin to use this Store. Credential::Password is reccommended.
166
167 It's purpose is mainly for testing, and it should probably be replaced by a
168 more "serious" store for production.
169
170 The hash in the config, as well as the user objects/hashes are freely mutable
171 at runtime.
172
173 =head1 CONFIGURATION
174
175 =over 4
176
177 =item class 
178
179 The classname used for the store. This is part of
180 L<Catalyst::Plugin::Authentication> and is the method by which
181 Catalyst::Authentication::Store::Minimal is loaded as the
182 user store. For this module to be used, this must be set to
183 'Minimal'.
184
185 =item users
186
187 This is a simple hash of users, the keys are the usenames, and the values are
188 hashrefs containing a password key/value pair, and optionally, a roles/list 
189 of role-names pair. If using roles, you will also need to add the 
190 Authorization::Roles plugin.
191
192 See the SYNOPSIS for an example.
193
194 =back
195
196 =head1 METHODS
197
198 There are no publicly exported routines in the Minimal store (or indeed in
199 most authentication stores)  However, below is a description of the routines 
200 required by L<Catalyst::Plugin::Authentication> for all authentication stores.
201
202 =head2 new( $config, $app, $realm )
203
204 Constructs a new store object, which uses the user element of the supplied config 
205 hash ref as it's backing structure.
206
207 =head2 find_user( $authinfo, $c ) 
208
209 Keys the hash by the 'id' or 'username' element in the authinfo hash and returns the user.
210
211 ... documentation fairy stopped here. ...
212
213 If the return value is unblessed it will be blessed as
214 L<Catalyst::Authentication::User::Hash>.
215
216 =head2 from_session( $id )
217
218 Delegates to C<get_user>.
219
220 =head2 user_supports( )
221
222 Chooses a random user from the hash and delegates to it.
223
224 =head2 get_user( )
225
226 =head2 setup( )
227
228 =cut
229
230