add unixuser prototype as preparation for testability of grants

This commit is contained in:
Michael Hoennig 2022-08-14 16:44:26 +02:00
parent bc05fb1eeb
commit 7869d07d30
11 changed files with 443 additions and 206 deletions

View File

@ -629,19 +629,21 @@ create or replace function queryAllRbacUsersWithPermissionsFor(objectId uuid)
language sql as $$ language sql as $$
select * select *
from RbacUser from RbacUser
where uuid in (with recursive grants as (select descendantUuid, where uuid in (
ascendantUuid -- @formatter:off
from RbacGrants with recursive grants as (
where descendantUuid = objectId select descendantUuid, ascendantUuid
union all from RbacGrants
select "grant".descendantUuid, where descendantUuid = objectId
"grant".ascendantUuid union all
from RbacGrants "grant" select "grant".descendantUuid, "grant".ascendantUuid
inner join grants recur on recur.ascendantUuid = "grant".descendantUuid) from RbacGrants "grant"
select ascendantUuid inner join grants recur on recur.ascendantUuid = "grant".descendantUuid
from grants); )
-- @formatter:on
select ascendantUuid
from grants);
$$; $$;
--// --//

View File

@ -19,7 +19,7 @@ select *
where isGranted(currentSubjectIds(), r.uuid) where isGranted(currentSubjectIds(), r.uuid)
) as unordered ) as unordered
-- @formatter:on -- @formatter:on
order by objectIdName; order by objectTable || '#' || objectIdName || '.' || roleType;
grant all privileges on rbacrole_rv to restricted; grant all privileges on rbacrole_rv to restricted;
--// --//
@ -49,7 +49,7 @@ select userName, objectTable||'#'||objectIdName||'.'||roletype as roleIdName,
where isGranted(currentSubjectIds(), r.uuid) where isGranted(currentSubjectIds(), r.uuid)
) as unordered ) as unordered
-- @formatter:on -- @formatter:on
order by objectIdName; order by roleIdName;
grant all privileges on rbacrole_rv to restricted; grant all privileges on rbacrole_rv to restricted;
--// --//

View File

@ -9,6 +9,6 @@ create table if not exists package
uuid uuid unique references RbacObject (uuid), uuid uuid unique references RbacObject (uuid),
customerUuid uuid references customer (uuid), customerUuid uuid references customer (uuid),
name varchar(5), name varchar(5),
description varchar(80) description varchar(96)
); );
--// --//

View File

@ -0,0 +1,14 @@
--liquibase formatted sql
-- ============================================================================
--changeset hs-unixuser-MAIN-TABLE:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create table if not exists UnixUser
(
uuid uuid unique references RbacObject (uuid),
packageUuid uuid references package (uuid),
name character varying(32),
description character varying(96)
);
--//

View File

@ -0,0 +1,211 @@
--liquibase formatted sql
-- ============================================================================
--changeset hs-package-rbac-CREATE-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the related RbacObject through a BEFORE INSERT TRIGGER.
*/
drop trigger if exists createRbacObjectForUnixUser_Trigger on UnixUser;
create trigger createRbacObjectForUnixUser_Trigger
before insert
on UnixUser
for each row
execute procedure createRbacObject();
--//
-- ============================================================================
--changeset hs-unixuser-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create or replace function unixUserOwner(uu UnixUser)
returns RbacRoleDescriptor
returns null on null input
language plpgsql as $$
begin
return roleDescriptor('unixuser', uu.uuid, 'owner');
end; $$;
create or replace function unixUserAdmin(uu UnixUser)
returns RbacRoleDescriptor
returns null on null input
language plpgsql as $$
begin
return roleDescriptor('unixuser', uu.uuid, 'admin');
end; $$;
create or replace function unixUserTenant(uu UnixUser)
returns RbacRoleDescriptor
returns null on null input
language plpgsql as $$
begin
return roleDescriptor('unixuser', uu.uuid, 'tenant');
end; $$;
create or replace function createUnixUserTenantRoleIfNotExists(unixUser UnixUser)
returns uuid
returns null on null input
language plpgsql as $$
declare
unixUserTenantRoleDesc RbacRoleDescriptor;
unixUserTenantRoleUuid uuid;
begin
unixUserTenantRoleDesc = unixUserTenant(unixUser);
unixUserTenantRoleUuid = findRoleId(unixUserTenantRoleDesc);
if unixUserTenantRoleUuid is not null then
return unixUserTenantRoleUuid;
end if;
return createRole(
unixUserTenantRoleDesc,
grantingPermissions(forObjectUuid => unixUser.uuid, permitOps => array ['view']),
beneathRole(unixUserAdmin(unixUser))
);
end; $$;
--//
-- ============================================================================
--changeset hs-unixuser-rbac-ROLES-CREATION:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles and their assignments for a new UnixUser for the AFTER INSERT TRIGGER.
*/
create or replace function createRbacRulesForUnixUser()
returns trigger
language plpgsql
strict as $$
declare
parentPackage package;
unixuserOwnerRoleId uuid;
unixuserAdminRoleId uuid;
begin
if TG_OP <> 'INSERT' then
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
select * from package where uuid = NEW.packageUuid into parentPackage;
-- an owner role is created and assigned to the package's admin group
unixuserOwnerRoleId = createRole(
unixUserOwner(NEW),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['*']),
beneathRole(packageAdmin(parentPackage))
);
-- and a unixuser admin role is created and assigned to the unixuser owner as well
unixuserAdminRoleId = createRole(
unixUserAdmin(NEW),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['edit']),
beneathRole(unixuserOwnerRoleId),
beingItselfA(packageTenant(parentPackage))
);
-- a tenent role is only created on demand
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new UnixUser.
*/
drop trigger if exists createRbacRulesForUnixUser_Trigger on UnixUser;
create trigger createRbacRulesForUnixUser_Trigger
after insert
on UnixUser
for each row
execute procedure createRbacRulesForUnixUser();
--//
-- ============================================================================
--changeset hs-unixuser-rbac-ROLES-REMOVAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Deletes the roles and their assignments of a deleted UnixUser for the BEFORE DELETE TRIGGER.
*/
create or replace function deleteRbacRulesForUnixUser()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
call deleteRole(findRoleId(unixUserOwner(OLD)));
call deleteRole(findRoleId(unixUserAdmin(OLD)));
call deleteRole(findRoleId(unixUserTenant(OLD)));
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
end; $$;
/*
An BEFORE DELETE TRIGGER which deletes the role structure of a UnixUser.
*/
drop trigger if exists deleteRbacRulesForUnixUser_Trigger on package;
create trigger deleteRbacRulesForUnixUser_Trigger
before delete
on UnixUser
for each row
execute procedure deleteRbacRulesForUnixUser();
--//
-- ============================================================================
--changeset hs-unixuser-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a view to the UnixUser main table which maps the identifying name
(in this case, actually the column `name`) to the objectUuid.
*/
drop view if exists UnixUser_iv;
create or replace view UnixUser_iv as
select distinct target.uuid, target.name as idName
from UnixUser as target;
-- TODO: Is it ok that everybody has access to this information?
grant all privileges on UnixUser_iv to restricted;
/*
Returns the objectUuid for a given identifying name (in this case, actually the column `name`).
*/
create or replace function unixUserUuidByIdName(idName varchar)
returns uuid
language sql
strict as $$
select uuid from UnixUser_iv iv where iv.idName = unixUserUuidByIdName.idName;
$$;
/*
Returns the identifying name for a given objectUuid (in this case the name).
*/
create or replace function unixUserIdNameByUuid(uuid uuid)
returns varchar
stable leakproof
language sql
strict as $$
select idName from UnixUser_iv iv where iv.uuid = unixUserIdNameByUuid.uuid;
$$;
--//
-- ============================================================================
--changeset hs-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a view to the customer main table which maps the identifying name
(in this case, the prefix) to the objectUuid.
*/
drop view if exists unixuser_rv;
create or replace view unixuser_rv as
select target.*
from unixuser as target
where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'unixuser', currentSubjectIds()));
grant all privileges on unixuser_rv to restricted;
--//

View File

@ -0,0 +1,62 @@
--liquibase formatted sql
-- ============================================================================
--changeset hs-unixuser-TEST-DATA-GENERATOR:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates test data for the package main table.
*/
create or replace procedure createUnixUserTestData(
minCustomerReference integer, -- skip customers with reference below this
unixUserPerPackage integer, -- create this many unix users for each package
doCommitAfterEach boolean -- only for mass data creation outside of Liquibase
)
language plpgsql as $$
declare
pac record;
pacAdmin varchar;
currentTask varchar;
begin
set hsadminng.currentUser to '';
for pac in
(select p.uuid, p.name
from package p
join customer c on p.customeruuid = c.uuid
where c.reference >= minCustomerReference)
loop
for t in 0..(unixUserPerPackage-1)
loop
currentTask = 'creating RBAC test unixuser #' || t || ' for package ' || pac.name || ' #' || pac.uuid;
raise notice 'task: %', currentTask;
pacAdmin = 'admin@' || pac.name || '.example.com';
set local hsadminng.currentUser to 'mike@hostsharing.net'; -- TODO: use a package-admin
set local hsadminng.assumedRoles = '';
set local hsadminng.currentTask to currentTask;
insert
into unixuser (name, packageUuid)
values (pac.name || '-' || intToVarChar(t, 4), pac.uuid);
if doCommitAfterEach then
commit;
end if;
end loop;
end loop;
end;
$$;
--//
-- ============================================================================
--changeset hs-unixuser-TEST-DATA-GENERATION:1 context=dev,tc endDelimiter:--//
-- ----------------------------------------------------------------------------
do language plpgsql $$
begin
call createUnixUserTestData(0, 2, false);
end;
$$;
--//

View File

@ -1,159 +0,0 @@
-- ========================================================
-- UnixUser example with RBAC
-- --------------------------------------------------------
set session session authorization default;
create table if not exists UnixUser
(
uuid uuid unique references RbacObject (uuid),
name character varying(32),
comment character varying(96),
packageUuid uuid references package (uuid)
);
create or replace function unixUserOwner(uu UnixUser)
returns RbacRoleDescriptor
returns null on null input
language plpgsql as $$
begin
return roleDescriptor('unixuser', uu.uuid, 'owner');
end; $$;
create or replace function unixUserAdmin(uu UnixUser)
returns RbacRoleDescriptor
returns null on null input
language plpgsql as $$
begin
return roleDescriptor('unixuser', uu.uuid, 'admin');
end; $$;
create or replace function unixUserTenant(uu UnixUser)
returns RbacRoleDescriptor
returns null on null input
language plpgsql as $$
begin
return roleDescriptor('unixuser', uu.uuid, 'tenant');
end; $$;
create or replace function createUnixUserTenantRoleIfNotExists(unixUser UnixUser)
returns uuid
returns null on null input
language plpgsql as $$
declare
unixUserTenantRoleDesc RbacRoleDescriptor;
unixUserTenantRoleUuid uuid;
begin
unixUserTenantRoleDesc = unixUserTenant(unixUser);
unixUserTenantRoleUuid = findRoleId(unixUserTenantRoleDesc);
if unixUserTenantRoleUuid is not null then
return unixUserTenantRoleUuid;
end if;
return createRole(
unixUserTenantRoleDesc,
grantingPermissions(forObjectUuid => unixUser.uuid, permitOps => array ['view']),
beneathRole(unixUserAdmin(unixUser))
);
end; $$;
drop trigger if exists createRbacObjectForUnixUser_Trigger on UnixUser;
create trigger createRbacObjectForUnixUser_Trigger
before insert
on UnixUser
for each row
execute procedure createRbacObject();
create or replace function createRbacRulesForUnixUser()
returns trigger
language plpgsql
strict as $$
declare
parentPackage package;
unixuserOwnerRoleId uuid;
unixuserAdminRoleId uuid;
begin
if TG_OP <> 'INSERT' then
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
select * from package where uuid = NEW.packageUuid into parentPackage;
-- an owner role is created and assigned to the package's admin group
unixuserOwnerRoleId = createRole(
unixUserOwner(NEW),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['*']),
beneathRole(packageAdmin(parentPackage))
);
-- and a unixuser admin role is created and assigned to the unixuser owner as well
unixuserAdminRoleId = createRole(
unixUserAdmin(NEW),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['edit']),
beneathRole(unixuserOwnerRoleId),
beingItselfA(packageTenant(parentPackage))
);
-- a tenent role is only created on demand
return NEW;
end; $$;
drop trigger if exists createRbacRulesForUnixUser_Trigger on UnixUser;
create trigger createRbacRulesForUnixUser_Trigger
after insert
on UnixUser
for each row
execute procedure createRbacRulesForUnixUser();
-- TODO: CREATE OR REPLACE FUNCTION deleteRbacRulesForUnixUser()
-- create RBAC-restricted view
set session session authorization default;
-- ALTER TABLE unixuser ENABLE ROW LEVEL SECURITY;
drop view if exists unixuser_rv;
create or replace view unixuser_rv as
select target.*
from unixuser as target
where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'unixuser', currentSubjectIds()));
grant all privileges on unixuser_rv to restricted;
-- generate UnixUser test data
do language plpgsql $$
declare
pac record;
pacAdmin varchar;
currentTask varchar;
begin
set hsadminng.currentUser to '';
for pac in (select p.uuid, p.name
from package p
join customer c on p.customeruuid = c.uuid
-- WHERE c.reference >= 18000
)
loop
for t in 0..9
loop
currentTask = 'creating RBAC test unixuser #' || t || ' for package ' || pac.name || ' #' || pac.uuid;
raise notice 'task: %', currentTask;
pacAdmin = 'admin@' || pac.name || '.example.com';
set local hsadminng.currentUser to 'mike@hostsharing.net'; -- TODO: use a package-admin
set local hsadminng.assumedRoles = '';
set local hsadminng.currentTask to currentTask;
insert
into unixuser (name, packageUuid)
values (pac.name || '-' || intToVarChar(t, 4), pac.uuid);
commit;
end loop;
end loop;
end;
$$;

View File

@ -30,6 +30,12 @@ databaseChangeLog:
- include: - include:
file: db/changelog/2022-07-29-070-hs-package-rbac.sql file: db/changelog/2022-07-29-070-hs-package-rbac.sql
- include: - include:
file: db/changelog/2022-07-29-070-hs-package-test-data.sql file: db/changelog/2022-07-29-070-hs-package-test-data.sql
- include:
file: db/changelog/2022-08-14-080-hs-unixuser.sql
- include:
file: db/changelog/2022-08-14-081-hs-unixuser-rbac.sql
- include:
file: db/changelog/2022-08-14-082-hs-unixuser-test-data.sql

View File

@ -12,7 +12,7 @@ import org.springframework.boot.test.web.server.LocalServerPort;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.*;
@SpringBootTest( @SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
@ -50,14 +50,15 @@ class RbacRoleControllerAcceptanceTest {
.then().assertThat() .then().assertThat()
.statusCode(200) .statusCode(200)
.contentType("application/json") .contentType("application/json")
.body("[0].roleName", is("customer#aaa.owner")) .body("[0].roleName", is("customer#aaa.admin"))
.body("[1].roleName", is("customer#aaa.admin")) .body("[1].roleName", is("customer#aaa.owner"))
.body("[2].roleName", is("customer#aaa.tenant")) .body("[2].roleName", is("customer#aaa.tenant"))
.body("[3].roleName", is("package#aaa00.owner"))
.body("[4].roleName", is("package#aaa00.tenant"))
// ... // ...
.body("[36].roleName", is("global#hostsharing.admin")) .body("", hasItem(hasEntry("roleName", "global#hostsharing.admin")))
.body( "size()", is(37)); .body("", hasItem(hasEntry("roleName", "customer#aab.admin")))
.body("", hasItem(hasEntry("roleName", "package#aab00.admin")))
.body("", hasItem(hasEntry("roleName", "unixuser#aab00-aaaa.owner")))
.body( "size()", is(73)); // increases with new test data
// @formatter:on // @formatter:on
} }
@ -69,17 +70,18 @@ class RbacRoleControllerAcceptanceTest {
RestAssured RestAssured
.given() .given()
.header("current-user", "mike@hostsharing.net") .header("current-user", "mike@hostsharing.net")
.header("assumed-roles", "package#aaa00.admin") .header("assumed-roles", "package#aab00.admin")
.port(port) .port(port)
.when() .when()
.get("http://localhost/api/rbac-roles") .get("http://localhost/api/rbac-roles")
.then().assertThat() .then().assertThat()
.statusCode(200) .statusCode(200)
.contentType("application/json") .contentType("application/json")
.body("[0].roleName", is("customer#aaa.tenant")) .body("[0].roleName", is("customer#aab.tenant"))
.body("[1].roleName", is("package#aaa00.admin")) .body("[1].roleName", is("package#aab00.admin"))
.body("[2].roleName", is("package#aaa00.tenant")) .body("[2].roleName", is("package#aab00.tenant"))
.body("size()", is(3)); .body("[3].roleName", is("unixuser#aab00-aaaa.admin"))
.body("size()", is(7)); // increases with new test data
// @formatter:on // @formatter:on
} }
@ -90,17 +92,18 @@ class RbacRoleControllerAcceptanceTest {
// @formatter:off // @formatter:off
RestAssured RestAssured
.given() .given()
.header("current-user", "aaa00@aaa.example.com") .header("current-user", "aac00@aac.example.com")
.port(port) .port(port)
.when() .when()
.get("http://localhost/api/rbac-roles") .get("http://localhost/api/rbac-roles")
.then().assertThat() .then().assertThat()
.statusCode(200) .statusCode(200)
.contentType("application/json") .contentType("application/json")
.body("[0].roleName", is("customer#aaa.tenant")) .body("[0].roleName", is("customer#aac.tenant"))
.body("[1].roleName", is("package#aaa00.admin")) .body("[1].roleName", is("package#aac00.admin"))
.body("[2].roleName", is("package#aaa00.tenant")) .body("[2].roleName", is("package#aac00.tenant"))
.body("size()", is(3));; .body("[3].roleName", is("unixuser#aac00-aaaa.admin"))
.body("size()", is(7)); // increases with new test data
// @formatter:on // @formatter:on
} }

View File

@ -59,7 +59,7 @@ class RbacRoleRepositoryIntegrationTest {
final var result = rbacRoleRepository.findAll(); final var result = rbacRoleRepository.findAll();
// then // then
exactlyTheseRbacRolesAreReturned(result, ALL_TEST_DATA_ROLES); allTheseRbacRolesAreReturned(result, ALL_TEST_DATA_ROLES);
} }
@Test @Test
@ -72,7 +72,7 @@ class RbacRoleRepositoryIntegrationTest {
final var result = rbacRoleRepository.findAll(); final var result = rbacRoleRepository.findAll();
then: then:
exactlyTheseRbacRolesAreReturned(result, ALL_TEST_DATA_ROLES); allTheseRbacRolesAreReturned(result, ALL_TEST_DATA_ROLES);
} }
@Test @Test
@ -84,13 +84,33 @@ class RbacRoleRepositoryIntegrationTest {
final var result = rbacRoleRepository.findAll(); final var result = rbacRoleRepository.findAll();
// then: // then:
exactlyTheseRbacRolesAreReturned( allTheseRbacRolesAreReturned(
result, result,
// @formatter:off // @formatter:off
"customer#aaa.admin", "customer#aaa.tenant", "customer#aaa.admin",
"package#aaa00.admin", "package#aaa00.owner", "package#aaa00.tenant", "customer#aaa.tenant",
"package#aaa01.admin", "package#aaa01.owner", "package#aaa01.tenant", "package#aaa00.admin",
"package#aaa02.admin", "package#aaa02.owner", "package#aaa02.tenant" "package#aaa00.owner",
"package#aaa00.tenant",
"package#aaa01.admin",
"package#aaa01.owner",
"package#aaa01.tenant",
// ...
"unixuser#aaa00-aaaa.admin",
"unixuser#aaa00-aaaa.owner",
// ..
"unixuser#aaa01-aaaa.admin",
"unixuser#aaa01-aaaa.owner"
// @formatter:on
);
noneOfTheseRbacRolesIsReturned(
result,
// @formatter:off
"global#hostsharing.admin",
"customer#aaa.owner",
"package#aab00.admin",
"package#aab00.owner",
"package#aab00.tenant"
// @formatter:on // @formatter:on
); );
} }
@ -102,7 +122,15 @@ class RbacRoleRepositoryIntegrationTest {
final var result = rbacRoleRepository.findAll(); final var result = rbacRoleRepository.findAll();
exactlyTheseRbacRolesAreReturned(result, "customer#aaa.tenant", "package#aaa00.tenant", "package#aaa00.admin"); exactlyTheseRbacRolesAreReturned(
result,
"customer#aaa.tenant",
"package#aaa00.admin",
"package#aaa00.tenant",
"unixuser#aaa00-aaaa.admin",
"unixuser#aaa00-aaaa.owner",
"unixuser#aaa00-aaab.admin",
"unixuser#aaa00-aaab.owner");
} }
@Test @Test
@ -191,4 +219,16 @@ class RbacRoleRepositoryIntegrationTest {
.containsExactlyInAnyOrder(expectedRoleNames); .containsExactlyInAnyOrder(expectedRoleNames);
} }
void allTheseRbacRolesAreReturned(final List<RbacRoleEntity> actualResult, final String... expectedRoleNames) {
assertThat(actualResult)
.extracting(RbacRoleEntity::getRoleName)
.contains(expectedRoleNames);
}
void noneOfTheseRbacRolesIsReturned(final List<RbacRoleEntity> actualResult, final String... unexpectedRoleNames) {
assertThat(actualResult)
.extracting(RbacRoleEntity::getRoleName)
.doesNotContain(unexpectedRoleNames);
}
} }

View File

@ -237,7 +237,7 @@ class RbacUserRepositoryIntegrationTest {
final var result = rbacUserRepository.findPermissionsOfUser("mike@hostsharing.net"); final var result = rbacUserRepository.findPermissionsOfUser("mike@hostsharing.net");
// then // then
exactlyTheseRbacPermissionsAreReturned(result, ALL_USER_PERMISSIONS); allTheseRbacPermissionsAreReturned(result, ALL_USER_PERMISSIONS);
} }
@Test @Test
@ -266,7 +266,7 @@ class RbacUserRepositoryIntegrationTest {
final var result = rbacUserRepository.findPermissionsOfUser("admin@aaa.example.com"); final var result = rbacUserRepository.findPermissionsOfUser("admin@aaa.example.com");
// then // then
exactlyTheseRbacPermissionsAreReturned( allTheseRbacPermissionsAreReturned(
result, result,
// @formatter:off // @formatter:off
"customer#aaa.admin -> customer#aaa: add-package", "customer#aaa.admin -> customer#aaa: add-package",
@ -276,14 +276,25 @@ class RbacUserRepositoryIntegrationTest {
"package#aaa00.admin -> package#aaa00: add-domain", "package#aaa00.admin -> package#aaa00: add-domain",
"package#aaa00.admin -> package#aaa00: add-unixuser", "package#aaa00.admin -> package#aaa00: add-unixuser",
"package#aaa00.tenant -> package#aaa00: view", "package#aaa00.tenant -> package#aaa00: view",
"unixuser#aaa00-aaaa.owner -> unixuser#aaa00-aaaa: *",
"package#aaa01.admin -> package#aaa01: add-domain", "package#aaa01.admin -> package#aaa01: add-domain",
"package#aaa01.admin -> package#aaa01: add-unixuser", "package#aaa01.admin -> package#aaa01: add-unixuser",
"package#aaa01.tenant -> package#aaa01: view", "package#aaa01.tenant -> package#aaa01: view",
"unixuser#aaa01-aaaa.owner -> unixuser#aaa01-aaaa: *",
"package#aaa02.admin -> package#aaa02: add-domain", "package#aaa02.admin -> package#aaa02: add-domain",
"package#aaa02.admin -> package#aaa02: add-unixuser", "package#aaa02.admin -> package#aaa02: add-unixuser",
"package#aaa02.tenant -> package#aaa02: view" "package#aaa02.tenant -> package#aaa02: view",
"unixuser#aaa02-aaaa.owner -> unixuser#aaa02-aaaa: *"
// @formatter:on
);
noneOfTheseRbacPermissionsAreReturned(
result,
// @formatter:off
"customer#aab.admin -> customer#aab: add-package",
"customer#aab.admin -> customer#aab: view",
"customer#aab.tenant -> customer#aab: view"
// @formatter:on // @formatter:on
); );
} }
@ -313,14 +324,29 @@ class RbacUserRepositoryIntegrationTest {
final var result = rbacUserRepository.findPermissionsOfUser("aaa00@aaa.example.com"); final var result = rbacUserRepository.findPermissionsOfUser("aaa00@aaa.example.com");
// then // then
exactlyTheseRbacPermissionsAreReturned( allTheseRbacPermissionsAreReturned(
result, result,
// @formatter:off // @formatter:off
"customer#aaa.tenant -> customer#aaa: view", "customer#aaa.tenant -> customer#aaa: view",
// "customer#aaa.admin -> customer#aaa: view" - Not permissions through the customer admin! // "customer#aaa.admin -> customer#aaa: view" - Not permissions through the customer admin!
"package#aaa00.admin -> package#aaa00: add-unixuser", "package#aaa00.admin -> package#aaa00: add-unixuser",
"package#aaa00.admin -> package#aaa00: add-domain", "package#aaa00.admin -> package#aaa00: add-domain",
"package#aaa00.tenant -> package#aaa00: view" "package#aaa00.tenant -> package#aaa00: view",
"unixuser#aaa00-aaaa.owner -> unixuser#aaa00-aaaa: *",
"unixuser#aaa00-aaab.owner -> unixuser#aaa00-aaab: *"
// @formatter:on
);
noneOfTheseRbacPermissionsAreReturned(
result,
// @formatter:off
"customer#aab.admin -> customer#aab: add-package",
"customer#aab.admin -> customer#aab: view",
"customer#aab.tenant -> customer#aab: view",
"package#aab00.admin -> package#aab00: add-unixuser",
"package#aab00.admin -> package#aab00: add-domain",
"package#aab00.tenant -> package#aab00: view",
"unixuser#aab00-aaaa.owner -> unixuser#aab00-aaaa: *",
"unixuser#aab00-aaab.owner -> unixuser#aab00-aaab: *"
// @formatter:on // @formatter:on
); );
} }
@ -346,7 +372,7 @@ class RbacUserRepositoryIntegrationTest {
final var result = rbacUserRepository.findPermissionsOfUser("aaa00@aaa.example.com"); final var result = rbacUserRepository.findPermissionsOfUser("aaa00@aaa.example.com");
// then // then
exactlyTheseRbacPermissionsAreReturned( allTheseRbacPermissionsAreReturned(
result, result,
// @formatter:off // @formatter:off
"customer#aaa.tenant -> customer#aaa: view", "customer#aaa.tenant -> customer#aaa: view",
@ -356,6 +382,22 @@ class RbacUserRepositoryIntegrationTest {
"package#aaa00.tenant -> package#aaa00: view" "package#aaa00.tenant -> package#aaa00: view"
// @formatter:on // @formatter:on
); );
noneOfTheseRbacPermissionsAreReturned(
result,
// @formatter:off
// no customer admin permissions
"customer#aaa.admin -> customer#aaa: add-package",
// no permissions on other customer's objects
"customer#aab.admin -> customer#aab: add-package",
"customer#aab.admin -> customer#aab: view",
"customer#aab.tenant -> customer#aab: view",
"package#aab00.admin -> package#aab00: add-unixuser",
"package#aab00.admin -> package#aab00: add-domain",
"package#aab00.tenant -> package#aab00: view",
"unixuser#aab00-aaaa.owner -> unixuser#aab00-aaaa: *",
"unixuser#aab00-aaab.owner -> unixuser#aab00-aaab: *"
// @formatter:on
);
} }
} }
@ -391,4 +433,20 @@ class RbacUserRepositoryIntegrationTest {
.containsExactlyInAnyOrder(expectedRoleNames); .containsExactlyInAnyOrder(expectedRoleNames);
} }
void allTheseRbacPermissionsAreReturned(
final List<RbacUserPermission> actualResult,
final String... expectedRoleNames) {
assertThat(actualResult)
.extracting(p -> p.getRoleName() + " -> " + p.getObjectTable() + "#" + p.getObjectIdName() + ": " + p.getOp())
.contains(expectedRoleNames);
}
void noneOfTheseRbacPermissionsAreReturned(
final List<RbacUserPermission> actualResult,
final String... unexpectedRoleNames) {
assertThat(actualResult)
.extracting(p -> p.getRoleName() + " -> " + p.getObjectTable() + "#" + p.getObjectIdName() + ": " + p.getOp())
.doesNotContain(unexpectedRoleNames);
}
} }