convert rbac*.sql files, except test-file, to Liquibase changesets
This commit is contained in:
parent
6c33bbe780
commit
d234ac3227
@ -1,63 +0,0 @@
|
|||||||
abort;
|
|
||||||
set local session authorization default;
|
|
||||||
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION array_distinct(anyarray) RETURNS anyarray AS $f$
|
|
||||||
SELECT array_agg(DISTINCT x) FROM unnest($1) t(x);
|
|
||||||
$f$ LANGUAGE SQL IMMUTABLE;
|
|
||||||
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION lastRowCount()
|
|
||||||
RETURNS bigint
|
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
DECLARE
|
|
||||||
lastRowCount bigint;
|
|
||||||
BEGIN
|
|
||||||
GET DIAGNOSTICS lastRowCount = ROW_COUNT;
|
|
||||||
RETURN lastRowCount;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
|
|
||||||
-- ========================================================
|
|
||||||
-- Test Data helpers
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION intToVarChar(i integer, len integer)
|
|
||||||
RETURNS varchar
|
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
DECLARE
|
|
||||||
partial varchar;
|
|
||||||
BEGIN
|
|
||||||
SELECT chr(ascii('a') + i%26) INTO partial;
|
|
||||||
IF len > 1 THEN
|
|
||||||
RETURN intToVarChar(i/26, len-1) || partial;
|
|
||||||
ELSE
|
|
||||||
RETURN partial;
|
|
||||||
END IF;
|
|
||||||
END; $$;
|
|
||||||
|
|
||||||
select * from intToVarChar(211, 4);
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION randomInRange(min INTEGER, max INTEGER)
|
|
||||||
RETURNS INT
|
|
||||||
RETURNS NULL ON NULL INPUT
|
|
||||||
language 'plpgsql' AS $$
|
|
||||||
BEGIN
|
|
||||||
RETURN floor(random() * (max-min + 1) + min);
|
|
||||||
END; $$;
|
|
||||||
|
|
||||||
select * from randomInRange(0, 4);
|
|
||||||
|
|
||||||
|
|
||||||
-- ========================================================
|
|
||||||
-- Test helpers
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
-- there are some random ractors in test data generation, thus a range has to be accepted
|
|
||||||
CREATE OR REPLACE PROCEDURE expectBetween(actualCount integer, expectedFrom integer, expectedTo integer)
|
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT actualCount BETWEEN expectedFrom AND expectedTo THEN
|
|
||||||
RAISE EXCEPTION 'count expected to be between % and %, but got %', expectedFrom, expectedTo, actualCount;
|
|
||||||
END IF;
|
|
||||||
END; $$;
|
|
@ -1,6 +1,15 @@
|
|||||||
ABORT;
|
ABORT;
|
||||||
SET SESSION SESSION AUTHORIZATION DEFAULT;
|
SET SESSION SESSION AUTHORIZATION DEFAULT;
|
||||||
|
|
||||||
|
-- there are some random ractors in test data generation, thus a range has to be accepted
|
||||||
|
CREATE OR REPLACE PROCEDURE expectBetween(actualCount integer, expectedFrom integer, expectedTo integer)
|
||||||
|
LANGUAGE plpgsql AS $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT actualCount BETWEEN expectedFrom AND expectedTo THEN
|
||||||
|
RAISE EXCEPTION 'count expected to be between % and %, but got %', expectedFrom, expectedTo, actualCount;
|
||||||
|
END IF;
|
||||||
|
END; $$;
|
||||||
|
|
||||||
DO LANGUAGE plpgsql $$
|
DO LANGUAGE plpgsql $$
|
||||||
DECLARE
|
DECLARE
|
||||||
resultCount integer;
|
resultCount integer;
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
--liquibase formatted sql
|
||||||
|
|
||||||
|
--changeset template:1 endDelimiter:--//
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
--//
|
@ -0,0 +1,18 @@
|
|||||||
|
--liquibase formatted sql
|
||||||
|
|
||||||
|
--changeset last-row-count:1 endDelimiter:--//
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns the row count from the result of the previous query.
|
||||||
|
Other than the native statement it's usable in an expression.
|
||||||
|
*/
|
||||||
|
create or replace function lastRowCount()
|
||||||
|
returns bigint
|
||||||
|
language plpgsql as $$
|
||||||
|
declare
|
||||||
|
lastRowCount bigint;
|
||||||
|
begin
|
||||||
|
get diagnostics lastrowCount = row_count;
|
||||||
|
return lastRowCount;
|
||||||
|
end; $$;
|
||||||
|
--//
|
@ -0,0 +1,25 @@
|
|||||||
|
--liquibase formatted sql
|
||||||
|
|
||||||
|
--changeset int-to-var:1 endDelimiter:--//
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns a textual representation of an integer number to be used as generated test data.
|
||||||
|
|
||||||
|
Examples :
|
||||||
|
intToVarChar(0, 3) => 'aaa'
|
||||||
|
intToVarChar(1, 3) => 'aab'
|
||||||
|
*/
|
||||||
|
create or replace function intToVarChar(i integer, len integer)
|
||||||
|
returns varchar
|
||||||
|
language plpgsql as $$
|
||||||
|
declare
|
||||||
|
partial varchar;
|
||||||
|
begin
|
||||||
|
select chr(ascii('a') + i%26) into partial;
|
||||||
|
if len > 1 then
|
||||||
|
return intToVarChar(i/26, len-1) || partial;
|
||||||
|
else
|
||||||
|
return partial;
|
||||||
|
end if;
|
||||||
|
END; $$;
|
||||||
|
--//
|
@ -0,0 +1,23 @@
|
|||||||
|
--liquibase formatted sql
|
||||||
|
|
||||||
|
--changeset random-in-range:1 endDelimiter:--//
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns a random integer in the given range (both included),
|
||||||
|
to be used for test data generation.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
randomInRange(0, 4) might return any of 0, 1, 2, 3, 4
|
||||||
|
*/
|
||||||
|
create or replace function randomInRange(min integer, max integer)
|
||||||
|
returns integer
|
||||||
|
returns null on null input
|
||||||
|
language 'plpgsql' AS $$
|
||||||
|
begin
|
||||||
|
return floor(random() * (max-min + 1) + min);
|
||||||
|
end; $$;
|
||||||
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
--liquibase formatted sql
|
||||||
|
|
||||||
|
--changeset uuid-ossp-extension:1 endDelimiter:--//
|
||||||
|
|
||||||
|
/*
|
||||||
|
Makes improved uuid generation available.
|
||||||
|
*/
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
--//
|
@ -7,14 +7,12 @@ SET SESSION SESSION AUTHORIZATION DEFAULT;
|
|||||||
|
|
||||||
-- https://arctype.com/blog/postgres-uuid/#creating-a-uuid-primary-key-using-uuid-osp-postgresql-example
|
-- https://arctype.com/blog/postgres-uuid/#creating-a-uuid-primary-key-using-uuid-osp-postgresql-example
|
||||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
--liquibase formatted sql
|
||||||
|
|
||||||
DROP TABLE IF EXISTS "RbacPermission";
|
--changeset rbac-base-reference:1 endDelimiter:--//
|
||||||
DROP TABLE IF EXISTS "RbacGrants";
|
/*
|
||||||
DROP TABLE IF EXISTS "RbacUser";
|
|
||||||
DROP TABLE IF EXISTS RbacReference CASCADE;
|
|
||||||
DROP TYPE IF EXISTS RbacOp CASCADE;
|
|
||||||
DROP TYPE IF EXISTS ReferenceType CASCADE;
|
|
||||||
|
|
||||||
|
*/
|
||||||
CREATE TYPE ReferenceType AS ENUM ('RbacUser', 'RbacRole', 'RbacPermission');
|
CREATE TYPE ReferenceType AS ENUM ('RbacUser', 'RbacRole', 'RbacPermission');
|
||||||
|
|
||||||
CREATE TABLE RbacReference
|
CREATE TABLE RbacReference
|
||||||
@ -23,88 +21,31 @@ CREATE TABLE RbacReference
|
|||||||
type ReferenceType not null
|
type ReferenceType not null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION assertReferenceType(argument varchar, referenceId uuid, expectedType ReferenceType)
|
||||||
|
RETURNS ReferenceType
|
||||||
|
LANGUAGE plpgsql AS $$
|
||||||
|
DECLARE
|
||||||
|
actualType ReferenceType;
|
||||||
|
BEGIN
|
||||||
|
actualType = (SELECT type FROM RbacReference WHERE uuid=referenceId);
|
||||||
|
IF ( actualType <> expectedType ) THEN
|
||||||
|
RAISE EXCEPTION '% must reference a %, but got a %', argument, expectedType, actualType;
|
||||||
|
end if;
|
||||||
|
RETURN expectedType;
|
||||||
|
END; $$;
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
|
--changeset rbac-base-user:1 endDelimiter:--//
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
CREATE TABLE RbacUser
|
CREATE TABLE RbacUser
|
||||||
(
|
(
|
||||||
uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE,
|
uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE,
|
||||||
name varchar(63) not null unique
|
name varchar(63) not null unique
|
||||||
);
|
);
|
||||||
|
|
||||||
-- DROP TABLE IF EXISTS RbacObject;
|
|
||||||
CREATE TABLE RbacObject
|
|
||||||
(
|
|
||||||
uuid uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
||||||
objectTable varchar(64) not null,
|
|
||||||
unique (objectTable, uuid)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TYPE RbacRoleType AS ENUM ('owner', 'admin', 'tenant');
|
|
||||||
|
|
||||||
CREATE TABLE RbacRole
|
|
||||||
(
|
|
||||||
uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE,
|
|
||||||
objectUuid uuid references RbacObject(uuid) not null,
|
|
||||||
roleType RbacRoleType not null
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE RbacGrants
|
|
||||||
(
|
|
||||||
ascendantUuid uuid references RbacReference (uuid) ON DELETE CASCADE,
|
|
||||||
descendantUuid uuid references RbacReference (uuid) ON DELETE CASCADE,
|
|
||||||
follow boolean not null default true,
|
|
||||||
primary key (ascendantUuid, descendantUuid)
|
|
||||||
);
|
|
||||||
CREATE INDEX ON RbacGrants (ascendantUuid);
|
|
||||||
CREATE INDEX ON RbacGrants (descendantUuid);
|
|
||||||
|
|
||||||
-- DROP DOMAIN IF EXISTS RbacOp CASCADE;
|
|
||||||
CREATE DOMAIN RbacOp AS VARCHAR(67)
|
|
||||||
CHECK(
|
|
||||||
VALUE = '*'
|
|
||||||
OR VALUE = 'delete'
|
|
||||||
OR VALUE = 'edit'
|
|
||||||
OR VALUE = 'view'
|
|
||||||
OR VALUE = 'assume'
|
|
||||||
OR VALUE ~ '^add-[a-z]+$'
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION createRbacObject()
|
|
||||||
RETURNS trigger
|
|
||||||
LANGUAGE plpgsql STRICT AS $$
|
|
||||||
DECLARE
|
|
||||||
objectUuid uuid;
|
|
||||||
BEGIN
|
|
||||||
IF TG_OP = 'INSERT' THEN
|
|
||||||
INSERT INTO RbacObject (objectTable) VALUES (TG_TABLE_NAME) RETURNING uuid INTO objectUuid;
|
|
||||||
NEW.uuid = objectUuid;
|
|
||||||
RETURN NEW;
|
|
||||||
ELSE
|
|
||||||
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
|
|
||||||
END IF;
|
|
||||||
END; $$;
|
|
||||||
|
|
||||||
|
|
||||||
-- DROP TABLE IF EXISTS RbacPermission;
|
|
||||||
CREATE TABLE RbacPermission
|
|
||||||
( uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE,
|
|
||||||
objectUuid uuid not null references RbacObject,
|
|
||||||
op RbacOp not null,
|
|
||||||
unique (objectUuid, op)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- SET SESSION SESSION AUTHORIZATION DEFAULT;
|
|
||||||
-- alter table rbacpermission add constraint rbacpermission_objectuuid_fkey foreign key (objectUuid) references rbacobject(uuid);
|
|
||||||
-- alter table rbacpermission drop constraint rbacpermission_objectuuid;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION hasPermission(forObjectUuid uuid, forOp RbacOp)
|
|
||||||
RETURNS bool
|
|
||||||
LANGUAGE sql AS $$
|
|
||||||
SELECT EXISTS (
|
|
||||||
SELECT op
|
|
||||||
FROM RbacPermission p
|
|
||||||
WHERE p.objectUuid=forObjectUuid AND p.op in ('*', forOp)
|
|
||||||
);
|
|
||||||
$$;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION createRbacUser(userName varchar)
|
CREATE OR REPLACE FUNCTION createRbacUser(userName varchar)
|
||||||
RETURNS uuid
|
RETURNS uuid
|
||||||
RETURNS NULL ON NULL INPUT
|
RETURNS NULL ON NULL INPUT
|
||||||
@ -147,6 +88,51 @@ BEGIN
|
|||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
|
--changeset rbac-base-object:1 endDelimiter:--//
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
CREATE TABLE RbacObject
|
||||||
|
(
|
||||||
|
uuid uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
objectTable varchar(64) not null,
|
||||||
|
unique (objectTable, uuid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION createRbacObject()
|
||||||
|
RETURNS trigger
|
||||||
|
LANGUAGE plpgsql STRICT AS $$
|
||||||
|
DECLARE
|
||||||
|
objectUuid uuid;
|
||||||
|
BEGIN
|
||||||
|
IF TG_OP = 'INSERT' THEN
|
||||||
|
INSERT INTO RbacObject (objectTable) VALUES (TG_TABLE_NAME) RETURNING uuid INTO objectUuid;
|
||||||
|
NEW.uuid = objectUuid;
|
||||||
|
RETURN NEW;
|
||||||
|
ELSE
|
||||||
|
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
|
||||||
|
END IF;
|
||||||
|
END; $$;
|
||||||
|
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
|
--changeset rbac-base-role:1 endDelimiter:--//
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
CREATE TYPE RbacRoleType AS ENUM ('owner', 'admin', 'tenant');
|
||||||
|
|
||||||
|
CREATE TABLE RbacRole
|
||||||
|
(
|
||||||
|
uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE,
|
||||||
|
objectUuid uuid references RbacObject(uuid) not null,
|
||||||
|
roleType RbacRoleType not null
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TYPE RbacRoleDescriptor AS
|
CREATE TYPE RbacRoleDescriptor AS
|
||||||
(
|
(
|
||||||
objectTable varchar(63), -- TODO: needed? remove?
|
objectTable varchar(63), -- TODO: needed? remove?
|
||||||
@ -154,32 +140,6 @@ CREATE TYPE RbacRoleDescriptor AS
|
|||||||
roleType RbacRoleType
|
roleType RbacRoleType
|
||||||
);
|
);
|
||||||
|
|
||||||
-- TODO: this ...
|
|
||||||
CREATE OR REPLACE FUNCTION roleDescriptor(objectTable varchar(63), objectUuid uuid, roleType RbacRoleType )
|
|
||||||
RETURNS RbacRoleDescriptor
|
|
||||||
RETURNS NULL ON NULL INPUT
|
|
||||||
STABLE LEAKPROOF
|
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
BEGIN
|
|
||||||
RETURN ROW(objectTable, objectUuid, roleType);
|
|
||||||
END; $$;
|
|
||||||
|
|
||||||
CREATE FUNCTION new_emp() RETURNS emp AS $$
|
|
||||||
SELECT text 'None' AS name,
|
|
||||||
1000.0 AS salary,
|
|
||||||
25 AS age,
|
|
||||||
point '(2,2)' AS cubicle;
|
|
||||||
$$ LANGUAGE SQL;
|
|
||||||
|
|
||||||
DO LANGUAGE plpgsql $$
|
|
||||||
DECLARE
|
|
||||||
roleDesc RbacRoleDescriptor;
|
|
||||||
BEGIN
|
|
||||||
select * FROM roleDescriptor('global', gen_random_uuid(), 'admin') into roleDesc;
|
|
||||||
RAISE NOTICE 'result: % % %', roleDesc.objecttable, roleDesc.objectuuid, roleDesc.roletype;
|
|
||||||
END; $$;
|
|
||||||
|
|
||||||
-- TODO: ... or that?
|
|
||||||
CREATE OR REPLACE FUNCTION roleDescriptor(objectTable varchar(63), objectUuid uuid, roleType RbacRoleType )
|
CREATE OR REPLACE FUNCTION roleDescriptor(objectTable varchar(63), objectUuid uuid, roleType RbacRoleType )
|
||||||
RETURNS RbacRoleDescriptor
|
RETURNS RbacRoleDescriptor
|
||||||
RETURNS NULL ON NULL INPUT
|
RETURNS NULL ON NULL INPUT
|
||||||
@ -239,7 +199,41 @@ BEGIN
|
|||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
-- select getRoleId('hostmaster', 'create');
|
--changeset rbac-base-permission:1 endDelimiter:--//
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
CREATE DOMAIN RbacOp AS VARCHAR(67)
|
||||||
|
CHECK(
|
||||||
|
VALUE = '*'
|
||||||
|
OR VALUE = 'delete'
|
||||||
|
OR VALUE = 'edit'
|
||||||
|
OR VALUE = 'view'
|
||||||
|
OR VALUE = 'assume'
|
||||||
|
OR VALUE ~ '^add-[a-z]+$'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- DROP TABLE IF EXISTS RbacPermission;
|
||||||
|
CREATE TABLE RbacPermission
|
||||||
|
( uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE,
|
||||||
|
objectUuid uuid not null references RbacObject,
|
||||||
|
op RbacOp not null,
|
||||||
|
unique (objectUuid, op)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- SET SESSION SESSION AUTHORIZATION DEFAULT;
|
||||||
|
-- alter table rbacpermission add constraint rbacpermission_objectuuid_fkey foreign key (objectUuid) references rbacobject(uuid);
|
||||||
|
-- alter table rbacpermission drop constraint rbacpermission_objectuuid;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION hasPermission(forObjectUuid uuid, forOp RbacOp)
|
||||||
|
RETURNS bool
|
||||||
|
LANGUAGE sql AS $$
|
||||||
|
SELECT EXISTS (
|
||||||
|
SELECT op
|
||||||
|
FROM RbacPermission p
|
||||||
|
WHERE p.objectUuid=forObjectUuid AND p.op in ('*', forOp)
|
||||||
|
);
|
||||||
|
$$;
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION createPermissions(forObjectUuid uuid, permitOps RbacOp[])
|
CREATE OR REPLACE FUNCTION createPermissions(forObjectUuid uuid, permitOps RbacOp[])
|
||||||
RETURNS uuid[]
|
RETURNS uuid[]
|
||||||
@ -281,260 +275,24 @@ CREATE OR REPLACE FUNCTION findPermissionId(forObjectUuid uuid, forOp RbacOp)
|
|||||||
WHERE p.objectUuid=forObjectUuid AND p.op in ('*', forOp)
|
WHERE p.objectUuid=forObjectUuid AND p.op in ('*', forOp)
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION assertReferenceType(argument varchar, referenceId uuid, expectedType ReferenceType)
|
--//
|
||||||
RETURNS ReferenceType
|
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
DECLARE
|
|
||||||
actualType ReferenceType;
|
|
||||||
BEGIN
|
|
||||||
actualType = (SELECT type FROM RbacReference WHERE uuid=referenceId);
|
|
||||||
IF ( actualType <> expectedType ) THEN
|
|
||||||
RAISE EXCEPTION '% must reference a %, but got a %', argument, expectedType, actualType;
|
|
||||||
end if;
|
|
||||||
RETURN expectedType;
|
|
||||||
END; $$;
|
|
||||||
|
|
||||||
CREATE OR REPLACE PROCEDURE grantPermissionsToRole(roleUuid uuid, permissionIds uuid[])
|
--changeset rbac-base-grants:1 endDelimiter:--//
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
BEGIN
|
|
||||||
RAISE NOTICE 'grantPermissionsToRole: % -> %', roleUuid, permissionIds;
|
|
||||||
FOR i IN array_lower(permissionIds, 1)..array_upper(permissionIds, 1) LOOP
|
|
||||||
perform assertReferenceType('roleId (ascendant)', roleUuid, 'RbacRole');
|
|
||||||
perform assertReferenceType('permissionId (descendant)', permissionIds[i], 'RbacPermission');
|
|
||||||
|
|
||||||
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (roleId, permissionIds[i], true); -- assumeV1
|
|
||||||
INSERT INTO RbacGrants (ascendantUuid, descendantUuid) VALUES (roleUuid, permissionIds[i]);
|
|
||||||
END LOOP;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
|
|
||||||
CREATE OR REPLACE PROCEDURE grantRoleToRole(subRoleId uuid, superRoleId uuid, doFollow bool = true )
|
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
BEGIN
|
|
||||||
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
|
|
||||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
|
||||||
|
|
||||||
IF ( isGranted(subRoleId, superRoleId) ) THEN
|
|
||||||
RAISE EXCEPTION 'Cyclic role grant detected between % and %', subRoleId, superRoleId;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (superRoleId, subRoleId, doapply); -- assumeV1
|
|
||||||
INSERT INTO RbacGrants (ascendantUuid, descendantUuid, follow) VALUES (superRoleId, subRoleId, doFollow)
|
|
||||||
ON CONFLICT DO NOTHING ; -- TODO: remove?
|
|
||||||
END; $$;
|
|
||||||
|
|
||||||
CREATE OR REPLACE PROCEDURE revokeRoleFromRole(subRoleId uuid, superRoleId uuid)
|
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
BEGIN
|
|
||||||
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
|
|
||||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
|
||||||
|
|
||||||
IF ( isGranted(subRoleId, superRoleId) ) THEN
|
|
||||||
DELETE FROM RbacGrants WHERE ascendantUuid=superRoleId AND descendantUuid=subRoleId;
|
|
||||||
END IF;
|
|
||||||
END; $$;
|
|
||||||
|
|
||||||
CREATE OR REPLACE PROCEDURE grantRoleToUser(roleId uuid, userId uuid)
|
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
BEGIN
|
|
||||||
perform assertReferenceType('roleId (ascendant)', roleId, 'RbacRole');
|
|
||||||
perform assertReferenceType('userId (descendant)', userId, 'RbacUser');
|
|
||||||
|
|
||||||
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (userId, roleId, true); -- assumeV1
|
|
||||||
INSERT INTO RbacGrants (ascendantUuid, descendantUuid) VALUES (userId, roleId)
|
|
||||||
ON CONFLICT DO NOTHING ; -- TODO: remove?
|
|
||||||
END; $$;
|
|
||||||
|
|
||||||
abort;
|
|
||||||
set local session authorization default;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION queryAccessibleObjectUuidsOfSubjectIds(
|
|
||||||
requiredOp RbacOp,
|
|
||||||
forObjectTable varchar, -- reduces the result set, but is not really faster when used in restricted view
|
|
||||||
subjectIds uuid[],
|
|
||||||
maxObjects integer = 8000)
|
|
||||||
RETURNS SETOF uuid
|
|
||||||
RETURNS NULL ON NULL INPUT
|
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
DECLARE
|
|
||||||
foundRows bigint;
|
|
||||||
BEGIN
|
|
||||||
RETURN QUERY SELECT DISTINCT perm.objectUuid
|
|
||||||
FROM (
|
|
||||||
WITH RECURSIVE grants AS (
|
|
||||||
SELECT descendantUuid, ascendantUuid, 1 AS level
|
|
||||||
FROM RbacGrants
|
|
||||||
WHERE follow AND ascendantUuid = ANY(subjectIds)
|
|
||||||
UNION DISTINCT
|
|
||||||
SELECT "grant".descendantUuid, "grant".ascendantUuid, level+1 AS level
|
|
||||||
FROM RbacGrants "grant"
|
|
||||||
INNER JOIN grants recur ON recur.descendantUuid = "grant".ascendantUuid
|
|
||||||
WHERE follow
|
|
||||||
) SELECT descendantUuid
|
|
||||||
FROM grants
|
|
||||||
) as granted
|
|
||||||
JOIN RbacPermission perm
|
|
||||||
ON granted.descendantUuid=perm.uuid AND perm.op IN ('*', requiredOp)
|
|
||||||
JOIN RbacObject obj ON obj.uuid=perm.objectUuid AND obj.objectTable=forObjectTable
|
|
||||||
LIMIT maxObjects+1;
|
|
||||||
|
|
||||||
foundRows = lastRowCount();
|
|
||||||
IF foundRows > maxObjects THEN
|
|
||||||
RAISE EXCEPTION 'Too many accessible objects, limit is %, found %.', maxObjects, foundRows
|
|
||||||
USING
|
|
||||||
ERRCODE = 'P0003',
|
|
||||||
HINT = 'Please assume a sub-role and try again.';
|
|
||||||
END IF;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
|
|
||||||
SET SESSION AUTHORIZATION DEFAULT;
|
|
||||||
CREATE ROLE admin;
|
|
||||||
GRANT USAGE ON SCHEMA public TO admin;
|
|
||||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin;
|
|
||||||
CREATE ROLE restricted;
|
|
||||||
GRANT USAGE ON SCHEMA public TO restricted;
|
|
||||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO restricted;
|
|
||||||
|
|
||||||
abort;
|
|
||||||
set local session authorization restricted;
|
|
||||||
begin transaction;
|
|
||||||
set local statement_timeout TO '15s';
|
|
||||||
select count(*)
|
|
||||||
from queryAccessibleObjectUuidsOfSubjectIds('view', 'customer', ARRAY[findRbacUserId('mike@hostsharing.net')], 10000);
|
|
||||||
end transaction;
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
abort;
|
|
||||||
set local session authorization default;
|
|
||||||
CREATE OR REPLACE FUNCTION queryRequiredPermissionsOfSubjectIds(requiredOp RbacOp, subjectIds uuid[])
|
|
||||||
RETURNS SETOF RbacPermission
|
|
||||||
STRICT
|
|
||||||
LANGUAGE sql AS $$
|
|
||||||
SELECT DISTINCT *
|
|
||||||
FROM RbacPermission
|
|
||||||
WHERE op = '*' OR op = requiredOp
|
|
||||||
AND uuid IN (
|
|
||||||
WITH RECURSIVE grants AS (
|
|
||||||
SELECT DISTINCT
|
|
||||||
descendantUuid,
|
|
||||||
ascendantUuid
|
|
||||||
FROM RbacGrants
|
|
||||||
WHERE
|
|
||||||
ascendantUuid = ANY(subjectIds)
|
|
||||||
UNION ALL
|
|
||||||
SELECT
|
|
||||||
"grant".descendantUuid,
|
|
||||||
"grant".ascendantUuid
|
|
||||||
FROM RbacGrants "grant"
|
|
||||||
INNER JOIN grants recur ON recur.descendantUuid = "grant".ascendantUuid
|
|
||||||
) SELECT
|
|
||||||
descendantUuid
|
|
||||||
FROM grants
|
|
||||||
);
|
|
||||||
$$;
|
|
||||||
|
|
||||||
abort;
|
|
||||||
set local session authorization restricted;
|
|
||||||
begin transaction;
|
|
||||||
-- set local statement_timeout TO '5s';
|
|
||||||
set local statement_timeout TO '5min';
|
|
||||||
select count(*) from queryRequiredPermissionsOfSubjectIds('view', ARRAY[findRbacUserId('mike@hostsharing.net')]);
|
|
||||||
end transaction;
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
abort;
|
|
||||||
set local session authorization default;
|
|
||||||
CREATE OR REPLACE FUNCTION queryAllPermissionsOfSubjectIds(subjectIds uuid[])
|
|
||||||
RETURNS SETOF RbacPermission
|
|
||||||
STRICT
|
|
||||||
LANGUAGE sql AS $$
|
|
||||||
SELECT DISTINCT * FROM RbacPermission WHERE uuid IN (
|
|
||||||
WITH RECURSIVE grants AS (
|
|
||||||
SELECT DISTINCT
|
|
||||||
descendantUuid,
|
|
||||||
ascendantUuid
|
|
||||||
FROM RbacGrants
|
|
||||||
WHERE
|
|
||||||
ascendantUuid = ANY(subjectIds)
|
|
||||||
UNION ALL
|
|
||||||
SELECT
|
|
||||||
"grant".descendantUuid,
|
|
||||||
"grant".ascendantUuid
|
|
||||||
FROM RbacGrants "grant"
|
|
||||||
INNER JOIN grants recur ON recur.descendantUuid = "grant".ascendantUuid
|
|
||||||
) SELECT
|
|
||||||
descendantUuid
|
|
||||||
FROM grants
|
|
||||||
);
|
|
||||||
$$;
|
|
||||||
|
|
||||||
abort;
|
|
||||||
set local session authorization restricted;
|
|
||||||
begin transaction;
|
|
||||||
set local statement_timeout TO '5s';
|
|
||||||
select count(*) from queryAllPermissionsOfSubjectIds(ARRAY[findRbacUserId('mike@hostsharing.net')]);
|
|
||||||
end transaction;
|
|
||||||
|
|
||||||
---
|
|
||||||
/*
|
/*
|
||||||
CREATE OR REPLACE FUNCTION queryAllPermissionsOfSubjectId(subjectId uuid) -- TODO: remove?
|
|
||||||
RETURNS SETOF RbacPermission
|
*/
|
||||||
RETURNS NULL ON NULL INPUT
|
CREATE TABLE RbacGrants
|
||||||
LANGUAGE sql AS $$
|
(
|
||||||
SELECT * FROM RbacPermission WHERE uuid IN (
|
ascendantUuid uuid references RbacReference (uuid) ON DELETE CASCADE,
|
||||||
WITH RECURSIVE grants AS (
|
descendantUuid uuid references RbacReference (uuid) ON DELETE CASCADE,
|
||||||
SELECT
|
follow boolean not null default true,
|
||||||
descendantUuid,
|
primary key (ascendantUuid, descendantUuid)
|
||||||
ascendantUuid
|
|
||||||
FROM
|
|
||||||
RbacGrants
|
|
||||||
WHERE
|
|
||||||
ascendantUuid = subjectId
|
|
||||||
UNION ALL
|
|
||||||
SELECT
|
|
||||||
"grant".descendantUuid,
|
|
||||||
"grant".ascendantUuid
|
|
||||||
FROM RbacGrants "grant"
|
|
||||||
INNER JOIN grants recur ON recur.descendantUuid = "grant".ascendantUuid
|
|
||||||
) SELECT
|
|
||||||
descendantUuid
|
|
||||||
FROM
|
|
||||||
grants
|
|
||||||
);
|
);
|
||||||
$$;*/
|
CREATE INDEX ON RbacGrants (ascendantUuid);
|
||||||
|
CREATE INDEX ON RbacGrants (descendantUuid);
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION queryAllRbacUsersWithPermissionsFor(objectId uuid)
|
|
||||||
RETURNS SETOF RbacUser
|
|
||||||
RETURNS NULL ON NULL INPUT
|
|
||||||
LANGUAGE sql AS $$
|
|
||||||
SELECT * FROM RbacUser WHERE uuid IN (
|
|
||||||
WITH RECURSIVE grants AS (
|
|
||||||
SELECT
|
|
||||||
descendantUuid,
|
|
||||||
ascendantUuid
|
|
||||||
FROM
|
|
||||||
RbacGrants
|
|
||||||
WHERE
|
|
||||||
descendantUuid = objectId
|
|
||||||
UNION ALL
|
|
||||||
SELECT
|
|
||||||
"grant".descendantUuid,
|
|
||||||
"grant".ascendantUuid
|
|
||||||
FROM
|
|
||||||
RbacGrants "grant"
|
|
||||||
INNER JOIN grants recur ON recur.ascendantUuid = "grant".descendantUuid
|
|
||||||
) SELECT
|
|
||||||
ascendantUuid
|
|
||||||
FROM
|
|
||||||
grants
|
|
||||||
);
|
|
||||||
$$;
|
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION findGrantees(grantedId uuid)
|
CREATE OR REPLACE FUNCTION findGrantees(grantedId uuid)
|
||||||
RETURNS SETOF RbacReference
|
RETURNS SETOF RbacReference
|
||||||
@ -615,10 +373,175 @@ CREATE OR REPLACE FUNCTION isPermissionGrantedToSubject(permissionId uuid, subje
|
|||||||
);
|
);
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
-- ========================================================
|
CREATE OR REPLACE PROCEDURE grantPermissionsToRole(roleUuid uuid, permissionIds uuid[])
|
||||||
-- current user + assumed roles
|
LANGUAGE plpgsql AS $$
|
||||||
-- --------------------------------------------------------
|
BEGIN
|
||||||
|
RAISE NOTICE 'grantPermissionsToRole: % -> %', roleUuid, permissionIds;
|
||||||
|
FOR i IN array_lower(permissionIds, 1)..array_upper(permissionIds, 1) LOOP
|
||||||
|
perform assertReferenceType('roleId (ascendant)', roleUuid, 'RbacRole');
|
||||||
|
perform assertReferenceType('permissionId (descendant)', permissionIds[i], 'RbacPermission');
|
||||||
|
|
||||||
|
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (roleId, permissionIds[i], true); -- assumeV1
|
||||||
|
INSERT INTO RbacGrants (ascendantUuid, descendantUuid) VALUES (roleUuid, permissionIds[i]);
|
||||||
|
END LOOP;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
CREATE OR REPLACE PROCEDURE grantRoleToRole(subRoleId uuid, superRoleId uuid, doFollow bool = true )
|
||||||
|
LANGUAGE plpgsql AS $$
|
||||||
|
BEGIN
|
||||||
|
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
|
||||||
|
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||||
|
|
||||||
|
IF ( isGranted(subRoleId, superRoleId) ) THEN
|
||||||
|
RAISE EXCEPTION 'Cyclic role grant detected between % and %', subRoleId, superRoleId;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (superRoleId, subRoleId, doapply); -- assumeV1
|
||||||
|
INSERT INTO RbacGrants (ascendantUuid, descendantUuid, follow) VALUES (superRoleId, subRoleId, doFollow)
|
||||||
|
ON CONFLICT DO NOTHING ; -- TODO: remove?
|
||||||
|
END; $$;
|
||||||
|
|
||||||
|
CREATE OR REPLACE PROCEDURE revokeRoleFromRole(subRoleId uuid, superRoleId uuid)
|
||||||
|
LANGUAGE plpgsql AS $$
|
||||||
|
BEGIN
|
||||||
|
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
|
||||||
|
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||||
|
|
||||||
|
IF ( isGranted(subRoleId, superRoleId) ) THEN
|
||||||
|
DELETE FROM RbacGrants WHERE ascendantUuid=superRoleId AND descendantUuid=subRoleId;
|
||||||
|
END IF;
|
||||||
|
END; $$;
|
||||||
|
|
||||||
|
CREATE OR REPLACE PROCEDURE grantRoleToUser(roleId uuid, userId uuid)
|
||||||
|
LANGUAGE plpgsql AS $$
|
||||||
|
BEGIN
|
||||||
|
perform assertReferenceType('roleId (ascendant)', roleId, 'RbacRole');
|
||||||
|
perform assertReferenceType('userId (descendant)', userId, 'RbacUser');
|
||||||
|
|
||||||
|
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (userId, roleId, true); -- assumeV1
|
||||||
|
INSERT INTO RbacGrants (ascendantUuid, descendantUuid) VALUES (userId, roleId)
|
||||||
|
ON CONFLICT DO NOTHING ; -- TODO: remove?
|
||||||
|
END; $$;
|
||||||
|
--//
|
||||||
|
|
||||||
|
--changeset rbac-base-query-accessible-object-uuids:1 endDelimiter:--//
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
CREATE OR REPLACE FUNCTION queryAccessibleObjectUuidsOfSubjectIds(
|
||||||
|
requiredOp RbacOp,
|
||||||
|
forObjectTable varchar, -- reduces the result set, but is not really faster when used in restricted view
|
||||||
|
subjectIds uuid[],
|
||||||
|
maxObjects integer = 8000)
|
||||||
|
RETURNS SETOF uuid
|
||||||
|
RETURNS NULL ON NULL INPUT
|
||||||
|
LANGUAGE plpgsql AS $$
|
||||||
|
DECLARE
|
||||||
|
foundRows bigint;
|
||||||
|
BEGIN
|
||||||
|
RETURN QUERY SELECT DISTINCT perm.objectUuid
|
||||||
|
FROM (
|
||||||
|
WITH RECURSIVE grants AS (
|
||||||
|
SELECT descendantUuid, ascendantUuid, 1 AS level
|
||||||
|
FROM RbacGrants
|
||||||
|
WHERE follow AND ascendantUuid = ANY(subjectIds)
|
||||||
|
UNION DISTINCT
|
||||||
|
SELECT "grant".descendantUuid, "grant".ascendantUuid, level+1 AS level
|
||||||
|
FROM RbacGrants "grant"
|
||||||
|
INNER JOIN grants recur ON recur.descendantUuid = "grant".ascendantUuid
|
||||||
|
WHERE follow
|
||||||
|
) SELECT descendantUuid
|
||||||
|
FROM grants
|
||||||
|
) as granted
|
||||||
|
JOIN RbacPermission perm
|
||||||
|
ON granted.descendantUuid=perm.uuid AND perm.op IN ('*', requiredOp)
|
||||||
|
JOIN RbacObject obj ON obj.uuid=perm.objectUuid AND obj.objectTable=forObjectTable
|
||||||
|
LIMIT maxObjects+1;
|
||||||
|
|
||||||
|
foundRows = lastRowCount();
|
||||||
|
IF foundRows > maxObjects THEN
|
||||||
|
RAISE EXCEPTION 'Too many accessible objects, limit is %, found %.', maxObjects, foundRows
|
||||||
|
USING
|
||||||
|
ERRCODE = 'P0003',
|
||||||
|
HINT = 'Please assume a sub-role and try again.';
|
||||||
|
END IF;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
|
--changeset rbac-base-query-granted-permissions:1 endDelimiter:--//
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
CREATE OR REPLACE FUNCTION queryGrantedPermissionsOfSubjectIds(requiredOp RbacOp, subjectIds uuid[])
|
||||||
|
RETURNS SETOF RbacPermission
|
||||||
|
STRICT
|
||||||
|
LANGUAGE sql AS $$
|
||||||
|
SELECT DISTINCT *
|
||||||
|
FROM RbacPermission
|
||||||
|
WHERE op = '*' OR op = requiredOp
|
||||||
|
AND uuid IN (
|
||||||
|
WITH RECURSIVE grants AS (
|
||||||
|
SELECT DISTINCT
|
||||||
|
descendantUuid,
|
||||||
|
ascendantUuid
|
||||||
|
FROM RbacGrants
|
||||||
|
WHERE
|
||||||
|
ascendantUuid = ANY(subjectIds)
|
||||||
|
UNION ALL
|
||||||
|
SELECT
|
||||||
|
"grant".descendantUuid,
|
||||||
|
"grant".ascendantUuid
|
||||||
|
FROM RbacGrants "grant"
|
||||||
|
INNER JOIN grants recur ON recur.descendantUuid = "grant".ascendantUuid
|
||||||
|
) SELECT
|
||||||
|
descendantUuid
|
||||||
|
FROM grants
|
||||||
|
);
|
||||||
|
$$;
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
|
--changeset rbac-base-query-users-with-permission-for-object:1 endDelimiter:--//
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION queryAllRbacUsersWithPermissionsFor(objectId uuid)
|
||||||
|
RETURNS SETOF RbacUser
|
||||||
|
RETURNS NULL ON NULL INPUT
|
||||||
|
LANGUAGE sql AS $$
|
||||||
|
SELECT * FROM RbacUser WHERE uuid IN (
|
||||||
|
WITH RECURSIVE grants AS (
|
||||||
|
SELECT
|
||||||
|
descendantUuid,
|
||||||
|
ascendantUuid
|
||||||
|
FROM
|
||||||
|
RbacGrants
|
||||||
|
WHERE
|
||||||
|
descendantUuid = objectId
|
||||||
|
UNION ALL
|
||||||
|
SELECT
|
||||||
|
"grant".descendantUuid,
|
||||||
|
"grant".ascendantUuid
|
||||||
|
FROM
|
||||||
|
RbacGrants "grant"
|
||||||
|
INNER JOIN grants recur ON recur.ascendantUuid = "grant".descendantUuid
|
||||||
|
) SELECT
|
||||||
|
ascendantUuid
|
||||||
|
FROM
|
||||||
|
grants
|
||||||
|
);
|
||||||
|
$$;
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
|
--changeset rbac-current-user:1 endDelimiter:--//
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
CREATE OR REPLACE FUNCTION currentUser()
|
CREATE OR REPLACE FUNCTION currentUser()
|
||||||
RETURNS varchar(63)
|
RETURNS varchar(63)
|
||||||
STABLE LEAKPROOF
|
STABLE LEAKPROOF
|
||||||
@ -637,7 +560,6 @@ BEGIN
|
|||||||
RETURN currentUser;
|
RETURN currentUser;
|
||||||
END; $$;
|
END; $$;
|
||||||
|
|
||||||
SET SESSION AUTHORIZATION DEFAULT;
|
|
||||||
CREATE OR REPLACE FUNCTION currentUserId()
|
CREATE OR REPLACE FUNCTION currentUserId()
|
||||||
RETURNS uuid
|
RETURNS uuid
|
||||||
STABLE LEAKPROOF
|
STABLE LEAKPROOF
|
||||||
@ -652,6 +574,12 @@ BEGIN
|
|||||||
END; $$;
|
END; $$;
|
||||||
|
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
|
--changeset rbac-assumed-roles:1 endDelimiter:--//
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
CREATE OR REPLACE FUNCTION assumedRoles()
|
CREATE OR REPLACE FUNCTION assumedRoles()
|
||||||
RETURNS varchar(63)[]
|
RETURNS varchar(63)[]
|
||||||
STABLE LEAKPROOF
|
STABLE LEAKPROOF
|
||||||
@ -670,24 +598,27 @@ BEGIN
|
|||||||
RETURN string_to_array(currentSubject, ';');
|
RETURN string_to_array(currentSubject, ';');
|
||||||
END; $$;
|
END; $$;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION pureIdentifier(rawIdentifier varchar)
|
||||||
|
RETURNS uuid
|
||||||
|
RETURNS NULL ON NULL INPUT
|
||||||
|
LANGUAGE plpgsql AS $$
|
||||||
|
begin
|
||||||
|
return regexp_replace(rawIdentifier, '\W+', '');
|
||||||
|
end; $$;
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION findUuidByIdName(objectTable varchar, objectIdName varchar)
|
CREATE OR REPLACE FUNCTION findUuidByIdName(objectTable varchar, objectIdName varchar)
|
||||||
RETURNS uuid
|
RETURNS uuid
|
||||||
RETURNS NULL ON NULL INPUT
|
RETURNS NULL ON NULL INPUT
|
||||||
LANGUAGE plpgsql AS $$
|
LANGUAGE plpgsql AS $$
|
||||||
DECLARE
|
DECLARE
|
||||||
|
sql varchar;
|
||||||
BEGIN
|
BEGIN
|
||||||
/*sql = 'E ' || baseTable || '_historicize' ||
|
objectTable := pureIdentifier(objectTable);
|
||||||
' AFTER INSERT OR DELETE OR UPDATE ON ' || baseTable ||
|
objectIdName := pureIdentifier(objectIdName);
|
||||||
' FOR EACH ROW EXECUTE PROCEDURE historicize()';
|
sql := objectTable || 'UuidByIdName(' || objectIdName || ');';
|
||||||
RAISE NOTICE 'sql: %', createTriggerSQL;
|
EXECUTE sql;
|
||||||
EXECUTE createTriggerSQ*/
|
|
||||||
|
|
||||||
RETURN customerUuidByIdName(objectIdName);
|
|
||||||
END; $$;
|
END; $$;
|
||||||
|
|
||||||
ROLLBACK;
|
|
||||||
SET SESSION AUTHORIZATION DEFAULT;
|
|
||||||
CREATE OR REPLACE FUNCTION currentSubjectIds()
|
CREATE OR REPLACE FUNCTION currentSubjectIds()
|
||||||
RETURNS uuid[]
|
RETURNS uuid[]
|
||||||
STABLE LEAKPROOF
|
STABLE LEAKPROOF
|
||||||
@ -731,3 +662,4 @@ BEGIN
|
|||||||
|
|
||||||
RETURN roleIdsToAssume;
|
RETURN roleIdsToAssume;
|
||||||
END; $$;
|
END; $$;
|
||||||
|
--//
|
12
src/main/resources/db/changelog/db.changelog-master.yaml
Normal file
12
src/main/resources/db/changelog/db.changelog-master.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
databaseChangeLog:
|
||||||
|
- include:
|
||||||
|
file: db/changelog/2022-07-28-001-last-row-count.sql
|
||||||
|
- include:
|
||||||
|
file: db/changelog/2022-07-28-002-int-to-var.sql
|
||||||
|
- include:
|
||||||
|
file: db/changelog/2022-07-28-003-random-in-range.sql
|
||||||
|
- include:
|
||||||
|
file: db/changelog/2022-07-28-004-uuid-ossp-extension.sql
|
||||||
|
- include:
|
||||||
|
file: db/changelog/2022-07-28-005-rbac-base.sql
|
||||||
|
|
Loading…
Reference in New Issue
Block a user