Whitespace. gah.
[working/Evergreen.git] / Open-ILS / src / perlmods / OpenILS / WWW / PasswordReset.pm
1 package OpenILS::WWW::PasswordReset;
2
3 # Copyright (C) 2010 Laurentian University
4 # Dan Scott <dscott@laurentian.ca>
5
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
20 use strict; use warnings;
21
22 use Apache2::Log;
23 use Apache2::Const -compile => qw(OK REDIRECT DECLINED NOT_FOUND :log);
24 use APR::Const    -compile => qw(:error SUCCESS);
25 use Apache2::RequestRec ();
26 use Apache2::RequestIO ();
27 use Apache2::RequestUtil;
28 use CGI;
29 use Template;
30
31 use OpenSRF::EX qw(:try);
32 use OpenSRF::Utils qw/:datetime/;
33 use OpenSRF::Utils::Cache;
34 use OpenSRF::System;
35 use OpenSRF::AppSession;
36
37 use OpenILS::Utils::Fieldmapper;
38 use OpenSRF::Utils::Logger qw/$logger/;
39 use OpenILS::Application::AppUtils;
40 use OpenILS::Utils::CStoreEditor qw/:funcs/;
41
42 my $log = 'OpenSRF::Utils::Logger';
43 my $U = 'OpenILS::Application::AppUtils';
44
45 my ($bootstrap, $actor, $templates);
46 my $i18n = {};
47 my $init_done = 0; # has child_init been called?
48
49 sub import {
50     my $self = shift;
51     $bootstrap = shift;
52 }
53
54 sub child_init {
55     OpenSRF::System->bootstrap_client( config_file => $bootstrap );
56     
57     my $conf = OpenSRF::Utils::SettingsClient->new();
58     my $idl = $conf->config_value("IDL");
59     Fieldmapper->import(IDL => $idl);
60     $templates = $conf->config_value("dirs", "templates");
61     $actor = OpenSRF::AppSession->create('open-ils.actor');
62     load_i18n();
63     $init_done = 1;
64 }
65
66 sub password_reset {
67     my $apache = shift;
68
69     child_init() unless $init_done;
70
71     return Apache2::Const::DECLINED if (-e $apache->filename);
72
73     $apache->content_type('text/html');
74
75         my $cgi = new CGI;
76     my $ctx = {};
77
78     $ctx->{'uri'} = $apache->uri;
79
80     # Get our locale from the URL
81     (my $locale = $apache->path_info) =~ s{^.*?/([a-z]{2}-[A-Z]{2})/.*?$}{$1};
82     if (!$locale) {
83         $locale = 'en-US';
84     }
85
86     # If locale exists, use it; otherwise fall back to en-US
87     if (exists $i18n->{$locale}) {
88         $ctx->{'i18n'} = $i18n->{$locale};
89     } else {
90         $ctx->{'i18n'} = $i18n->{'en-US'};
91     }
92
93     my $tt = Template->new({
94         INCLUDE_PATH => $templates
95     }) || die "$Template::ERROR\n";
96
97     # Get our UUID: if no UUID, then display barcode / username / email prompt
98     (my $uuid = $apache->path_info) =~ s{^/$locale/([^/]*?)$}{$1};
99     $logger->info("Password reset: UUID = $uuid");
100
101     if (!$uuid) {
102         request_password_reset($apache, $cgi, $tt, $ctx);
103     } else {
104         reset_password($apache, $cgi, $tt, $ctx, $uuid);
105     }
106 }
107
108 sub reset_password {
109     my ($apache, $cgi, $tt, $ctx, $uuid) = @_;
110
111     my $password_1 = $cgi->param('pwd1');
112     my $password_2 = $cgi->param('pwd2');
113
114     $ctx->{'title'} = $ctx->{'i18n'}{'TITLE'};
115     $ctx->{'password_prompt'} = $ctx->{'i18n'}{'PASSWORD_PROMPT'};
116     $ctx->{'password_prompt2'} = $ctx->{'i18n'}{'PASSWORD_PROMPT2'};
117
118     # In case non-matching passwords slip through our funky Web interface
119     if ($password_1 and $password_2 and ($password_1 ne $password_2)) {
120         $ctx->{'status'} = {
121             style => 'error',
122             msg => $ctx->{'i18n'}{'NO_MATCH'}
123         };
124         $tt->process('password-reset/reset-form.tt2', $ctx)
125             || die $tt->error();
126         return Apache2::Const::OK;
127     }
128
129     if ($password_1 and $password_2 and ($password_1 eq $password_2)) {
130         my $response = $actor->request('open-ils.actor.patron.password_reset.commit', $uuid, $password_1)->gather();
131         if (ref($response) && $response->{'textcode'}) {
132
133             if ($response->{'textcode'} eq 'PATRON_NOT_AN_ACTIVE_PASSWORD_RESET_REQUEST') {
134                 $ctx->{'status'} = { 
135                     style => 'error',
136                     msg => $ctx->{'i18n'}{'NOT_ACTIVE'}
137
138                 };
139             }
140             if ($response->{'textcode'} eq 'PATRON_PASSWORD_WAS_NOT_STRONG') {
141                 $ctx->{'status'} = { 
142                     style => 'error',
143                     msg => $ctx->{'i18n'}{'NOT_STRONG'}
144
145                 };
146             }
147             $tt->process('password-reset/reset-form.tt2', $ctx)
148                 || die $tt->error();
149             return Apache2::Const::OK;
150         }
151         $ctx->{'status'} = { 
152             style => 'success',
153             msg => $ctx->{'i18n'}{'SUCCESS'}
154         };
155     }
156
157     # Either the password change was successful, or this is their first time through
158     $tt->process('password-reset/reset-form.tt2', $ctx)
159         || die $tt->error();
160
161     return Apache2::Const::OK;
162 }
163
164 # Load our localized strings - lame, need to convert to Locale::Maketext
165 sub load_i18n {
166     foreach my $string_bundle (glob("$templates/password-reset/strings.*")) {
167         open(I18NFH, '<', $string_bundle);
168         (my $locale = $string_bundle) =~ s/^.*\.([a-z]{2}-[A-Z]{2})$/$1/;
169         $logger->debug("Loaded locale [$locale] from file: [$string_bundle]");
170         while(<I18NFH>) {
171             my ($string_id, $string) = ($_ =~ m/^(.+?)=(.*?)$/);
172             $i18n->{$locale}{$string_id} = $string;
173         }
174         close(I18NFH);
175     }
176 }
177
178 sub request_password_reset {
179     my ($apache, $cgi, $tt, $ctx) = @_;
180
181     my $barcode = $cgi->param('barcode');
182     my $username = $cgi->param('username');
183     my $email = $cgi->param('email');
184
185     if (!($barcode or $username or $email)) {
186         $ctx->{'status'} = {
187             style => 'plain',
188             msg => $ctx->{'i18n'}{'IDENTIFY_YOURSELF'}
189         };
190         $tt->process('password-reset/request-form.tt2', $ctx)
191             || die $tt->error();
192         return Apache2::Const::OK;
193     } elsif ($barcode) {
194         my $response = $actor->request('open-ils.actor.patron.password_reset.request', 'barcode', $barcode)->gather();
195         $ctx->{'status'} = {
196             style => 'plain',
197             msg => $ctx->{'i18n'}{'REQUEST_SUCCESS'}
198         };
199         # Hide form
200         $tt->process('password-reset/request-form.tt2', $ctx)
201             || die $tt->error();
202         return Apache2::Const::OK;
203     } elsif ($username) {
204         my $response = $actor->request('open-ils.actor.patron.password_reset.request', 'username', $username)->gather();
205         $ctx->{'status'} = {
206             style => 'plain',
207             msg => $ctx->{'i18n'}{'REQUEST_SUCCESS'}
208         };
209         # Hide form
210         $tt->process('password-reset/request-form.tt2', $ctx)
211             || die $tt->error();
212         return Apache2::Const::OK;
213     }
214 }
215
216 1;
217
218 # vim: et:ts=4:sw=4