improved role structure including comprised tenant sub roles

This commit is contained in:
Michael Hoennig 2022-07-25 16:38:21 +02:00
parent 377b63ca3d
commit d4eeb35e91
26 changed files with 613 additions and 146 deletions

8
.run/00-util.sql.run.xml Normal file
View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="00-util.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/00-util.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="10-rbac-base.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/10-rbac-base.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="12-rbac-role-builder.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/12-rbac-role-builder.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="18--rbac-all.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/18--rbac-all.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="20-hs-base.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/20-hs-base.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="21-hs-customer.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/21-hs-customer.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="22-hs-packages.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/22-hs-packages.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="23-hs-unixuser.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/23-hs-unixuser.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="24-hs-domain.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/24-hs-domain.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="25-hs-emailaddress.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/25-hs-emailaddress.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="29-hs-statistics.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/29-hs-statistics.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="30-run-all.sql" type="DatabaseScript" editBeforeRun="true" nameIsGenerated="true">
<script-file value="$PROJECT_DIR$/sql/30-run-all.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -0,0 +1,18 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="run all up to statistics" type="DatabaseScript" editBeforeRun="true">
<script-file value="$PROJECT_DIR$/sql/00-util.sql" />
<script-file value="$PROJECT_DIR$/sql/10-rbac-base.sql" />
<script-file value="$PROJECT_DIR$/sql/12-rbac-role-builder.sql" />
<script-file value="$PROJECT_DIR$/sql/18-rbac-statistics.sql" />
<script-file value="$PROJECT_DIR$/sql/20-hs-base.sql" />
<script-file value="$PROJECT_DIR$/sql/21-hs-customer.sql" />
<script-file value="$PROJECT_DIR$/sql/22-hs-packages.sql" />
<script-file value="$PROJECT_DIR$/sql/23-hs-unixuser.sql" />
<script-file value="$PROJECT_DIR$/sql/24-hs-domain.sql" />
<script-file value="$PROJECT_DIR$/sql/25-hs-emailaddress.sql" />
<script-file value="$PROJECT_DIR$/sql/29-hs-statistics.sql" />
<script-mode>FILE</script-mode>
<data-source id="58980aaf-09d7-4782-a6fa-859aa1fc3986" namespace="database/&quot;postgres&quot;/schema/&quot;public&quot;" />
<method v="2" />
</configuration>
</component>

View File

@ -35,4 +35,15 @@ ELSE
RETURN partial; RETURN partial;
END IF; END IF;
END; $$; END; $$;
SELECT * FROM intToVarChar(211, 4);
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);

View File

@ -45,7 +45,7 @@ CREATE TABLE RbacGrants
CREATE INDEX ON RbacGrants (ascendantUuid); CREATE INDEX ON RbacGrants (ascendantUuid);
CREATE INDEX ON RbacGrants (descendantUuid); CREATE INDEX ON RbacGrants (descendantUuid);
DROP DOMAIN IF EXISTS RbacOp CASCADE; -- DROP DOMAIN IF EXISTS RbacOp CASCADE;
CREATE DOMAIN RbacOp AS VARCHAR(67) CREATE DOMAIN RbacOp AS VARCHAR(67)
CHECK( CHECK(
VALUE = '*' VALUE = '*'
@ -56,7 +56,7 @@ CREATE DOMAIN RbacOp AS VARCHAR(67)
OR VALUE ~ '^add-[a-z]+$' OR VALUE ~ '^add-[a-z]+$'
); );
DROP TABLE IF EXISTS RbacObject; -- DROP TABLE IF EXISTS RbacObject;
CREATE TABLE RbacObject CREATE TABLE RbacObject
( (
uuid uuid UNIQUE DEFAULT uuid_generate_v4(), uuid uuid UNIQUE DEFAULT uuid_generate_v4(),
@ -80,7 +80,7 @@ BEGIN
END; $$; END; $$;
DROP TABLE IF EXISTS RbacPermission; -- DROP TABLE IF EXISTS RbacPermission;
CREATE TABLE RbacPermission CREATE TABLE RbacPermission
( uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE, ( uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE,
objectUuid uuid not null, objectUuid uuid not null,
@ -111,13 +111,15 @@ BEGIN
END; END;
$$; $$;
CREATE OR REPLACE FUNCTION findRbacUser(userName varchar) -- TODO: rename to ...Id CREATE OR REPLACE FUNCTION findRbacUserId(userName varchar)
RETURNS uuid RETURNS uuid
RETURNS NULL ON NULL INPUT RETURNS NULL ON NULL INPUT
LANGUAGE sql AS $$ LANGUAGE sql AS $$
SELECT uuid FROM RbacUser WHERE name = userName SELECT uuid FROM RbacUser WHERE name = userName
$$; $$;
CREATE TYPE RbacWhenNotExists AS ENUM ('fail', 'create');
CREATE OR REPLACE FUNCTION getRbacUserId(userName varchar, whenNotExists RbacWhenNotExists) CREATE OR REPLACE FUNCTION getRbacUserId(userName varchar, whenNotExists RbacWhenNotExists)
RETURNS uuid RETURNS uuid
RETURNS NULL ON NULL INPUT RETURNS NULL ON NULL INPUT
@ -125,7 +127,7 @@ CREATE OR REPLACE FUNCTION getRbacUserId(userName varchar, whenNotExists RbacWhe
DECLARE DECLARE
userUuid uuid; userUuid uuid;
BEGIN BEGIN
userUuid = findRbacUser(userName); userUuid = findRbacUserId(userName);
IF ( userUuid IS NULL ) THEN IF ( userUuid IS NULL ) THEN
IF ( whenNotExists = 'fail') THEN IF ( whenNotExists = 'fail') THEN
RAISE EXCEPTION 'RbacUser with name="%" not found', userName; RAISE EXCEPTION 'RbacUser with name="%" not found', userName;
@ -169,8 +171,6 @@ CREATE OR REPLACE FUNCTION findRoleId(roleName varchar)
SELECT uuid FROM RbacRole WHERE name = roleName SELECT uuid FROM RbacRole WHERE name = roleName
$$; $$;
CREATE TYPE RbacWhenNotExists AS ENUM ('fail', 'create');
CREATE OR REPLACE FUNCTION getRoleId(roleName varchar, whenNotExists RbacWhenNotExists) CREATE OR REPLACE FUNCTION getRoleId(roleName varchar, whenNotExists RbacWhenNotExists)
RETURNS uuid RETURNS uuid
RETURNS NULL ON NULL INPUT RETURNS NULL ON NULL INPUT
@ -265,7 +265,7 @@ BEGIN
END IF; END IF;
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (superRoleId, subRoleId, doapply); -- assumeV1 -- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (superRoleId, subRoleId, doapply); -- assumeV1
INSERT INTO RbacGrants (ascendantUuid, descendantUuid, follow)VALUES (superRoleId, subRoleId, doFollow) INSERT INTO RbacGrants (ascendantUuid, descendantUuid, follow) VALUES (superRoleId, subRoleId, doFollow)
ON CONFLICT DO NOTHING ; -- TODO: remove? ON CONFLICT DO NOTHING ; -- TODO: remove?
END; $$; END; $$;
@ -288,7 +288,7 @@ BEGIN
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (userId, roleId, true); -- assumeV1 -- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (userId, roleId, true); -- assumeV1
INSERT INTO RbacGrants (ascendantUuid, descendantUuid) VALUES (userId, roleId) INSERT INTO RbacGrants (ascendantUuid, descendantUuid) VALUES (userId, roleId)
ON CONFLICT DO NOTHING ; -- TODO: remove ON CONFLICT DO NOTHING ; -- TODO: remove?
END; $$; END; $$;
abort; abort;
@ -306,9 +306,12 @@ CREATE OR REPLACE FUNCTION nextLevel(level integer, maxDepth integer)
$$; $$;
abort;
set local session authorization default;
CREATE OR REPLACE FUNCTION queryAccessibleObjectUuidsOfSubjectIds( CREATE OR REPLACE FUNCTION queryAccessibleObjectUuidsOfSubjectIds(
requiredOp RbacOp, requiredOp RbacOp,
forObjectTable varchar, -- TODO: test perforamance in joins! forObjectTable varchar, -- TODO: test performance in joins!
subjectIds uuid[], subjectIds uuid[],
maxObjects integer = 16000) maxObjects integer = 16000)
RETURNS SETOF uuid RETURNS SETOF uuid
@ -345,12 +348,18 @@ CREATE OR REPLACE FUNCTION queryAccessibleObjectUuidsOfSubjectIds(
END; END;
$$; $$;
SET SESSION AUTHORIZATION DEFAULT;
CREATE ROLE admin;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin;
CREATE ROLE restricted;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO restricted;
abort; abort;
set local session authorization restricted; set local session authorization restricted;
begin transaction; begin transaction;
set local statement_timeout TO '5s'; set local statement_timeout TO '15s';
select count(*) select count(*)
from queryAccessibleObjectUuidsOfSubjectIds('view', 'customer', ARRAY[findRbacUser('mike@hostsharing.net')], 10000); from queryAccessibleObjectUuidsOfSubjectIds('view', 'customer', ARRAY[findRbacUserId('mike@hostsharing.net')], 10000);
end transaction; end transaction;
--- ---
@ -389,7 +398,7 @@ set local session authorization restricted;
begin transaction; begin transaction;
-- set local statement_timeout TO '5s'; -- set local statement_timeout TO '5s';
set local statement_timeout TO '5min'; set local statement_timeout TO '5min';
select count(*) from queryRequiredPermissionsOfSubjectIds('view', ARRAY[findRbacUser('mike@hostsharing.net')]); select count(*) from queryRequiredPermissionsOfSubjectIds('view', ARRAY[findRbacUserId('mike@hostsharing.net')]);
end transaction; end transaction;
--- ---
@ -424,7 +433,7 @@ abort;
set local session authorization restricted; set local session authorization restricted;
begin transaction; begin transaction;
set local statement_timeout TO '5s'; set local statement_timeout TO '5s';
select count(*) from queryAllPermissionsOfSubjectIds(ARRAY[findRbacUser('mike@hostsharing.net')]); select count(*) from queryAllPermissionsOfSubjectIds(ARRAY[findRbacUserId('mike@hostsharing.net')]);
end transaction; end transaction;
--- ---
@ -564,18 +573,10 @@ CREATE OR REPLACE FUNCTION isPermissionGrantedToSubject(permissionId uuid, subje
); );
$$; $$;
SET SESSION AUTHORIZATION DEFAULT;
CREATE ROLE admin;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin;
CREATE ROLE restricted;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO restricted;
-- ======================================================== -- ========================================================
-- Current User -- current user + assumed roles
-- -------------------------------------------------------- -- --------------------------------------------------------
CREATE OR REPLACE FUNCTION currentUser() CREATE OR REPLACE FUNCTION currentUser()
RETURNS varchar(63) RETURNS varchar(63)
STABLE LEAKPROOF STABLE LEAKPROOF

View File

@ -0,0 +1,208 @@
-- ========================================================
-- 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; $$;

View File

@ -1,5 +1,5 @@
DROP VIEW "RbacStatisticsV"; DROP VIEW IF EXISTS "RbacStatisticsV";
CREATE VIEW "RbacStatisticsV" AS CREATE VIEW "RbacStatisticsV" AS
SELECT no, to_char("count", '9 999 999 999') as "count", "table" SELECT no, to_char("count", '9 999 999 999') as "count", "table"
FROM ( FROM (

View File

@ -17,40 +17,62 @@ CREATE TRIGGER createRbacObjectForCustomer_Trigger
BEFORE INSERT ON customer BEFORE INSERT ON customer
FOR EACH ROW EXECUTE PROCEDURE createRbacObject(); FOR EACH ROW EXECUTE PROCEDURE createRbacObject();
CREATE OR REPLACE FUNCTION customerOwner(customerName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('customer', customerName, 'owner');
end; $$;
CREATE OR REPLACE FUNCTION customerAdmin(customerName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('customer', customerName, 'admin');
end; $$;
CREATE OR REPLACE FUNCTION customerTenant(customerName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('customer', customerName, 'tenant');
end; $$;
CREATE OR REPLACE FUNCTION createRbacRulesForCustomer() CREATE OR REPLACE FUNCTION createRbacRulesForCustomer()
RETURNS trigger RETURNS trigger
LANGUAGE plpgsql STRICT AS $$ LANGUAGE plpgsql STRICT AS $$
DECLARE DECLARE
adminUserNameUuid uuid; customerOwnerUuid uuid;
customerOwnerRoleId uuid; customerAdminUuid uuid;
customerAdminRoleId uuid;
BEGIN BEGIN
IF TG_OP <> 'INSERT' THEN IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT'; RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
END IF; END IF;
-- an owner role is created and assigned to the administrators group -- the owner role with full access for Hostsharing administrators
customerOwnerRoleId = createRole('customer#'||NEW.prefix||'.owner'); customerOwnerUuid = createRole(
call grantRoleToRole(customerOwnerRoleId, getRoleId('administrators', 'create')); customerOwner(NEW.prefix),
-- ... and permissions for all ops are assigned grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']),
call grantPermissionsToRole(customerOwnerRoleId, beneathRole('administrators')
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*'])); );
-- ... also a customer admin role is created and granted to the customer owner role -- the admin role for the customer's admins, who can view and add products
customerAdminRoleId = createRole('customer#'||NEW.prefix||'.admin'); customerAdminUuid = createRole(
call grantRoleToRole(customerAdminRoleId, customerOwnerRoleId, false); customerAdmin(NEW.prefix),
-- ... to which a permission with view and add- ops is assigned grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['view', 'add-package']),
call grantPermissionsToRole(customerAdminRoleId, -- NO auto follow for customer owner to avoid exploding permissions for administrators
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['view', 'add-package'])); withUser(NEW.adminUserName, 'create') -- implicitly ignored if null
-- if a admin user is given for the customer, );
IF (NEW.adminUserName IS NOT NULL) THEN
-- ... the customer admin role is also assigned to the admin user of the customer -- allow the customer owner role (thus administrators) to assume the customer admin role
adminUserNameUuid = findRoleId(NEW.adminUserName); call grantRoleToRole(customerAdminUuid, customerOwnerUuid, FALSE);
IF ( adminUserNameUuid IS NULL ) THEN
adminUserNameUuid = createRbacUser(NEW.adminUserName); -- the tenant role which later can be used by owners+admins of sub-objects
END IF; perform createRole(
call grantRoleToUser(customerAdminRoleId, adminUserNameUuid); customerTenant(NEW.prefix),
END IF; grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['view'])
);
RETURN NEW; RETURN NEW;
END; $$; END; $$;
@ -109,7 +131,7 @@ DO LANGUAGE plpgsql $$
BEGIN BEGIN
SET hsadminng.currentUser TO ''; SET hsadminng.currentUser TO '';
FOR t IN 0..9999 LOOP FOR t IN 0..69 LOOP
currentTask = 'creating RBAC test customer #' || t; currentTask = 'creating RBAC test customer #' || t;
SET LOCAL hsadminng.currentUser TO 'mike@hostsharing.net'; SET LOCAL hsadminng.currentUser TO 'mike@hostsharing.net';
SET LOCAL hsadminng.assumedRoles = ''; SET LOCAL hsadminng.assumedRoles = '';

View File

@ -11,6 +11,28 @@ CREATE TABLE IF NOT EXISTS package (
customerUuid uuid REFERENCES customer(uuid) customerUuid uuid REFERENCES customer(uuid)
); );
CREATE OR REPLACE FUNCTION packageOwner(packageName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('package', packageName, 'owner');
end; $$;
CREATE OR REPLACE FUNCTION packageAdmin(packageName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('package', packageName, 'admin');
end; $$;
CREATE OR REPLACE FUNCTION packageTenant(packageName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('package', packageName, 'tenant');
end; $$;
DROP TRIGGER IF EXISTS createRbacObjectForPackage_Trigger ON package; DROP TRIGGER IF EXISTS createRbacObjectForPackage_Trigger ON package;
CREATE TRIGGER createRbacObjectForPackage_Trigger CREATE TRIGGER createRbacObjectForPackage_Trigger
BEFORE INSERT ON package BEFORE INSERT ON package
@ -21,8 +43,8 @@ CREATE OR REPLACE FUNCTION createRbacRulesForPackage()
LANGUAGE plpgsql STRICT AS $$ LANGUAGE plpgsql STRICT AS $$
DECLARE DECLARE
parentCustomer customer; parentCustomer customer;
packageOwnerRoleId uuid; packageOwnerRoleUuid uuid;
packageTenantRoleId uuid; packageAdminRoleUuid uuid;
BEGIN BEGIN
IF TG_OP <> 'INSERT' THEN IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT'; RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
@ -30,21 +52,27 @@ BEGIN
SELECT * FROM customer AS c WHERE c.uuid=NEW.customerUuid INTO parentCustomer; SELECT * FROM customer AS c WHERE c.uuid=NEW.customerUuid INTO parentCustomer;
-- an owner role is created and assigned to the customer's admin group -- an owner role is created and assigned to the customer's admin role
packageOwnerRoleId = createRole('package#'||NEW.name||'.owner'); packageOwnerRoleUuid = createRole(
call grantRoleToRole(packageOwnerRoleId, getRoleId('customer#'||parentCustomer.prefix||'.admin', 'fail')); packageOwner(NEW.name),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']),
beneathRole(customerAdmin(parentCustomer.prefix))
);
-- ... and permissions for all ops are assigned -- an owner role is created and assigned to the package owner role
call grantPermissionsToRole(packageOwnerRoleId, packageAdminRoleUuid = createRole(
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*'])); packageAdmin(NEW.name),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['edit', 'add-unixuser']),
beneathRole(packageOwnerRoleUuid)
);
-- ... also a package tenant role is created and assigned to the package owner as well -- and a package tenant role is created and assigned to the package admin as well
packageTenantRoleId = createRole('package#'||NEW.name||'.tenant'); perform createRole(
call grantRoleToRole(packageTenantRoleId, packageOwnerRoleId); packageTenant(NEW.name),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY ['view']),
-- ... to which a permission with view operation is assigned beneathRole(packageAdminRoleUuid),
call grantPermissionsToRole(packageTenantRoleId, beingItselfA(customerTenant(parentCustomer.prefix))
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['view'])); );
RETURN NEW; RETURN NEW;
END; $$; END; $$;
@ -96,7 +124,7 @@ DO LANGUAGE plpgsql $$
SET hsadminng.currentUser TO ''; SET hsadminng.currentUser TO '';
FOR cust IN (SELECT * FROM customer) LOOP FOR cust IN (SELECT * FROM customer) LOOP
FOR t IN 0..9 LOOP FOR t IN 0..randominrange(1, 2) LOOP
pacName = cust.prefix || TO_CHAR(t, 'fm00'); pacName = cust.prefix || TO_CHAR(t, 'fm00');
currentTask = 'creating RBAC test package #'|| pacName || ' for customer ' || cust.prefix || ' #' || cust.uuid; currentTask = 'creating RBAC test package #'|| pacName || ' for customer ' || cust.prefix || ' #' || cust.uuid;
RAISE NOTICE 'task: %', currentTask; RAISE NOTICE 'task: %', currentTask;

View File

@ -11,6 +11,49 @@ CREATE TABLE IF NOT EXISTS UnixUser (
packageUuid uuid REFERENCES package(uuid) packageUuid uuid REFERENCES package(uuid)
); );
CREATE OR REPLACE FUNCTION unixUserOwner(unixUserName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('unixuser', unixUserName, 'owner');
end; $$;
CREATE OR REPLACE FUNCTION unixUserAdmin(unixUserName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('unixuser', unixUserName, 'admin');
end; $$;
CREATE OR REPLACE FUNCTION unixUserTenant(unixUserName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('unixuser', unixUserName, 'tenant');
end; $$;
CREATE OR REPLACE FUNCTION createUnixUserTenantRoleIfNotExists(unixUser UnixUser)
RETURNS uuid
RETURNS NULL ON NULL INPUT
LANGUAGE plpgsql AS $$
DECLARE
unixUserTenantRoleName varchar;
unixUserTenantRoleUuid uuid;
BEGIN
unixUserTenantRoleName = unixUserTenant(unixUser.name);
unixUserTenantRoleUuid = findRoleId(unixUserTenantRoleName);
IF unixUserTenantRoleUuid IS NOT NULL THEN
RETURN unixUserTenantRoleUuid;
END IF;
RETURN createRole(
unixUserTenantRoleName,
grantingPermissions(forObjectUuid => unixUser.uuid, permitOps => ARRAY['edit', 'add-domain']),
beneathRole(unixUserAdmin(unixUser.name))
);
END; $$;
DROP TRIGGER IF EXISTS createRbacObjectForUnixUser_Trigger ON UnixUser; DROP TRIGGER IF EXISTS createRbacObjectForUnixUser_Trigger ON UnixUser;
CREATE TRIGGER createRbacObjectForUnixUser_Trigger CREATE TRIGGER createRbacObjectForUnixUser_Trigger
BEFORE INSERT ON UnixUser BEFORE INSERT ON UnixUser
@ -23,7 +66,6 @@ DECLARE
parentPackage package; parentPackage package;
unixuserOwnerRoleId uuid; unixuserOwnerRoleId uuid;
unixuserAdminRoleId uuid; unixuserAdminRoleId uuid;
unixuserTenantRoleId uuid;
BEGIN BEGIN
IF TG_OP <> 'INSERT' THEN IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT'; RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
@ -31,26 +73,22 @@ BEGIN
SELECT * FROM package WHERE uuid=NEW.packageUuid into parentPackage; SELECT * FROM package WHERE uuid=NEW.packageUuid into parentPackage;
-- an owner role is created and assigned to the package owner group -- an owner role is created and assigned to the package's admin group
unixuserOwnerRoleId = createRole('unixuser#'||NEW.name||'.owner'); unixuserOwnerRoleId = createRole(
call grantRoleToRole(unixuserOwnerRoleId, getRoleId('package#'||parentPackage.name||'.owner', 'fail')); unixUserOwner(NEW.name),
-- ... and permissions for all ops are assigned grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']),
call grantPermissionsToRole(unixuserOwnerRoleId, beneathRole(packageAdmin(parentPackage.name))
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*'])); );
-- ... also a unixuser admin role is created and assigned to the unixuser owner as well -- and a unixuser admin role is created and assigned to the unixuser owner as well
unixuserAdminRoleId = createRole('unixuser#'||NEW.name||'.admin'); unixuserAdminRoleId = createRole(
call grantRoleToRole(unixuserAdminRoleId, unixuserOwnerRoleId); unixUserAdmin(NEW.name),
-- ... to which a permission with view operation is assigned grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['edit', 'add-domain']),
call grantPermissionsToRole(unixuserAdminRoleId, beneathRole(unixuserOwnerRoleId),
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['edit', 'add-domain'])); beingItselfA(packageTenant(parentPackage.name))
);
-- ... also a unixuser tenant role is created and assigned to the unixuser admin -- a tenent role is only created on demand
unixuserTenantRoleId = createRole('unixuser#'||NEW.name||'.tenant');
call grantRoleToRole(unixuserTenantRoleId, unixuserAdminRoleId);
-- ... to which a permission with view operation is assigned
call grantPermissionsToRole(unixuserTenantRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['view']));
RETURN NEW; RETURN NEW;
END; $$; END; $$;

View File

@ -16,12 +16,35 @@ CREATE TRIGGER createRbacObjectForDomain_Trigger
BEFORE INSERT ON Domain BEFORE INSERT ON Domain
FOR EACH ROW EXECUTE PROCEDURE createRbacObject(); FOR EACH ROW EXECUTE PROCEDURE createRbacObject();
CREATE OR REPLACE FUNCTION domainOwner(unixUserName varchar, domainName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('domain', unixUserName || '/' || domainName, 'owner');
end; $$;
CREATE OR REPLACE FUNCTION domainAdmin(unixUserName varchar, domainName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('domain', unixUserName || '/' || domainName, 'admin');
end; $$;
CREATE OR REPLACE FUNCTION domainTenant(unixUserName varchar, domainName varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('domain', unixUserName || '/' || domainName, 'tenant');
end; $$;
CREATE OR REPLACE FUNCTION createRbacRulesForDomain() CREATE OR REPLACE FUNCTION createRbacRulesForDomain()
RETURNS trigger RETURNS trigger
LANGUAGE plpgsql STRICT AS $$ LANGUAGE plpgsql STRICT AS $$
DECLARE DECLARE
parentUser unixuser; parentUser unixuser;
domainOwnerRoleId uuid; domainOwnerRoleUuid uuid;
domainAdminRoleUuid uuid;
BEGIN BEGIN
IF TG_OP <> 'INSERT' THEN IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT'; RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
@ -29,13 +52,27 @@ BEGIN
SELECT * FROM unixuser WHERE uuid=NEW.unixUserUuid into parentUser; SELECT * FROM unixuser WHERE uuid=NEW.unixUserUuid into parentUser;
-- an owner role is created and assigned to the unix user admin -- a domain owner role is created and assigned to the unixuser's admin role
RAISE NOTICE 'creating domain owner role: %', 'domain#'||NEW.name||'.owner'; domainOwnerRoleUuid = createRole(
domainOwnerRoleId = getRoleId('domain#'||NEW.name||'.owner', 'create'); domainOwner(parentUser.name, NEW.name),
call grantRoleToRole(domainOwnerRoleId, getRoleId('unixuser#'||parentUser.name||'.admin', 'fail')); grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']),
-- ... and permissions for all ops are assigned beneathRole(unixUserAdmin(parentUser.name))
call grantPermissionsToRole(domainOwnerRoleId, );
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']));
-- a domain admin role is created and assigned to the domain's owner role
domainAdminRoleUuid = createRole(
domainAdmin(parentUser.name, NEW.name),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['edit', 'add-emailaddress']),
beneathRole(domainOwnerRoleUuid)
);
-- and a domain tenant role is created and assigned to the domain's admiin role
perform createRole(
domainTenant(parentUser.name, NEW.name),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']),
beneathRole(domainAdminRoleUuid),
beingItselfA(createUnixUserTenantRoleIfNotExists(parentUser))
);
RETURN NEW; RETURN NEW;
END; $$; END; $$;
@ -74,7 +111,7 @@ DO LANGUAGE plpgsql $$
FOR uu IN (SELECT * FROM unixuser) LOOP FOR uu IN (SELECT * FROM unixuser) LOOP
IF ( random() < 0.3 ) THEN IF ( random() < 0.3 ) THEN
FOR t IN 0..2 LOOP FOR t IN 0..1 LOOP
currentTask = 'creating RBAC test Domain #' || t || ' for UnixUser ' || uu.name|| ' #' || uu.uuid; currentTask = 'creating RBAC test Domain #' || t || ' for UnixUser ' || uu.name|| ' #' || uu.uuid;
RAISE NOTICE 'task: %', currentTask; RAISE NOTICE 'task: %', currentTask;
@ -85,7 +122,7 @@ DO LANGUAGE plpgsql $$
SET LOCAL hsadminng.currentTask TO currentTask; SET LOCAL hsadminng.currentTask TO currentTask;
INSERT INTO Domain (name, unixUserUuid) INSERT INTO Domain (name, unixUserUuid)
VALUES ('dom-' || t || '.' || pac.name || '.example.org' , uu.uuid); VALUES ('dom-' || t || '.' || uu.name || '.example.org' , uu.uuid);
COMMIT; COMMIT;
END LOOP; END LOOP;

View File

@ -16,35 +16,51 @@ CREATE TRIGGER createRbacObjectForEMailAddress_Trigger
BEFORE INSERT ON EMailAddress BEFORE INSERT ON EMailAddress
FOR EACH ROW EXECUTE PROCEDURE createRbacObject(); FOR EACH ROW EXECUTE PROCEDURE createRbacObject();
CREATE OR REPLACE FUNCTION emailAddressOwner(emailAddress varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('emailaddress', emailAddress, 'owner');
end; $$;
CREATE OR REPLACE FUNCTION emailAddressAdmin(emailAddress varchar)
RETURNS varchar
LANGUAGE plpgsql STRICT AS $$
begin
return roleName('emailaddress', emailAddress, 'admin');
end; $$;
CREATE OR REPLACE FUNCTION createRbacRulesForEMailAddress() CREATE OR REPLACE FUNCTION createRbacRulesForEMailAddress()
RETURNS trigger RETURNS trigger
LANGUAGE plpgsql STRICT AS $$ LANGUAGE plpgsql STRICT AS $$
DECLARE DECLARE
parentDomain record;
eMailAddress varchar; eMailAddress varchar;
parentDomain domain; eMailAddressOwnerRoleUuid uuid;
eMailAddressOwnerRoleId uuid;
eMailAddressTenantRoleId uuid;
BEGIN BEGIN
IF TG_OP <> 'INSERT' THEN IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT'; RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
END IF; END IF;
SELECT * FROM domain WHERE uuid=NEW.domainUuid into parentDomain; SELECT d.name as name, u.name as unixUserName FROM domain d
LEFT JOIN unixuser u ON u.uuid = d.unixuseruuid
WHERE d.uuid=NEW.domainUuid into parentDomain;
eMailAddress = NEW.localPart || '@' || parentDomain.name; eMailAddress = NEW.localPart || '@' || parentDomain.name;
-- an owner role is created and assigned to the domain owner -- an owner role is created and assigned to the domains's admin group
eMailAddressOwnerRoleId = getRoleId('emailaddress#'||eMailAddress||'.owner', 'create'); eMailAddressOwnerRoleUuid = createRole(
call grantRoleToRole(eMailAddressOwnerRoleId, getRoleId('domain#'||parentDomain.name||'.owner', 'fail')); emailAddressOwner(eMailAddress),
-- ... and permissions for all ops are assigned grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']),
call grantPermissionsToRole(eMailAddressOwnerRoleId, beneathRole(domainAdmin( parentDomain.unixUserName, parentDomain.name))
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*'])); );
-- a tenant role is created and assigned to a user with the new email address -- and an admin role is created and assigned to the unixuser owner as well
eMailAddressTenantRoleId = getRoleId('emailaddress#'||eMailAddress||'.tenant', 'create'); perform createRole(
call grantRoleToUser(eMailAddressTenantRoleId, getRbacUserId(eMailAddress, 'create')); emailAddressAdmin(eMailAddress),
-- ... and permissions for all ops are assigned grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['edit']),
call grantPermissionsToRole(eMailAddressTenantRoleId, beneathRole(eMailAddressOwnerRoleUuid),
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*'])); -- TODO '*' -> 'edit', 'view' beingItselfA(domainTenant(parentDomain.unixUserName, parentDomain.name))
);
RETURN NEW; RETURN NEW;
END; $$; END; $$;
@ -59,22 +75,6 @@ CREATE TRIGGER createRbacRulesForEMailAddress_Trigger
-- create RBAC restricted view -- create RBAC restricted view
abort;
set session authorization default ;
START TRANSACTION;
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
SET LOCAL hsadminng.assumedRoles = 'customer#bbb.owner;customer#bbc.owner';
-- SET LOCAL hsadminng.assumedRoles = 'package#bbb00.owner;package#bbb01.owner';
select count(*) from queryAccessibleObjectUuidsOfSubjectIds( 'view', currentSubjectIds(), 7) as a
join rbacobject as o on a=o.uuid;
/* SELECT DISTINCT target.*
FROM EMailAddress AS target
JOIN queryAccessibleObjectUuidsOfSubjectIds( 'view', currentSubjectIds()) AS allowedObjId
ON target.uuid = allowedObjId;*/
END TRANSACTION;
SET SESSION SESSION AUTHORIZATION DEFAULT; SET SESSION SESSION AUTHORIZATION DEFAULT;
ALTER TABLE EMailAddress ENABLE ROW LEVEL SECURITY; ALTER TABLE EMailAddress ENABLE ROW LEVEL SECURITY;
DROP VIEW IF EXISTS EMailAddress_rv; DROP VIEW IF EXISTS EMailAddress_rv;
@ -99,7 +99,7 @@ DO LANGUAGE plpgsql $$
SET hsadminng.currentUser TO ''; SET hsadminng.currentUser TO '';
FOR dom IN (SELECT * FROM domain) LOOP FOR dom IN (SELECT * FROM domain) LOOP
FOR t IN 0..5 LOOP FOR t IN 0..4 LOOP
currentTask = 'creating RBAC test EMailAddress #' || t || ' for Domain ' || dom.name; currentTask = 'creating RBAC test EMailAddress #' || t || ' for Domain ' || dom.name;
RAISE NOTICE 'task: %', currentTask; RAISE NOTICE 'task: %', currentTask;

View File

@ -35,16 +35,18 @@ ROLLBACK;
BEGIN TRANSACTION; BEGIN TRANSACTION;
SET SESSION SESSION AUTHORIZATION restricted; SET SESSION SESSION AUTHORIZATION restricted;
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net'; SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
SET LOCAL hsadminng.assumedRoles = 'customer#bbb.admin;customer#bbc.admin'; SET LOCAL hsadminng.assumedRoles = 'customer#aab.admin;customer#aac.admin';
SELECT * FROM package_rv p; SELECT * FROM package_rv p;
END TRANSACTION; END TRANSACTION;
---
-- hostsharing admin assuming two customer admin role and listing all accessible unixusers -- hostsharing admin assuming two customer admin role and listing all accessible unixusers
ROLLBACK; ROLLBACK;
BEGIN TRANSACTION; BEGIN TRANSACTION;
SET SESSION SESSION AUTHORIZATION restricted; SET SESSION SESSION AUTHORIZATION restricted;
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net'; SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
SET LOCAL hsadminng.assumedRoles = 'customer#bbb.admin;customer#bbc.admin'; SET LOCAL hsadminng.assumedRoles = 'customer#aab.admin;customer#aac.admin';
SELECT c.prefix, c.reference, uu.* SELECT c.prefix, c.reference, uu.*
FROM unixuser_rv uu FROM unixuser_rv uu
@ -52,10 +54,12 @@ FROM unixuser_rv uu
JOIN customer_rv c ON c.uuid = p.customeruuid; JOIN customer_rv c ON c.uuid = p.customeruuid;
END TRANSACTION; END TRANSACTION;
---
BEGIN TRANSACTION; BEGIN TRANSACTION;
SET SESSION SESSION AUTHORIZATION restricted; SET SESSION SESSION AUTHORIZATION restricted;
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net'; SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
SET LOCAL hsadminng.assumedRoles = 'customer#bbb.admin;customer#bbc.admin'; SET LOCAL hsadminng.assumedRoles = 'customer#aab.admin;customer#aac.admin';
SELECT p.name, uu.name, dom.name SELECT p.name, uu.name, dom.name
FROM domain_rv dom FROM domain_rv dom
@ -64,24 +68,26 @@ FROM domain_rv dom
JOIN customer_rv c ON c.uuid = p.customeruuid; JOIN customer_rv c ON c.uuid = p.customeruuid;
END TRANSACTION; END TRANSACTION;
---
BEGIN TRANSACTION; BEGIN TRANSACTION;
SET SESSION SESSION AUTHORIZATION restricted; SET SESSION SESSION AUTHORIZATION restricted;
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net'; SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
SET LOCAL hsadminng.assumedRoles = 'customer#bbb.admin;customer#bbc.admin'; SET LOCAL hsadminng.assumedRoles = 'customer#aab.admin;customer#aac.admin';
-- TODO: we need tenant roles on parent objects
-- SET LOCAL hsadminng.assumedRoles = 'package#bbb03.owner;package#bbb08.owner';
SELECT p.name as "package", ema.localPart || '@' || dom.name as "email-address" SELECT c.prefix, p.name as "package", ema.localPart || '@' || dom.name as "email-address"
FROM emailaddress_rv ema FROM emailaddress_rv ema
JOIN domain_rv dom ON dom.uuid = ema.domainuuid JOIN domain_rv dom ON dom.uuid = ema.domainuuid
JOIN unixuser_rv uu ON uu.uuid = dom.unixuseruuid JOIN unixuser_rv uu ON uu.uuid = dom.unixuseruuid
JOIN package_rv p ON p.uuid = uu.packageuuid JOIN package_rv p ON p.uuid = uu.packageuuid
JOIN customer_rv c ON c.uuid = p.customeruuid; JOIN customer_rv c ON c.uuid = p.customeruuid;
END TRANSACTION; END TRANSACTION;
---
ROLLBACK; ROLLBACK;
BEGIN TRANSACTION; BEGIN TRANSACTION;
SET SESSION SESSION AUTHORIZATION restricted; SET SESSION SESSION AUTHORIZATION restricted;
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net'; SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
select * from customer_rv c where c.prefix='bbb'; select * from customer_rv c where c.prefix='aab';
END TRANSACTION; END TRANSACTION;

View File

@ -5,7 +5,7 @@
DROP VIEW IF EXISTS "BusinessTableStatisticsV"; DROP VIEW IF EXISTS "BusinessTableStatisticsV";
CREATE VIEW "BusinessTableStatisticsV" AS CREATE VIEW "BusinessTableStatisticsV" AS
SELECT no, to_char("count", '999 999 999') as "count", to_char("required", '999 999 999') as "required", to_char("count"::float/"required"::float, '990.9') as "factor", "table" SELECT no, to_char("count", '999 999 999') as "count", to_char("required", '999 999 999') as "required", to_char("count"::float/"required"::float, '990.999') as "factor", "table"
FROM (select 1 as no, count(*) as "count", 7000 as "required", 'customers' as "table" FROM (select 1 as no, count(*) as "count", 7000 as "required", 'customers' as "table"
from customer from customer
UNION UNION
@ -22,3 +22,5 @@ FROM (select 1 as no, count(*) as "count", 7000 as "required", 'customers' as "
from emailaddress from emailaddress
) totals ) totals
ORDER BY totals.no; ORDER BY totals.no;
SELECT * FROM "BusinessTableStatisticsV";