]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Auth.pm
updates to support corner cases in circ
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Auth.pm
1 use strict; use warnings;
2 package OpenILS::Application::Auth;
3 use OpenSRF::Application;
4 use base qw/OpenSRF::Application/;
5 use OpenSRF::Utils::Cache;
6 use Digest::MD5 qw(md5_hex);
7 use OpenSRF::Utils::Logger qw(:level);
8 use OpenILS::Utils::Fieldmapper;
9 use OpenSRF::EX qw(:try);
10 use OpenILS::Application::AppUtils;
11 use OpenILS::Perm;
12 use OpenILS::Application::AppUtils;
13 use OpenILS::EX;
14
15 # memcache handle
16 my $cache_handle;
17 my $apputils = "OpenILS::Application::AppUtils";
18
19
20 # -------------------------------------------------------------
21 # Methods
22 # -------------------------------------------------------------
23 # -------------------------------------------------------------
24
25 __PACKAGE__->register_method(
26         method  => "init_authenticate",
27         api_name        => "open-ils.auth.authenticate.init",
28         argc            => 1, #(username) 
29         note            =>      <<TEXT,
30 Generates a random seed and returns it.  The client
31 must then perform md5_hex( \$seed . \$password ) and use that
32 as the passwordhash to open-ils.auth.authenticate.complete
33 TEXT
34 );
35
36 __PACKAGE__->register_method(
37         method  => "complete_authenticate",
38         api_name        => "open-ils.auth.authenticate.complete",
39         argc            => 2, #( barcode, passwdhash )
40         note            => <<TEXT,
41 Client provides the username and passwordhash (see 
42 open-ils.auth.authenticate.init).  If their password hash is 
43 correct for the given username, a session id is returned, 
44 if not, "0" is returned
45 TEXT
46 );
47
48 __PACKAGE__->register_method(
49         method  => "retrieve_session",
50         api_name        => "open-ils.auth.session.retrieve",
51         argc            => 1, #( sessionid )
52         note            => <<TEXT,
53 Pass in a sessionid and this returns the username associated with it
54 TEXT
55 );
56
57 __PACKAGE__->register_method(
58         method  => "delete_session",
59         api_name        => "open-ils.auth.session.delete",
60         argc            => 1, #( sessionid )
61         note            => <<TEXT,
62 Pass in a sessionid and this delete it from the cache 
63 TEXT
64 );
65
66
67 # -------------------------------------------------------------
68 # Implementation
69 # -------------------------------------------------------------
70 # -------------------------------------------------------------
71
72
73 # -------------------------------------------------------------
74 # connect to the memcache server
75 # -------------------------------------------------------------
76 sub child_init {
77         $cache_handle = OpenSRF::Utils::Cache->new('global');
78 }
79
80
81 # -------------------------------------------------------------
82 # We build a random hash and put the hash along with the 
83 # username into memcache (so that any backend may fulfill the
84 # auth request).
85 # -------------------------------------------------------------
86 sub init_authenticate {
87         my( $self, $client, $username ) = @_;
88         my $seed = md5_hex( time() . $$ . rand() . $username );
89         $cache_handle->put_cache( "_open-ils_seed_$username", $seed, 30 );
90         warn "init happened with seed $seed\n";
91         return $seed;
92 }
93
94 # -------------------------------------------------------------
95 # The temporary hash is removed from memcache.  
96 # We retrieve the password from storage and verify
97 # their password hash against our re-hashed version of the 
98 # password. If all goes well, we return the session id. 
99 # Otherwise, we return "0"
100 # If type is set to 'opac', then this is an opac login,
101 # otherwise, it's a staff login
102 # -------------------------------------------------------------
103 sub complete_authenticate {
104         my( $self, $client, $username, $passwdhash, $type ) = @_;
105
106         my $name = "open-ils.storage.direct.actor.user.search.usrname.atomic";
107
108         warn "Completing Authentication\n";
109
110         warn "Retrieving user from storage..\n";
111         my $user_list = OpenILS::Application::AppUtils->simple_scalar_request(
112                         "open-ils.storage", $name, $username );
113
114         unless(ref($user_list)) {
115                 #return OpenILS::EX->new("UNKNOWN_USER")->ex;
116                 return { ilsevent => 1000 };
117         }
118
119         warn "We have the user from storage with usrname $username\n";
120
121         my $user = $user_list->[0];
122         
123
124         if(!$user or !ref($user) ) {
125 #               return OpenILS::EX->new("UNKNOWN_USER")->ex();
126                 return { ilsevent => 1000 };
127         }
128
129         my $password = $user->passwd();
130         warn "user passwd is $password\n";
131
132         if(!$password) {
133                 throw OpenSRF::EX::ERROR ("No password exists for $username", ERROR);
134         }
135
136         warn "we have a password\n";
137
138         my $current_seed = $cache_handle->get_cache("_open-ils_seed_$username");
139         $cache_handle->delete_cache( "_open-ils_seed_$username" );
140
141         warn "Removed tmp data from cache\n";
142
143         unless($current_seed) {
144                 throw OpenSRF::EX::User 
145                         ("User must call open-ils.auth.init_authenticate first (or respond faster)");
146         }
147
148         my $hash = md5_hex($current_seed . $password);
149
150         if( $hash eq $passwdhash ) {
151                 # password is correct... do they have permission to login here?
152
153                 my $timeout = 28800; #staff login timeout - different for opac?
154                 my $opactimeout = 604800; # 14 days
155
156                 if($type eq "opac") {
157                         # 1 is the top level org unit (we should probably load the tree and get id from it)
158                         warn "Checking user perms for OPAC login\n";
159                         if($apputils->check_user_perms($user->id(), 1, "OPAC_LOGIN")) {
160                                 return OpenILS::Perm->new("OPAC_LOGIN");
161                         }
162
163                 } else {
164                         # 1 is the top level org unit (we should probably load the tree and get id from it)
165                         warn "Checking user perms for Staff login\n";
166                         if($apputils->check_user_perms($user->id(), 1, "STAFF_LOGIN")) {
167                                 return OpenILS::Perm->new("STAFF_LOGIN");
168                         }
169                 }
170
171                 my $session_id = md5_hex(time() . $$ . rand()); 
172                 $cache_handle->put_cache( $session_id, $user, $timeout );
173                 #return $session_id;
174                 return { ilsevent => 0, authtoken => $session_id };
175
176         } else {
177
178                 warn "User password is incorrect...\n"; # send exception
179                 return { ilsevent => 1000 };
180         }
181 }
182
183 sub retrieve_session {
184         my( $self, $client, $sessionid ) = @_;
185         my $user =  $cache_handle->get_cache($sessionid);
186         if(!$user) {
187                 warn "No User returned from retrieve_session $sessionid\n";
188         }
189         if($user) {$user->clear_passwd();}
190         return $user;
191 }
192
193 sub delete_session {
194         my( $self, $client, $sessionid ) = @_;
195         return $cache_handle->delete_cache($sessionid);
196 }
197
198
199 1;