</permacrud>
</class>
- <class id="cra" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::remoteauth_profile" oils_persist:tablename="config.remoteauth_profile" reporter:label="Remote Patron Authentication Configuration Profile">
- <fields oils_persist:primary="name">
+ <class id="cra" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::remoteauth_profile" oils_persist:tablename="config.remoteauth_profile" reporter:label="Remote Authentication Profile">
+ <fields oils_persist:primary="id">
+ <field name="id" reporter:datatype="id" reporter:label="ID" oils_obj:required="true"/>
<field name="name" reporter:datatype="text" reporter:label="Name" oils_obj:required="true"/>
<field name="description" reporter:datatype="text" reporter:label="Description"/>
<field name="context_org" reporter:datatype="org_unit" reporter:label="Context Org" oils_obj:required="true"/>
<field name="enabled" reporter:datatype="bool" reporter:label="Enabled"/>
<field name="perm" reporter:datatype="link" reporter:label="Permission Required by User" oils_obj:required="true"/>
<field name="restrict_to_org" reporter:datatype="bool" reporter:label="Restrict by Home Library"/>
- <field name="allow_inactive" reporter:datatype="bool" reporter:label="Allow Inactive Users"/>
<field name="allow_expired" reporter:datatype="bool" reporter:label="Allow Expired Users"/>
<field name="block_list" reporter:datatype="text" reporter:label="Block List"/>
<field name="usr_activity_type" reporter:datatype="link" reporter:label="User Activity Type"/>
BEGIN;
CREATE TABLE config.remoteauth_profile (
- name TEXT PRIMARY KEY,
+ id SERIAL PRIMARY KEY,
+ name TEXT UNIQUE NOT NULL,
description TEXT,
context_org INT NOT NULL REFERENCES actor.org_unit(id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
enabled BOOLEAN NOT NULL DEFAULT FALSE,
perm INT NOT NULL REFERENCES permission.perm_list(id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED,
restrict_to_org BOOLEAN NOT NULL DEFAULT TRUE,
- allow_inactive BOOL NOT NULL DEFAULT FALSE,
allow_expired BOOL NOT NULL DEFAULT FALSE,
block_list TEXT,
usr_activity_type INT REFERENCES config.usr_activity_type(id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED
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;
--- /dev/null
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+-- The allow_inactive rule is deprecated, warn if any profile is using it.
+DO $SQL$
+BEGIN
+ PERFORM * FROM config.remoteauth_profile WHERE allow_inactive IS TRUE;
+ IF FOUND THEN
+ RAISE NOTICE 'Remote authentication is no longer supported for inactive users.';
+ END IF;
+END;
+$SQL$;
+
+
+DROP FUNCTION IF EXISTS actor.permit_remoteauth(TEXT, BIGINT);
+
+
+-- Add a new SERIAL primary key (the "id" column) to config.remoteauth_profile.
+-- The primary key is generally the first column, so we drop and recreate the
+-- config.remoteauth_profile table (preserving any existing data, of course) in
+-- order to get our desired column order.
+CREATE TABLE config.remoteauth_profile_temp (
+ id SERIAL PRIMARY KEY,
+ name TEXT UNIQUE NOT NULL,
+ description TEXT,
+ context_org INT NOT NULL REFERENCES actor.org_unit(id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+ enabled BOOLEAN NOT NULL DEFAULT FALSE,
+ perm INT NOT NULL REFERENCES permission.perm_list(id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED,
+ restrict_to_org BOOLEAN NOT NULL DEFAULT TRUE,
+ allow_expired BOOL NOT NULL DEFAULT FALSE,
+ block_list TEXT,
+ usr_activity_type INT REFERENCES config.usr_activity_type(id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED
+);
+
+INSERT INTO config.remoteauth_profile_temp (
+ name, description, context_org, enabled, perm, restrict_to_org,
+ allow_expired, block_list, usr_activity_type
+) SELECT
+ name, description, context_org, enabled, perm, restrict_to_org,
+ allow_expired, block_list, usr_activity_type
+FROM config.remoteauth_profile;
+
+DROP TABLE config.remoteauth_profile;
+ALTER TABLE config.remoteauth_profile_temp RENAME TO remoteauth_profile;
+
+
+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_found';
+ END IF;
+
+ IF usr.expire_date < NOW() AND profile.allow_expired IS FALSE THEN
+ RETURN 'expired';
+ 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 'blocked';
+ END IF;
+ END LOOP;
+ END IF;
+
+ -- User has passed all tests.
+ RETURN 'success';
+
+END;
+$func$ LANGUAGE plpgsql;
+
+COMMIT;
+
-- config for Basic HTTP Authentication (SYS1)
INSERT INTO config.remoteauth_profile
(name, description, context_org, enabled, perm,
- restrict_to_org, allow_inactive, allow_expired, block_list, usr_activity_type)
+ restrict_to_org, allow_expired, block_list, usr_activity_type)
VALUES ('Basic', 'Basic HTTP Authentication for SYS1', 2, TRUE, 1,
- TRUE, FALSE, FALSE, NULL, 1001);
+ TRUE, FALSE, NULL, 1001);