1 package OpenILS::WWW::AccessHandler;
2 use strict; use warnings;
5 use Apache2::Const -compile => qw(:common HTTP_OK HTTP_FORBIDDEN HTTP_MOVED_TEMPORARILY HTTP_MOVED_PERMANENTLY);
6 use Apache2::RequestRec;
19 # Configuration options
21 # URL to redirect to for login
22 my $lurl = $r->dir_config('OILSAccessHandlerLoginURL') || '/eg/opac/login';
23 # Redirection variable to come "back" from the previous URL
24 my $lurlvar = $r->dir_config('OILSAccessHandlerLoginURLRedirectVar') || 'redirect_to';
25 # No access page? If not set, just return forbidden.
26 my $failurl = $r->dir_config('OILSAccessHandlerFailURL');
27 # Required permission (if set)
28 my $userperm = $r->dir_config('OILSAccessHandlerPermission');
29 # Need to be in good standing?
30 my $userstanding = $r->dir_config('OILSAccessHandlerGoodStanding') || 0;
31 # Required org unit (if set)
32 my $userou = $r->dir_config('OILSAccessHandlerHomeOU');
33 # OU for permission/standing checks, if not set use home OU
34 my $checkou = $r->dir_config('OILSAccessHandlerCheckOU');
35 # Set referrer based on OU Setting?
36 my $referrersetting = $r->dir_config('OILSAccessHandlerReferrerSetting');
38 my $url = $r->construct_url();
40 # push everyone to the secure site
41 if ($url =~ /^http:/o) {
42 my $target = $r->construct_url($r->unparsed_uri);
43 $target =~ s/^http:/https:/o;
44 $r->headers_out->set(Location => $target);
45 return Apache2::Const::HTTP_MOVED_PERMANENTLY;
48 # We could use CGI....but that creates issues if post data may be submitted
49 my $auth_ses = ($r->headers_in->get('Cookie') =~ /(?:^|\s)ses=([^;]*)/)[0];
50 my $user = _verify_login($auth_ses);
52 if (!defined($user)) {
53 my $redirect = $r->construct_url($r->unparsed_uri);
54 my $target = $r->construct_url($lurl) . '?' . $lurlvar . '=' . uri_escape($redirect);
55 $target =~ s/^http:/https:/o; # This should never be needed due to the redirect above, but better safe than sorry
56 $r->headers_out->set(Location => $target);
57 # Lets not cache this either, just in case.
58 $r->headers_out->set('Cache-Control' => 'no-cache, no-store, must-revalidate');
59 $r->headers_out->set(Pragma => 'no-cache');
60 $r->headers_out->set(Expires => 0);
61 return Apache2::Const::HTTP_MOVED_TEMPORARILY;
64 # Convert check OU from shortname, if needed
65 $checkou = _get_org_id($checkou);
67 # If we have no check OU at this point, use the user's home OU
68 $checkou ||= $user->home_ou;
73 my @permissions = split(/\s*[ ,]\s*/, $userperm);
74 $failed++ unless _verify_permission($auth_ses, $user, $checkou, \@permissions);
76 if (!$failed && $userstanding) {
77 $failed++ unless _verify_standing($user);
79 if (!$failed && $userou) {
80 $failed++ unless _verify_home_ou($user, $userou);
83 # If we failed one of the above checks they aren't allowed in
86 my $target = $r->construct_url($failurl);
87 $r->headers_out->set(Location => $target);
88 return Apache2::Const::HTTP_MOVED_TEMPORARILY;
90 return Apache2::Const::HTTP_FORBIDDEN;
94 # Forced referrer for some referrer auth services?
95 if ($referrersetting) {
96 my $referrervalue = _get_ou_setting($referrersetting, $checkou);
97 if ($referrervalue && $referrervalue->{value}) {
98 $r->headers_in->set('Referer', $referrervalue->{value});
102 # If we haven't thrown them out yet, let them through
103 return Apache2::Const::OK;
106 # "Private" functions
111 return undef unless $token;
113 my $user = OpenSRF::AppSession
114 ->create('open-ils.auth')
115 ->request('open-ils.auth.session.retrieve', $token)
118 if (ref($user) eq 'HASH' && $user->{ilsevent} == 1001) {
122 return $user if ref($user);
128 my ($org_identifier) = @_;
129 # Does this look like a number?
130 if ($org_identifier !~ '^[0-9]+$') {
132 if ($org_identifier) {
133 # Look up org unit by shortname
134 my $org_unit = OpenSRF::AppSession
135 ->create('open-ils.actor')
136 ->request('open-ils.actor.org_unit.retrieve_by_shortname', $org_identifier)
138 if ($org_unit && ref($org_unit) ne 'HASH') {
139 # We appear to have an org unit! So return the ID.
140 return $org_unit->id;
144 # Looks like a database ID, so leave it alone.
145 return $org_identifier;
147 # If we have reached this point, assume that we found no useful ID.
152 sub _verify_home_ou {
153 my ($user, $home_ou) = @_;
154 my $org_tree = OpenSRF::AppSession
155 ->create('open-ils.actor')
156 ->request('open-ils.actor.org_tree.ancestors.retrieve', $user->home_ou)
158 if ($org_tree && ref($org_tree) ne 'HASH') {
161 $user_orgs{$org_tree->id} = 1;
162 if ($org_tree->children) {
163 $org_tree = @{$org_tree->children}[0];
169 my @home_ous = split(/\s*[ ,]\s*/,$home_ou);
170 for my $cur_ou (@home_ous) {
171 $cur_ou = _get_org_id($cur_ou);
172 if ($user_orgs{$cur_ou}) {
181 sub _verify_permission {
182 my ($token, $user, $org_unit, $permissions) = @_;
184 my $failures = OpenSRF::AppSession
185 ->create('open-ils.actor')
186 ->request('open-ils.actor.user.perm.check', $token, $user->id, $org_unit, $permissions)
189 return !scalar(@$failures);
193 sub _verify_standing {
196 # If barred you are not in good standing
197 return 0 if $user->barred;
198 # If inactive you are also not in good standing
199 return 0 unless $user->active;
201 # Possible addition: Standing Penalty Checks?
206 sub _get_ou_setting {
207 my ($setting, $org_unit) = @_;
209 my $value = OpenSRF::AppSession->create('open-ils.actor')
210 ->request('open-ils.actor.ou_setting.ancestor_default', $org_unit, $setting)