Changing module naming from Catalyst::Plugin::Authentication to
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Plugin / Authentication / Realm.pm
CommitLineData
810966b5 1package Catalyst::Plugin::Authentication::Realm;
2
3use strict;
4use warnings;
2c7d23af 5
810966b5 6use base qw/Class::Accessor::Fast/;
7
8BEGIN {
9 __PACKAGE__->mk_accessors(qw/store credential name config/);
10};
11
12sub new {
13 my ($class, $realmname, $config, $app) = @_;
14
15 my $self = { config => $config };
16 bless $self, $class;
17
18 $self->name($realmname);
19
20 $app->log->debug("Setting up auth realm $realmname") if $app->debug;
8513d51b 21
22 # use the Null store as a default
23 if( ! exists $config->{store}{class} ) {
0f673ca7 24 $config->{store}{class} = '+Catalyst::Authentication::Store::Null';
8513d51b 25 $app->log->debug( qq(No Store specified for realm "$realmname", using the Null store.) );
810966b5 26 }
810966b5 27 my $storeclass = $config->{'store'}{'class'};
28
29 ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
30 ## taken to mean C::P::A::Store::(specifiedclass)
31 if ($storeclass !~ /^\+(.*)$/ ) {
0f673ca7 32 $storeclass = "Catalyst::Authentication::Store::${storeclass}";
810966b5 33 } else {
34 $storeclass = $1;
35 }
810966b5 36
37 # a little niceness - since most systems seem to use the password credential class,
38 # if no credential class is specified we use password.
0f673ca7 39 $config->{credential}{class} ||= '+Catalyst::Authentication::Credential::Password';
810966b5 40
41 my $credentialclass = $config->{'credential'}{'class'};
42
43 ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
0f673ca7 44 ## taken to mean C::A::Credential::(specifiedclass)
810966b5 45 if ($credentialclass !~ /^\+(.*)$/ ) {
0f673ca7 46 $credentialclass = "Catalyst::Authentication::Credential::${credentialclass}";
810966b5 47 } else {
48 $credentialclass = $1;
49 }
50
0f673ca7 51 # if we made it here - we have what we need to load the classes
52
53 ### BACKWARDS COMPATIBILITY - DEPRECATION WARNING:
54 ### we must eval the ensure_class_loaded - because we might need to try the old-style
55 ### ::Plugin:: module naming if the standard method fails.
56
57 eval {
58 Catalyst::Utils::ensure_class_loaded( $credentialclass );
59 };
60
61 if ($@) {
62 $app->log->warn( qq(Credential class "$credentialclass" not found, trying deprecated ::Plugin:: style naming. ) );
63 $credentialclass =~ s/Catalyst::Authentication/Catalyst::Plugin::Authentication/;
64 Catalyst::Utils::ensure_class_loaded( $credentialclass );
65 }
66
67 eval {
68 Catalyst::Utils::ensure_class_loaded( $storeclass );
69 };
70
71 if ($@) {
72 $app->log->warn( qq(Store class "$storeclass" not found, trying deprecated ::Plugin:: style naming. ) );
73 $storeclass =~ s/Catalyst::Authentication/Catalyst::Plugin::Authentication/;
74 Catalyst::Utils::ensure_class_loaded( $storeclass );
75 }
810966b5 76
77 # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms
78 # of get_user and add it to the class. this is because the auth routines use find_user,
79 # and rely on it being present. (this avoids per-call checks)
80 if (!$storeclass->can('find_user')) {
81 no strict 'refs';
82 *{"${storeclass}::find_user"} = sub {
83 my ($self, $info) = @_;
84 my @rest = @{$info->{rest}} if exists($info->{rest});
85 $self->get_user($info->{id}, @rest);
86 };
87 }
88
89 ## a little cruft to stay compatible with some poorly written stores / credentials
90 ## we'll remove this soon.
91 if ($storeclass->can('new')) {
92 $self->store($storeclass->new($config->{'store'}, $app, $self));
93 } else {
94 $app->log->error("THIS IS DEPRECATED: $storeclass has no new() method - Attempting to use uninstantiated");
95 $self->store($storeclass);
96 }
97 if ($credentialclass->can('new')) {
98 $self->credential($credentialclass->new($config->{'credential'}, $app, $self));
99 } else {
100 $app->log->error("THIS IS DEPRECATED: $credentialclass has no new() method - Attempting to use uninstantiated");
101 $self->credential($credentialclass);
102 }
103
104 return $self;
105}
106
107sub find_user {
108 my ( $self, $authinfo, $c ) = @_;
109
110 my $res = $self->store->find_user($authinfo, $c);
111
4437366d 112 if (!$res) {
9b840849 113 if ($self->config->{'auto_create_user'} && $self->store->can('auto_create_user') ) {
114 $res = $self->store->auto_create_user($authinfo, $c);
4437366d 115 }
9b840849 116 } elsif ($self->config->{'auto_update_user'} && $self->store->can('auto_update_user')) {
117 $res = $self->store->auto_update_user($authinfo, $c, $res);
4437366d 118 }
810966b5 119
120 return $res;
121}
122
123sub authenticate {
124 my ($self, $c, $authinfo) = @_;
125
126 my $user = $self->credential->authenticate($c, $self, $authinfo);
127 if (ref($user)) {
128 $c->set_authenticated($user, $self->name);
129 return $user;
130 } else {
131 return undef;
132 }
133}
134
135sub save_user_in_session {
136 my ( $self, $c, $user ) = @_;
137
138 $c->session->{__user_realm} = $self->name;
139
140 # we want to ask the store for a user prepared for the session.
141 # but older modules split this functionality between the user and the
142 # store. We try the store first. If not, we use the old method.
143 if ($self->store->can('for_session')) {
144 $c->session->{__user} = $self->store->for_session($c, $user);
145 } else {
146 $c->session->{__user} = $user->for_session;
147 }
148}
149
150sub from_session {
151 my ($self, $c, $frozen_user) = @_;
152
153 return $self->store->from_session($c, $frozen_user);
154}
155
156
157__PACKAGE__;
158
b72f8c2e 159__END__
2c7d23af 160
161=pod
162
163=head1 NAME
164
165Catalyst::Plugin::Authentication::Realm - Base class for realm objects.
166
167=head1 DESCRIPTION
168
d2ca09b8 169=head1 CONFIGURATION
2c7d23af 170
171=over 4
172
d2ca09b8 173=item class
174
deebc899 175By default this class is the default realm class. You can specify a custom
176realm class with this config parameter.
177
d2ca09b8 178=item auto_create_user
2c7d23af 179
deebc899 180Set this to true if you wish this realm to auto-create user accounts when the
181user doesn't exist (most useful for remote authentication schemes).
182
d2ca09b8 183=item auto_update_user
2c7d23af 184
deebc899 185Set this to true if you wish this realm to auto-update user accounts after
186authentication (most useful for remote authentication schemes).
187
d2ca09b8 188=back
189
190=head1 METHODS
2c7d23af 191
d2ca09b8 192=head2 new( )
2c7d23af 193
deebc899 194Instantiantes this realm, plus the specified store and credential classes.
195
196=head2 store( )
197
198Holds an instance of the store object for this realm.
199
200=head2 credential( )
201
202Holds an instance of the credential object for this realm.
203
d2ca09b8 204=head2 find_user( )
205
deebc899 206Delegates to the store object. Will also re-delegate auto_create_user and
207auto_update_user at this time, if necessary.
208
d2ca09b8 209=head2 authenticate( )
210
deebc899 211Delegates to the credential objects and sets the authenticated user on success.
212
d2ca09b8 213=head2 save_user_in_session( )
214
deebc899 215Delegates to the store object.
216
d2ca09b8 217=head2 from_session( )
2c7d23af 218
deebc899 219Delegates to the store object.
220
2c7d23af 221=cut
222