changes update plus some stub docs
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Plugin / Authentication / Realm.pm
1 package Catalyst::Plugin::Authentication::Realm;
2
3 use strict;
4 use warnings;
5
6 use base qw/Class::Accessor::Fast/;
7
8 BEGIN {
9     __PACKAGE__->mk_accessors(qw/store credential name config/);
10 };
11
12 sub 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;
21     if (!exists($config->{'store'}{'class'})) {
22         Carp::croak "Couldn't setup the authentication realm named '$realmname', no class defined";
23     } 
24         
25     $config->{store}{class} ||= '+Catalyst::Plugin::Authentication::Store::Null';
26     
27     # use the 
28     my $storeclass = $config->{'store'}{'class'};
29     
30     ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
31     ## taken to mean C::P::A::Store::(specifiedclass)
32     if ($storeclass !~ /^\+(.*)$/ ) {
33         $storeclass = "Catalyst::Plugin::Authentication::Store::${storeclass}";
34     } else {
35         $storeclass = $1;
36     }
37     
38
39     # a little niceness - since most systems seem to use the password credential class, 
40     # if no credential class is specified we use password.
41     $config->{credential}{class} ||= '+Catalyst::Plugin::Authentication::Credential::Password';
42
43     my $credentialclass = $config->{'credential'}{'class'};
44     
45     ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
46     ## taken to mean C::P::A::Credential::(specifiedclass)
47     if ($credentialclass !~ /^\+(.*)$/ ) {
48         $credentialclass = "Catalyst::Plugin::Authentication::Credential::${credentialclass}";
49     } else {
50         $credentialclass = $1;
51     }
52     
53     # if we made it here - we have what we need to load the classes;
54     Catalyst::Utils::ensure_class_loaded( $credentialclass );
55     Catalyst::Utils::ensure_class_loaded( $storeclass );
56     
57     # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms 
58     # of get_user and add it to the class.  this is because the auth routines use find_user, 
59     # and rely on it being present. (this avoids per-call checks)
60     if (!$storeclass->can('find_user')) {
61         no strict 'refs';
62         *{"${storeclass}::find_user"} = sub {
63                                                 my ($self, $info) = @_;
64                                                 my @rest = @{$info->{rest}} if exists($info->{rest});
65                                                 $self->get_user($info->{id}, @rest);
66                                             };
67     }
68     
69     ## a little cruft to stay compatible with some poorly written stores / credentials
70     ## we'll remove this soon.
71     if ($storeclass->can('new')) {
72         $self->store($storeclass->new($config->{'store'}, $app, $self));
73     } else {
74         $app->log->error("THIS IS DEPRECATED: $storeclass has no new() method - Attempting to use uninstantiated");
75         $self->store($storeclass);
76     }
77     if ($credentialclass->can('new')) {
78         $self->credential($credentialclass->new($config->{'credential'}, $app, $self));
79     } else {
80         $app->log->error("THIS IS DEPRECATED: $credentialclass has no new() method - Attempting to use uninstantiated");
81         $self->credential($credentialclass);
82     }
83     
84     return $self;
85 }
86
87 sub find_user {
88     my ( $self, $authinfo, $c ) = @_;
89
90     my $res = $self->store->find_user($authinfo, $c);
91     
92     if (!$res) {
93       if ($self->config->{'auto_create'} && $self->store->can('auto_create') ) {
94           $res = $self->store->auto_create($authinfo, $c);
95       }
96     } elsif ($self->config->{'auto_update'} && $self->store->can('auto_update')) {
97         $res = $self->store->auto_update($authinfo, $c, $res);
98     } 
99     
100     return $res;
101 }
102
103 sub authenticate {
104      my ($self, $c, $authinfo) = @_;
105
106      my $user = $self->credential->authenticate($c, $self, $authinfo);
107      if (ref($user)) {
108          $c->set_authenticated($user, $self->name);
109          return $user;
110      } else {
111          return undef;
112      }
113 }
114
115 sub save_user_in_session {
116     my ( $self, $c, $user ) = @_;
117
118     $c->session->{__user_realm} = $self->name;
119     
120     # we want to ask the store for a user prepared for the session.
121     # but older modules split this functionality between the user and the
122     # store.  We try the store first.  If not, we use the old method.
123     if ($self->store->can('for_session')) {
124         $c->session->{__user} = $self->store->for_session($c, $user);
125     } else {
126         $c->session->{__user} = $user->for_session;
127     }
128 }
129
130 sub from_session {
131     my ($self, $c, $frozen_user) = @_;
132     
133     return $self->store->from_session($c, $frozen_user);
134 }
135
136
137 __PACKAGE__;
138
139 __END__
140
141 =pod
142
143 =head1 NAME
144
145 Catalyst::Plugin::Authentication::Realm - Base class for realm objects.
146
147 =head1 DESCRIPTION
148
149 =head1 METHODS
150
151 =over 4
152
153 =item new
154
155 =item find_user
156
157 =item authenticate
158
159 =item save_user_in_session
160
161 =item from_session
162
163 =back
164
165 =cut
166
167