Added auto_update feature - for updating user information on checkin -
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Plugin / Authentication / Realm.pm
CommitLineData
646ea5b1 1package Catalyst::Plugin::Authentication::Realm;
2
3use strict;
4use warnings;
5use base qw/Class::Accessor::Fast/;
6
7BEGIN {
8 __PACKAGE__->mk_accessors(qw/store credential name config/);
9};
10
11sub 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
86sub find_user {
87 my ( $self, $authinfo, $c ) = @_;
88
89 my $res = $self->store->find_user($authinfo, $c);
90
4bd1f581 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);
97 }
646ea5b1 98
99 return $res;
100}
101
102sub 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
114sub 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
129sub 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__