-- ======================================================== -- EMailAddress example with RBAC -- -------------------------------------------------------- SET SESSION SESSION AUTHORIZATION DEFAULT ; CREATE TABLE IF NOT EXISTS EMailAddress ( uuid uuid UNIQUE REFERENCES RbacObject(uuid), localPart character varying(64), domainUuid uuid REFERENCES domain(uuid) ); DROP TRIGGER IF EXISTS createRbacObjectForEMailAddress_Trigger ON EMailAddress; CREATE TRIGGER createRbacObjectForEMailAddress_Trigger BEFORE INSERT ON EMailAddress 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() RETURNS trigger LANGUAGE plpgsql STRICT AS $$ DECLARE parentDomain record; eMailAddress varchar; eMailAddressOwnerRoleUuid uuid; BEGIN IF TG_OP <> 'INSERT' THEN RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT'; END IF; 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; -- an owner role is created and assigned to the domains's admin group eMailAddressOwnerRoleUuid = createRole( emailAddressOwner(eMailAddress), grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']), beneathRole(domainAdmin( parentDomain.unixUserName, parentDomain.name)) ); -- and an admin role is created and assigned to the unixuser owner as well perform createRole( emailAddressAdmin(eMailAddress), grantingPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['edit']), beneathRole(eMailAddressOwnerRoleUuid), beingItselfA(domainTenant(parentDomain.unixUserName, parentDomain.name)) ); RETURN NEW; END; $$; DROP TRIGGER IF EXISTS createRbacRulesForEMailAddress_Trigger ON EMailAddress; CREATE TRIGGER createRbacRulesForEMailAddress_Trigger AFTER INSERT ON EMailAddress FOR EACH ROW EXECUTE PROCEDURE createRbacRulesForEMailAddress(); -- TODO: CREATE OR REPLACE FUNCTION deleteRbacRulesForEMailAddress() -- create RBAC-restricted view -- automatically updatable, but slow with WHERE IN SET SESSION SESSION AUTHORIZATION DEFAULT; ALTER TABLE EMailAddress ENABLE ROW LEVEL SECURITY; DROP VIEW IF EXISTS EMailAddress_rv; CREATE OR REPLACE VIEW EMailAddress_rv AS SELECT DISTINCT target.* FROM EMailAddress AS target WHERE target.uuid IN (SELECT DISTINCT uuid FROM queryAccessibleObjectUuidsOfSubjectIds( 'view', 'emailaddress', currentSubjectIds())); GRANT ALL PRIVILEGES ON EMailAddress_rv TO restricted; -- not automatically updatable, but fast with JOIN SET SESSION SESSION AUTHORIZATION DEFAULT; ALTER TABLE EMailAddress ENABLE ROW LEVEL SECURITY; DROP VIEW IF EXISTS EMailAddress_rv; CREATE OR REPLACE VIEW EMailAddress_rv AS SELECT target.* FROM EMailAddress AS target WHERE target.uuid IN (SELECT DISTINCT uuid FROM queryAccessibleObjectUuidsOfSubjectIds( 'view', 'emailaddress', currentSubjectIds())); GRANT ALL PRIVILEGES ON EMailAddress_rv TO restricted; -- generate EMailAddress test data DO LANGUAGE plpgsql $$ DECLARE dom record; pacAdmin varchar; currentTask varchar; BEGIN SET hsadminng.currentUser TO ''; FOR dom IN ( SELECT d.uuid, d.name, p.name as packageName FROM domain d JOIN unixuser u ON u.uuid = d.unixuseruuid JOIN package p ON u.packageuuid = p.uuid JOIN customer c ON p.customeruuid = c.uuid -- WHERE c.reference >= 18000 ) LOOP FOR t IN 0..4 LOOP currentTask = 'creating RBAC test EMailAddress #' || t || ' for Domain ' || dom.name; RAISE NOTICE 'task: %', currentTask; pacAdmin = 'admin@' || dom.packageName || '.example.com'; SET LOCAL hsadminng.currentUser TO pacAdmin; SET LOCAL hsadminng.assumedRoles = ''; SET LOCAL hsadminng.currentTask TO currentTask; INSERT INTO EMailAddress (localPart, domainUuid) VALUES ('local' || t, dom.uuid); COMMIT; END LOOP; END LOOP; END; $$;