From: Jeff Davis Date: Thu, 15 Jul 2021 18:56:49 +0000 (-0700) Subject: LP#1936422: RemoteAuth: handle "not permitted" and "has penalties" auth failures... X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=refs%2Fheads%2Fuser%2Fjeffdavis%2Flp1936422-remoteauth-more-error-codes;p=working%2FEvergreen.git LP#1936422: RemoteAuth: handle "not permitted" and "has penalties" auth failures separately Previously, a user who lacked permission to authenticate was treated as not found by RemoteAuth, and a user with standing penalites was treated as blocked. This commit adds the ability to handle those failure modes separately, using the EZProxyCGI handler as an example; the default behavior for other RemoteAuth handlers is unchanged. Signed-off-by: Jeff Davis --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth.pm index 863796d0cf..1956820fd2 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth.pm @@ -183,6 +183,10 @@ sub do_patron_auth { return $self->patron_not_found; } elsif ($permit_test eq 'expired') { return $self->patron_is_expired; + } elsif ($permit_test eq 'not_permitted') { + return $self->patron_not_permitted; + } elsif ($permit_test eq 'has_penalties') { + return $self->patron_has_penalties; } else { return $self->patron_is_blocked; } @@ -268,6 +272,10 @@ sub get_patron_info { return $self->patron_is_expired; } elsif ($permit_test eq 'blocked') { return $self->patron_is_blocked; + } elsif ($permit_test eq 'not_permitted') { + return $self->patron_not_permitted; + } elsif ($permit_test eq 'has_penalties') { + return $self->patron_has_penalties; } else { return $self->backend_error; } @@ -318,5 +326,19 @@ sub patron_is_expired { return Apache2::Const::DECLINED; } +# patron does not have required permission to authenticate; +# treat them as being not found +sub patron_not_permitted { + my $self = shift; + return $self->patron_not_found; +} + +# patron has blocking penalties; +# treat them as being blocked +sub patron_has_penalties { + my $self = shift; + return $self->patron_is_blocked; +} + 1; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth/EZProxyCGI.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth/EZProxyCGI.pm index f18063e369..cf3a9d3105 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth/EZProxyCGI.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth/EZProxyCGI.pm @@ -185,12 +185,24 @@ sub patron_not_found { return $self->error('patron_not_found'); } -# patron is barred or has blocking penalties +# patron is barred/blocked sub patron_is_blocked { my $self = shift; return $self->error('patron_is_blocked'); } +# patron does not have permission to authenticate +sub patron_not_permitted { + my $self = shift; + return $self->error('patron_not_permitted'); +} + +# patron has blocking penalties +sub patron_has_penalties { + my $self = shift; + return $self->error('patron_has_penalties'); +} + # patron is expired sub patron_is_expired { my $self = shift; diff --git a/Open-ILS/src/sql/Pg/150.remoteauth.sql b/Open-ILS/src/sql/Pg/150.remoteauth.sql index 0b36c4991c..445be88a0c 100644 --- a/Open-ILS/src/sql/Pg/150.remoteauth.sql +++ b/Open-ILS/src/sql/Pg/150.remoteauth.sql @@ -43,7 +43,7 @@ BEGIN SELECT INTO perm code FROM permission.perm_list WHERE id = profile.perm; IF permission.usr_has_perm(usr.id, perm, profile.context_org) IS FALSE THEN - RETURN 'not_found'; + RETURN 'not_permitted'; END IF; IF usr.expire_date < NOW() AND profile.allow_expired IS FALSE THEN @@ -71,7 +71,7 @@ BEGIN IF penalty_count > 0 THEN -- User has penalties that match this block, so auth is not permitted. -- Don't bother testing the rest of the block list. - RETURN 'blocked'; + RETURN 'has_penalties'; END IF; END LOOP; END IF; diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.remoteauth-more-error-codes.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.remoteauth-more-error-codes.sql new file mode 100644 index 0000000000..2d579029b3 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.remoteauth-more-error-codes.sql @@ -0,0 +1,75 @@ +BEGIN; + +SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version); + +CREATE OR REPLACE FUNCTION actor.permit_remoteauth (profile_name TEXT, userid BIGINT) RETURNS TEXT AS $func$ +DECLARE + usr actor.usr%ROWTYPE; + profile config.remoteauth_profile%ROWTYPE; + perm TEXT; + context_org_list INT[]; + home_prox INT; + block TEXT; + penalty_count INT; +BEGIN + + SELECT INTO usr * FROM actor.usr WHERE id = userid AND NOT deleted; + IF usr IS NULL THEN + RETURN 'not_found'; + END IF; + + IF usr.barred IS TRUE THEN + RETURN 'blocked'; + END IF; + + SELECT INTO profile * FROM config.remoteauth_profile WHERE name = profile_name; + SELECT INTO context_org_list ARRAY_AGG(id) FROM actor.org_unit_full_path( profile.context_org ); + + -- user's home library must be within the context org + IF profile.restrict_to_org IS TRUE AND usr.home_ou NOT IN (SELECT * FROM UNNEST(context_org_list)) THEN + RETURN 'not_found'; + END IF; + + SELECT INTO perm code FROM permission.perm_list WHERE id = profile.perm; + IF permission.usr_has_perm(usr.id, perm, profile.context_org) IS FALSE THEN + RETURN 'not_permitted'; + END IF; + + IF usr.expire_date < NOW() AND profile.allow_expired IS FALSE THEN + RETURN 'expired'; + END IF; + + IF usr.active IS FALSE AND profile.allow_inactive IS FALSE THEN + RETURN 'blocked'; + END IF; + + -- Proximity of user's home_ou to context_org to see if penalties should be ignored. + SELECT INTO home_prox prox FROM actor.org_unit_proximity WHERE from_org = usr.home_ou AND to_org = profile.context_org; + + -- Loop through the block list to see if the user has any matching penalties. + IF profile.block_list IS NOT NULL THEN + FOR block IN SELECT UNNEST(STRING_TO_ARRAY(profile.block_list, '|')) LOOP + SELECT INTO penalty_count COUNT(DISTINCT csp.*) + FROM actor.usr_standing_penalty usp + JOIN config.standing_penalty csp ON (csp.id = usp.standing_penalty) + WHERE usp.usr = usr.id + AND usp.org_unit IN ( SELECT * FROM UNNEST(context_org_list) ) + AND ( usp.stop_date IS NULL or usp.stop_date > NOW() ) + AND ( csp.ignore_proximity IS NULL OR csp.ignore_proximity < home_prox ) + AND csp.block_list ~ block; + IF penalty_count > 0 THEN + -- User has penalties that match this block, so auth is not permitted. + -- Don't bother testing the rest of the block list. + RETURN 'has_penalties'; + END IF; + END LOOP; + END IF; + + -- User has passed all tests. + RETURN 'success'; + +END; +$func$ LANGUAGE plpgsql; + +COMMIT; + diff --git a/Open-ILS/src/templates/remoteauth/ezproxycgi/error.tt2 b/Open-ILS/src/templates/remoteauth/ezproxycgi/error.tt2 index d078a08f7f..ad17c06c89 100644 --- a/Open-ILS/src/templates/remoteauth/ezproxycgi/error.tt2 +++ b/Open-ILS/src/templates/remoteauth/ezproxycgi/error.tt2 @@ -6,6 +6,10 @@ Patron not found. [% ELSIF ctx.error_msg == 'patron_is_blocked' %] Your account is blocked. + [% ELSIF ctx.error_msg == 'patron_has_penalties' %] + Your account has penalties which prevent authentication. + [% ELSIF ctx.error_msg == 'patron_not_permitted' %] + Your account is not permitted to authenticate. [% ELSIF ctx.error_msg == 'patron_is_expired' %] Your account is expired. [% ELSE %]