]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth/PatronAPI.pm
LP#1887196: RemoteAuth PatronAPI authentication
[Evergreen.git] / Open-ILS / src / perlmods / lib / OpenILS / WWW / RemoteAuth / PatronAPI.pm
1 # Copyright (C) 2019 BC Libraries Cooperative
2 #
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
7
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16
17 # ======================================================================
18 # - RemoteAuth handler for PatronAPI authentication:
19 #   https://csdirect.iii.com/sierrahelp/Content/sril/sril_patronapi.html
20 # ======================================================================
21
22 package OpenILS::WWW::RemoteAuth::PatronAPI;
23 use strict; use warnings;
24 use OpenILS::WWW::RemoteAuth;
25 use base "OpenILS::WWW::RemoteAuth";
26
27 use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN AUTH_REQUIRED HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST);
28 use File::Spec;
29 use OpenSRF::EX qw(:try);
30 use OpenSRF::Utils::Logger qw/$logger/;
31 use OpenILS::Utils::CStoreEditor qw/:funcs/;
32 use OpenSRF::Utils::JSON;
33 use OpenILS::WWW::RemoteAuth::Template;
34
35 sub new {
36     my( $class, $args ) = @_;
37     $args ||= {};
38     $args->{request_type} ||= 'default';
39     $class = ref $class || $class;
40     return bless($args, $class);
41 }
42
43 sub r {
44     my ($self, $r) = @_;
45     $self->{r} = $r if $r;
46     return $self->{r};
47 }
48
49 sub request_type {
50     my ($self, $request_type) = @_;
51     $self->{request_type} = $request_type if $request_type;
52     return $self->{request_type};
53 }
54
55 sub process {
56     my ($self, $r) = @_;
57     my ($authtoken, $editor, $config);
58
59     $self->r($r);
60
61     # authorize client
62     try {
63         my $client_user = $r->dir_config('OILSRemoteAuthClientUsername');
64         my $client_pw = $r->dir_config('OILSRemoteAuthClientPassword');
65         $authtoken = $self->do_client_auth($client_user, $client_pw);
66     } catch Error with {
67         $logger->error("RemoteAuth PatronAPI failed on client auth: @_");
68         return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR;
69     };
70     return $self->client_not_authorized unless $authtoken;
71
72     # load config
73     try {
74         $editor = new_editor( authtoken => $authtoken );
75         $config = $self->load_config($editor, $r);
76     } catch Error with {
77         $logger->error("RemoteAuth PatronAPI failed on load config: @_");
78         return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR;
79     };
80     return $self->backend_error unless $config;
81
82     my $allow_dump = $r->dir_config('OILSRemoteAuthPatronAPIAllowDump') || 'false';
83     my $id_type = $r->dir_config('OILSRemoteAuthPatronAPIIDType') || 'barcode';
84
85     # parse request
86     my $path = $r->path_info;
87     $path =~ s|/*\$||; # strip any trailing slashes
88     my @params = reverse File::Spec->splitdir($path);
89     $self->request_type(shift @params);
90
91     if ($self->request_type eq 'dump') {
92         unless ($allow_dump eq 'true') {
93             return $self->client_not_authorized;
94         }
95         my ($id, @leftovers) = @params;
96         return $self->get_patron_info($editor, $config, { $id_type => $id });
97
98     } elsif ($self->request_type eq 'pintest') {
99         my ($password, $id, @leftovers) = @params;
100         return $self->do_patron_auth($editor, $config, $id, $password);
101
102     } else {
103         $logger->error("RemoteAuth PatronAPI: invalid request format");
104         return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR;
105     }
106 }
107
108 sub success {
109     my ($self, $user) = @_;
110     my $template = $self->request_type;
111     my $ctx = {
112         result => 'success'
113     };
114     my $tt = new OpenILS::WWW::RemoteAuth::Template;
115     return $tt->process($template, $ctx, $self->r);
116 }
117
118 # wrapper method for auth failures
119 sub error {
120     my ($self, $msg) = @_;
121     my $template = $self->request_type;
122     my $ctx = {
123         result => 'error',
124         error_msg => $msg
125     };
126     my $tt = new OpenILS::WWW::RemoteAuth::Template;
127     return $tt->process($template, $ctx, $self->r);
128 }
129
130 # generic backend error
131 sub backend_error {
132     my $self = shift;
133     return $self->error('backend_error');
134 }
135
136 # client error (e.g. missing params)
137 sub client_error {
138     my $self = shift;
139     return $self->error('client_error');
140 }
141
142 # client auth failed
143 sub client_not_authorized {
144     my $self = shift;
145     return $self->error('client_not_authorized');
146 }
147
148 # patron auth failed (bad password etc)
149 sub patron_not_authenticated {
150     my $self = shift;
151     return $self->error('patron_not_authenticated');
152 }
153
154 # patron does not exist or is inactive/deleted
155 sub patron_not_found {
156     my $self = shift;
157     return $self->error('patron_not_found');
158 }
159
160 # patron is barred or has blocking penalties
161 sub patron_is_blocked {
162     my $self = shift;
163     return $self->error('patron_is_blocked');
164 }
165
166 # patron is expired
167 sub patron_is_expired {
168     my $self = shift;
169     return $self->error('patron_is_expired');
170 }
171
172 1;
173
174