209 lines
5.3 KiB
MySQL
209 lines
5.3 KiB
MySQL
|
|
||
|
|
||
|
-- ========================================================
|
||
|
-- Role-Hierarcy helper functions
|
||
|
-- --------------------------------------------------------
|
||
|
|
||
|
CREATE TYPE RbacRoleType AS ENUM ('owner', 'admin', 'tenant');
|
||
|
|
||
|
-- PERMISSIONS --------------------------------------------
|
||
|
|
||
|
-- drop type RbacPermissions;
|
||
|
CREATE TYPE RbacPermissions AS
|
||
|
(
|
||
|
permissionUuids uuid[]
|
||
|
);
|
||
|
|
||
|
CREATE OR REPLACE FUNCTION grantingPermissions(forObjectUuid uuid, permitOps RbacOp[])
|
||
|
RETURNS RbacPermissions
|
||
|
LANGUAGE plpgsql STRICT AS $$
|
||
|
BEGIN
|
||
|
RETURN ROW(createPermissions(forObjectUuid, permitOps))::RbacPermissions;
|
||
|
END; $$;
|
||
|
|
||
|
-- SUPER ROLES --------------------------------------------
|
||
|
|
||
|
-- drop type RbacSuperRoles;
|
||
|
CREATE TYPE RbacSuperRoles AS
|
||
|
(
|
||
|
roleUuids uuid[]
|
||
|
);
|
||
|
|
||
|
-- drop function beneathRoles(roleName varchar);
|
||
|
CREATE OR REPLACE FUNCTION beneathRoles(roleNames varchar[])
|
||
|
RETURNS RbacSuperRoles
|
||
|
LANGUAGE plpgsql STRICT AS $$
|
||
|
DECLARE
|
||
|
superRoleName varchar;
|
||
|
superRoleUuids uuid[] := ARRAY[]::uuid[];
|
||
|
BEGIN
|
||
|
FOREACH superRoleName IN ARRAY roleNames LOOP
|
||
|
superRoleUuids := superRoleUuids || getRoleId(superRoleName, 'fail');
|
||
|
END LOOP;
|
||
|
|
||
|
RETURN ROW(superRoleUuids)::RbacSuperRoles;
|
||
|
END; $$;
|
||
|
|
||
|
-- drop function beneathRole(roleName varchar);
|
||
|
CREATE OR REPLACE FUNCTION beneathRole(roleName varchar)
|
||
|
RETURNS RbacSuperRoles
|
||
|
LANGUAGE plpgsql STRICT AS $$
|
||
|
BEGIN
|
||
|
RETURN beneathRoles(ARRAY[roleName]);
|
||
|
END; $$;
|
||
|
|
||
|
-- drop function beneathRole(roleUuid uuid);
|
||
|
CREATE OR REPLACE FUNCTION beneathRole(roleUuid uuid)
|
||
|
RETURNS RbacSuperRoles
|
||
|
LANGUAGE plpgsql STRICT AS $$
|
||
|
BEGIN
|
||
|
RETURN ROW(ARRAY[roleUuid]::uuid[])::RbacSuperRoles;
|
||
|
END; $$;
|
||
|
|
||
|
-- drop function asTopLevelRole(roleName varchar);
|
||
|
CREATE OR REPLACE FUNCTION asTopLevelRole()
|
||
|
RETURNS RbacSuperRoles
|
||
|
LANGUAGE plpgsql STRICT AS $$
|
||
|
BEGIN
|
||
|
RETURN ROW(ARRAY[]::uuid[])::RbacSuperRoles;
|
||
|
END; $$;
|
||
|
|
||
|
-- SUB ROLES ----------------------------------------------
|
||
|
|
||
|
CREATE TYPE RbacSubRoles AS
|
||
|
(
|
||
|
roleUuids uuid[]
|
||
|
);
|
||
|
|
||
|
-- drop FUNCTION beingItselfA(roleUuid uuid)
|
||
|
CREATE OR REPLACE FUNCTION beingItselfA(roleUuid uuid)
|
||
|
RETURNS RbacSubRoles
|
||
|
LANGUAGE plpgsql STRICT AS $$
|
||
|
BEGIN
|
||
|
RETURN ROW(ARRAY[roleUuid]::uuid[])::RbacSubRoles;
|
||
|
END; $$;
|
||
|
|
||
|
-- drop FUNCTION beingItselfA(roleName varchar)
|
||
|
CREATE OR REPLACE FUNCTION beingItselfA(roleName varchar)
|
||
|
RETURNS RbacSubRoles
|
||
|
LANGUAGE plpgsql STRICT AS $$
|
||
|
BEGIN
|
||
|
RETURN beingItselfA(getRoleId(roleName, 'fail'));
|
||
|
END; $$;
|
||
|
|
||
|
-- USERS --------------------------------------------------
|
||
|
|
||
|
-- drop type RbacUsers;
|
||
|
CREATE TYPE RbacUsers AS
|
||
|
(
|
||
|
userUuids uuid[]
|
||
|
);
|
||
|
|
||
|
-- drop function withUsers(userNames varchar);
|
||
|
CREATE OR REPLACE FUNCTION withUsers(userNames varchar[])
|
||
|
RETURNS RbacUsers
|
||
|
LANGUAGE plpgsql STRICT AS $$
|
||
|
DECLARE
|
||
|
userName varchar;
|
||
|
userUuids uuid[] := ARRAY[]::uuid[];
|
||
|
BEGIN
|
||
|
FOREACH userName IN ARRAY userNames LOOP
|
||
|
userUuids := userUuids || getRbacUserId(userName, 'fail');
|
||
|
END LOOP;
|
||
|
|
||
|
RETURN ROW(userUuids)::RbacUsers;
|
||
|
END; $$;
|
||
|
|
||
|
|
||
|
-- DROP FUNCTION withUser(userName varchar, whenNotExists RbacWhenNotExists);
|
||
|
CREATE OR REPLACE FUNCTION withUser(userName varchar, whenNotExists RbacWhenNotExists = 'fail')
|
||
|
RETURNS RbacUsers
|
||
|
RETURNS NULL ON NULL INPUT
|
||
|
LANGUAGE plpgsql AS $$
|
||
|
BEGIN
|
||
|
RETURN ROW(ARRAY[getRbacUserId(userName, whenNotExists )]);
|
||
|
END; $$;
|
||
|
|
||
|
-- ROLE NAME BUILDER --------------------------------------
|
||
|
|
||
|
CREATE OR REPLACE FUNCTION roleName(objectTable varchar, objectName varchar, roleType RbacRoleType )
|
||
|
RETURNS varchar
|
||
|
RETURNS NULL ON NULL INPUT
|
||
|
STABLE LEAKPROOF
|
||
|
LANGUAGE plpgsql AS $$
|
||
|
BEGIN
|
||
|
RETURN objectTable || '#' || objectName || '.' || roleType;
|
||
|
END; $$;
|
||
|
|
||
|
|
||
|
-- CREATE ROLE MAIN FUNCTION ------------------------------
|
||
|
|
||
|
CREATE OR REPLACE FUNCTION createRole(
|
||
|
roleName varchar,
|
||
|
permissions RbacPermissions,
|
||
|
superRoles RbacSuperRoles,
|
||
|
subRoles RbacSubRoles = null,
|
||
|
users RbacUsers = null
|
||
|
)
|
||
|
RETURNS uuid
|
||
|
CALLED ON NULL INPUT
|
||
|
LANGUAGE plpgsql AS $$
|
||
|
DECLARE
|
||
|
roleUuid uuid;
|
||
|
superRoleUuid uuid;
|
||
|
subRoleUuid uuid;
|
||
|
userUuid uuid;
|
||
|
BEGIN
|
||
|
RAISE NOTICE 'creating role: %', roleName;
|
||
|
roleUuid = createRole(roleName);
|
||
|
|
||
|
call grantPermissionsToRole(roleUuid, permissions.permissionUuids);
|
||
|
|
||
|
IF superRoles IS NOT NULL THEN
|
||
|
FOREACH superRoleUuid IN ARRAY superRoles.roleuUids LOOP
|
||
|
call grantRoleToRole(roleUuid, superRoleUuid);
|
||
|
END LOOP;
|
||
|
END IF;
|
||
|
|
||
|
IF subRoles IS NOT NULL THEN
|
||
|
FOREACH subRoleUuid IN ARRAY subRoles.roleuUids LOOP
|
||
|
call grantRoleToRole(subRoleUuid, roleUuid);
|
||
|
END LOOP;
|
||
|
END IF;
|
||
|
|
||
|
IF users IS NOT NULL THEN
|
||
|
FOREACH userUuid IN ARRAY users.useruUids LOOP
|
||
|
call grantRoleToUser(roleUuid, userUuid);
|
||
|
END LOOP;
|
||
|
END IF;
|
||
|
|
||
|
RETURN roleUuid;
|
||
|
END; $$;
|
||
|
|
||
|
CREATE OR REPLACE FUNCTION createRole(
|
||
|
roleName varchar,
|
||
|
permissions RbacPermissions,
|
||
|
users RbacUsers = null
|
||
|
)
|
||
|
RETURNS uuid
|
||
|
CALLED ON NULL INPUT
|
||
|
LANGUAGE plpgsql AS $$
|
||
|
BEGIN
|
||
|
RETURN createRole(roleName, permissions, null, null, users);
|
||
|
END; $$;
|
||
|
|
||
|
CREATE OR REPLACE FUNCTION createRole(
|
||
|
roleName varchar,
|
||
|
permissions RbacPermissions,
|
||
|
subRoles RbacSubRoles,
|
||
|
users RbacUsers = null
|
||
|
)
|
||
|
RETURNS uuid
|
||
|
CALLED ON NULL INPUT
|
||
|
LANGUAGE plpgsql AS $$
|
||
|
BEGIN
|
||
|
RETURN createRole(roleName, permissions, null, subRoles, users);
|
||
|
END; $$;
|
||
|
|
||
|
|