BEGIN;
+/*
+
+CREATE TYPE actor.cascade_setting_summary AS (
+ name TEXT,
+ value JSON,
+ has_org_setting BOOLEAN,
+ has_user_setting BOOLEAN,
+ has_workstation_setting BOOLEAN
+);
+
-- SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
CREATE TABLE config.workstation_setting_type (
AFTER INSERT OR UPDATE ON config.workstation_setting_type
FOR EACH ROW EXECUTE PROCEDURE config.setting_is_user_or_ws();
-CREATE OR REPLACE FUNCTION actor.get_setting(setting_name TEXT,
- org_id INT, user_id INT, workstation_id INT) RETURNS JSON AS
+ */
+
+CREATE OR REPLACE FUNCTION actor.get_cascade_setting(
+ setting_name TEXT, org_id INT, user_id INT, workstation_id INT)
+ RETURNS actor.cascade_setting_summary AS
$FUNC$
DECLARE
setting_value JSON;
+ summary actor.cascade_setting_summary;
org_setting_type config.org_unit_setting_type%ROWTYPE;
BEGIN
+ summary.name := setting_name;
+
+ -- Collect the org setting type status first in case we exit early.
+ -- The existance of an org setting type is not considered
+ -- privileged information.
+ SELECT INTO org_setting_type *
+ FROM config.org_unit_setting_type WHERE name = setting_name;
+ IF FOUND THEN
+ summary.has_org_setting := TRUE;
+ ELSE
+ summary.has_org_setting := FALSE;
+ END IF;
+
-- User and workstation settings have the same priority.
-- Start with user settings since that's the simplest code path.
+ -- The workstation_id is ignored if no user_id is provided.
IF user_id IS NOT NULL THEN
- SELECT INTO setting_value value
- FROM actor.usr_setting
+
+ SELECT INTO summary.value value FROM actor.usr_setting
WHERE usr = user_id AND name = setting_name;
- IF FOUND THEN
- RETURN setting_value;
- END IF;
- END IF;
- -- No user setting value found. Next try workstation.
- IF workstation_id IS NOT NULL THEN
+ IF FOUND THEN
+ -- if we have a value, we have a setting type
+ summary.has_user_setting := TRUE;
- SELECT INTO setting_value value
- FROM actor.workstation_setting
- WHERE workstation = workstation_id AND name = setting_name;
+ IF workstation_id THEN
+ -- Only inform the caller about the workstation
+ -- setting type disposition when a workstation id is
+ -- provided. Otherwise, it's NULL to indicate UNKNOWN.
+ summary.has_workstation_setting := FALSE;
+ END IF;
- IF FOUND THEN
- RETURN setting_value;
+ RETURN summary;
END IF;
- -- Workstation setting not found. However, since we have a
- -- workstation let's use its owning_lib if necessary.
- IF org_id IS NULL THEN
- SELECT INTO org_id owning_lib
- FROM actor.workstation WHERE id = workstation_id;
+ -- no user setting value, but a setting type may exist
+ SELECT INTO summary.has_user_setting EXISTS (
+ SELECT TRUE FROM config.usr_setting_type
+ WHERE name = setting_name
+ );
+
+ IF workstation_id IS NOT NULL THEN
+
+ IF NOT summary.has_user_setting THEN
+ -- A workstation setting type may only exist when a user
+ -- setting type does not.
+
+ SELECT INTO summary.value value
+ FROM actor.workstation_setting
+ WHERE workstation = workstation_id AND name = setting_name;
+
+ IF FOUND THEN
+ -- if we have a value, we have a setting type
+ summary.has_workstation_setting := TRUE;
+ RETURN summary;
+ END IF;
+
+ -- no value, but a setting type may exist
+ SELECT INTO summary.has_workstation_setting EXISTS (
+ SELECT TRUE FROM config.workstation_setting_type
+ WHERE name = setting_name
+ );
+ END IF;
+
+ -- Finally make use of the workstation to determine the org
+ -- unit if none is provided.
+ IF org_id IS NULL AND summary.has_org_setting THEN
+ SELECT INTO org_id owning_lib
+ FROM actor.workstation WHERE id = workstation_id;
+ END IF;
END IF;
END IF;
-- First see if we have any data that needs protecting, then
-- check the permission if needed.
+ IF NOT summary.has_org_setting THEN
+ RETURN summary;
+ END IF;
+
+ -- avoid putting the value into the summary until we confirm
+ -- the value should be visible to the caller.
SELECT INTO setting_value value
FROM actor.org_unit_ancestor_setting(setting_name, org_id);
IF NOT FOUND THEN
-- No value found -- perm check is irrelevant.
- RETURN NULL;
+ RETURN summary;
END IF;
- -- Check view permissions if necessary.
- SELECT INTO org_setting_type *
- FROM config.org_unit_setting_type WHERE name = setting_name;
-
IF org_setting_type.view_perm IS NOT NULL THEN
IF user_id IS NULL THEN
RAISE NOTICE 'Perm check required but no user_id provided';
- RETURN NULL;
+ RETURN summary;
END IF;
IF NOT permission.usr_has_perm(
THEN
RAISE NOTICE 'Perm check failed for user % on %',
user_id, org_setting_type.view_perm;
- RETURN NULL;
+ RETURN summary;
END IF;
END IF;
-- Perm check succeeded or was not necessary.
- RETURN setting_value;
+ summary.value := setting_value;
+ RETURN summary;
END;
$FUNC$ LANGUAGE PLPGSQL;
-CREATE OR REPLACE FUNCTION actor.get_setting_batch(setting_names TEXT[],
- org_id INT, user_id INT, workstation_id INT) RETURNS SETOF JSON AS
+CREATE OR REPLACE FUNCTION actor.get_cascade_setting_batch(
+ setting_names TEXT[], org_id INT, user_id INT, workstation_id INT)
+ RETURNS SETOF actor.cascade_setting_summary AS
$FUNC$
-- Returns a row per setting matching the setting name order. If no
-- value is applied, NULL is returned to retain name-response ordering.
DECLARE
setting_name TEXT;
+ summary actor.cascade_setting_summary;
BEGIN
FOREACH setting_name IN ARRAY setting_names LOOP
- RETURN NEXT * FROM actor.get_setting(
+ SELECT INTO summary * FROM actor.get_cascade_setting(
setting_Name, org_id, user_id, workstation_id);
+ RETURN NEXT summary;
END LOOP;
END;
$FUNC$ LANGUAGE PLPGSQL;
}
service.getServerItem = function(key) {
- if (service.keyCache[key] != undefined)
+ if (key in service.keyCache) {
return $q.when(service.keyCache[key])
+ }
if (!service.auth) service.auth = $injector.get('egAuth');
if (!service.auth.token()) return $q.when(null);
'open-ils.actor.settings.retrieve.atomic',
[key], service.auth.token()
).then(function(settings) {
- service.keyCache[key] = settings[0] ? settings[0][key] : null;
+ var val = settings[0].value();
+ // The server returns null for undefined settings.
+ // Treat as undefined for backwards compat.
+ service.keyCache[key] = (val === null) ? undefined : val;
return service.keyCache[key];
});
}
'open-ils.actor.settings.retrieve',
keys, service.auth.token()
).then(
- function() {
- // cache a value of null for any settings that have
- // no server values applied
- angular.forEach(keys, function(key) {
- if (Object.keys(foundValues).indexOf(key) == -1)
- service.keyCache[key] = foundValues[key] = null;
- });
- return foundValues;
- },
- null,
+ function() { return foundValues; },
+ function() {},
function(setting) {
- // when streaming we receive one setting per response
- var key = Object.keys(setting)[0];
- service.keyCache[key] = foundValues[key] = setting[key];
+ var val = setting.value();
+ // The server returns null for undefined settings.
+ // Treat as undefined for backwards compat.
+ service.keyCache[setting.name()] =
+ foundValues[setting.name()] =
+ (val === null) ? undefined : val;
}
);
}