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