generated BankAccount RBAC rules, BankAccount tests green again

This commit is contained in:
Michael Hoennig 2024-03-14 06:22:53 +01:00
parent 2774707801
commit 6b68b93082
10 changed files with 144 additions and 131 deletions

View File

@ -59,7 +59,7 @@ public class HsOfficeBankAccountEntity implements HasUuid, Stringifyable {
public static RbacView rbac() {
return rbacViewFor("bankAccount", HsOfficeBankAccountEntity.class)
.withIdentityView(SQL.projection("concat(iban, ':', holder)"))
.withIdentityView(SQL.projection("iban"))
.withUpdatableColumns("holder", "iban", "bic")
.toRole("global", GUEST).grantPermission("bankAccount", INSERT)

View File

@ -75,10 +75,11 @@ public class HsOfficeContactEntity implements Stringifyable, HasUuid {
})
.createSubRole(REFERRER, (with) -> {
with.permission(SELECT);
});
})
.toRole(GLOBAL, GUEST).grantPermission("contact", INSERT);
}
public static void main(String[] args) throws IOException {
rbac().generateWithBaseFileName("203-hs-office-contact-rbac-generated");
rbac().generateWithBaseFileName("203-hs-office-contact-rbac");
}
}

View File

@ -2,7 +2,6 @@ package net.hostsharing.hsadminng.hs.office.partner;
import lombok.*;
import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
import net.hostsharing.hsadminng.persistence.HasUuid;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
@ -14,10 +13,8 @@ import java.io.IOException;
import java.time.LocalDate;
import java.util.UUID;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.fetchedBySql;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.stringify.Stringify.stringify;

View File

@ -318,12 +318,12 @@ class RolesGrantsAndPermissionsGenerator {
generatePermissionsForRole(plPgSql, role);
generateUserGrantsForRole(plPgSql, role);
generateIncomingSuperRolesForRole(plPgSql, role);
generateOutgoingSubRolesForRole(plPgSql, role);
generateUserGrantsForRole(plPgSql, role);
plPgSql.chopTail(",\n");
plPgSql.writeLn();
});

View File

@ -37,7 +37,7 @@ declare
subRoleUuid uuid;
superRoleUuid uuid;
userUuid uuid;
grantedByRoleUuid uuid;
grantedByRoleUuid uuid; -- FIXME: rename to userGrantsByRoleUuid
begin
roleUuid := createRole(roleDescriptor);
@ -58,8 +58,9 @@ begin
end loop;
if cardinality(userUuids) > 0 then
-- direct grants to users need a grantedByRole which can revoke the grant
if grantedByRole is null then
grantedByRoleUuid := roleUuid;
grantedByRoleUuid := roleUuid; -- FIXME: or do we want to require an explicit grantedByRoleUuid?
else
grantedByRoleUuid := getRoleId(grantedByRole);
end if;

View File

@ -1,4 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator at 2024-03-14T09:00:15.769718298.
-- ============================================================================
--changeset hs-office-contact-rbac-OBJECT:1 endDelimiter:--//
@ -15,28 +17,28 @@ call generateRbacRoleDescriptors('hsOfficeContact', 'hs_office_contact');
-- ============================================================================
--changeset hs-office-contact-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset hs-office-contact-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles and their assignments for a new contact for the AFTER INSERT TRIGGER.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function createRbacRolesForHsOfficeContact()
returns trigger
language plpgsql
strict as $$
create or replace procedure buildRbacSystemForHsOfficeContact(
NEW hs_office_contact
)
language plpgsql as $$
declare
begin
if TG_OP <> 'INSERT' then
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
call enterTriggerForObjectUuid(NEW.uuid);
perform createRoleWithGrants(
hsOfficeContactOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()],
grantedByRole => globalAdmin()
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
@ -51,86 +53,105 @@ begin
incomingSuperRoles => array[hsOfficeContactAdmin(NEW)]
);
return NEW;
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_contact row.
*/
create trigger createRbacRolesForHsOfficeContact_Trigger
after insert
on hs_office_contact
create or replace function insertTriggerForHsOfficeContact_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeContact(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficeContact_tg
after insert on hs_office_contact
for each row
execute procedure createRbacRolesForHsOfficeContact();
execute procedure insertTriggerForHsOfficeContact_tf();
--//
-- ============================================================================
--changeset hs-office-contact-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_contact permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO hs_office_contact permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
roleUuid := findRoleId(globalGuest());
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_contact');
call grantPermissionToRole(permissionUuid, roleUuid);
END LOOP;
END;
$$;
/**
Adds hs_office_contact INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_contact_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
globalGuest(),
createPermission(NEW.uuid, 'INSERT', 'hs_office_contact'));
return NEW;
end; $$;
create trigger hs_office_contact_global_insert_tg
after insert on global
for each row
execute procedure hs_office_contact_global_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_contact.
*/
create or replace function hs_office_contact_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_contact not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
--//
-- ============================================================================
--changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_contact', $idName$
target.label
label
$idName$);
--//
-- ============================================================================
--changeset hs-office-contact-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_contact', 'target.label',
call generateRbacRestrictedView('hs_office_contact',
$orderBy$
label
$orderBy$,
$updates$
label = new.label,
postalAddress = new.postalAddress,
emailAddresses = new.emailAddresses,
phoneNumbers = new.phoneNumbers
$updates$);
--/
-- ============================================================================
--changeset hs-office-contact-rbac-NEW-CONTACT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-contact and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid;
begin
call defineContext('granting global new-contact permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-contact']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
*/
create or replace function addHsOfficeContactNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-contact not permitted for %',
array_to_string(currentSubjects(), ';', 'null');
end; $$;
/**
Checks if the user or assumed roles are allowed to create a new customer.
*/
create trigger hs_office_contact_insert_trigger
before insert
on hs_office_contact
for each row
-- TODO.spec: who is allowed to create new contacts
when ( not hasAssumedRole() )
execute procedure addHsOfficeContactNotAllowedForCurrentSubjects();
--//

View File

@ -1,6 +1,6 @@
### rbac bankAccount
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T19:09:38.350576842.
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-14T08:55:11.118624882.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%

View File

@ -1,5 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T19:09:38.359318650.
-- This code generated was by RbacViewPostgresGenerator at 2024-03-14T08:55:11.127959896.
-- ============================================================================
--changeset hs-office-bankaccount-rbac-OBJECT:1 endDelimiter:--//
@ -36,8 +37,8 @@ begin
perform createRoleWithGrants(
hsOfficeBankAccountOwner(NEW),
permissions => array['DELETE'],
userUuids => array[currentUserUuid()],
incomingSuperRoles => array[globalAdmin()]
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
@ -72,9 +73,9 @@ create trigger insertTriggerForHsOfficeBankAccount_tg
after insert on hs_office_bankaccount
for each row
execute procedure insertTriggerForHsOfficeBankAccount_tf();
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
@ -108,8 +109,8 @@ create or replace function hs_office_bankaccount_global_insert_tf()
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_bankaccount'),
globalGuest());
globalGuest(),
createPermission(NEW.uuid, 'INSERT', 'hs_office_bankaccount'));
return NEW;
end; $$;
@ -128,23 +129,23 @@ begin
raise exception '[403] insert into hs_office_bankaccount not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_bankaccount', $idName$
concat(iban, ':', holder)
iban
$idName$);
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_bankaccount',
$orderBy$
concat(iban, ':', holder)
iban
$orderBy$,
$updates$
holder = new.holder,
@ -153,4 +154,3 @@ call generateRbacRestrictedView('hs_office_bankaccount',
$updates$);
--//

View File

@ -102,23 +102,21 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTestWithC
final var roles = rawRoleRepo.findAll();
assertThat(distinctRoleNamesOf(roles)).containsExactlyInAnyOrder(Array.from(
initialRoleNames,
"hs_office_bankaccount#sometempaccC.owner",
"hs_office_bankaccount#sometempaccC.admin",
"hs_office_bankaccount#sometempaccC.tenant",
"hs_office_bankaccount#sometempaccC.guest"
"hs_office_bankaccount#DE25500105176934832579.owner",
"hs_office_bankaccount#DE25500105176934832579.admin",
"hs_office_bankaccount#DE25500105176934832579.referrer"
));
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromFormatted(
initialGrantNames,
"{ grant perm DELETE on hs_office_bankaccount#sometempaccC to role hs_office_bankaccount#sometempaccC.owner by system and assume }",
"{ grant role hs_office_bankaccount#sometempaccC.owner to role global#global.admin by system and assume }",
"{ grant role hs_office_bankaccount#sometempaccC.owner to user selfregistered-user-drew@hostsharing.org by global#global.admin and assume }",
"{ grant perm DELETE on hs_office_bankaccount#DE25500105176934832579 to role hs_office_bankaccount#DE25500105176934832579.owner by system and assume }",
"{ grant role hs_office_bankaccount#DE25500105176934832579.owner to role global#global.admin by system and assume }",
"{ grant role hs_office_bankaccount#DE25500105176934832579.owner to user selfregistered-user-drew@hostsharing.org by hs_office_bankaccount#DE25500105176934832579.owner and assume }",
"{ grant role hs_office_bankaccount#sometempaccC.admin to role hs_office_bankaccount#sometempaccC.owner by system and assume }",
"{ grant role hs_office_bankaccount#DE25500105176934832579.admin to role hs_office_bankaccount#DE25500105176934832579.owner by system and assume }",
"{ grant perm UPDATE on hs_office_bankaccount#DE25500105176934832579 to role hs_office_bankaccount#DE25500105176934832579.admin by system and assume }",
"{ grant role hs_office_bankaccount#sometempaccC.tenant to role hs_office_bankaccount#sometempaccC.admin by system and assume }",
"{ grant perm SELECT on hs_office_bankaccount#sometempaccC to role hs_office_bankaccount#sometempaccC.guest by system and assume }",
"{ grant role hs_office_bankaccount#sometempaccC.guest to role hs_office_bankaccount#sometempaccC.tenant by system and assume }",
"{ grant perm SELECT on hs_office_bankaccount#DE25500105176934832579 to role hs_office_bankaccount#DE25500105176934832579.referrer by system and assume }",
"{ grant role hs_office_bankaccount#DE25500105176934832579.referrer to role hs_office_bankaccount#DE25500105176934832579.admin by system and assume }",
null
));
}
@ -241,10 +239,6 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTestWithC
final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll());
final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll());
final var givenBankAccount = givenSomeTemporaryBankAccount("selfregistered-user-drew@hostsharing.org");
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll()).size()).as("unexpected number of roles created")
.isEqualTo(initialRoleNames.size() + 4);
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()).size()).as("unexpected number of grants created")
.isEqualTo(initialGrantNames.size() + 7);
// when
final var result = jpaAttempt.transacted(() -> {

View File

@ -107,12 +107,11 @@ class HsOfficeContactRepositoryIntegrationTest extends ContextBasedTestWithClean
"hs_office_contact#anothernewcontact.admin",
"hs_office_contact#anothernewcontact.referrer"
));
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.from(
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromFormatted(
initialGrantNames,
"{ grant perm * on hs_office_contact#anothernewcontact to role hs_office_contact#anothernewcontact.owner by system and assume }",
"{ grant role hs_office_contact#anothernewcontact.owner to role global#global.admin by system and assume }",
"{ grant perm UPDATE on hs_office_contact#anothernewcontact to role hs_office_contact#anothernewcontact.admin by system and assume }",
"{ grant role hs_office_contact#anothernewcontact.tenant to role hs_office_contact#anothernewcontact.admin by system and assume }",
"{ grant role hs_office_contact#anothernewcontact.owner to user selfregistered-user-drew@hostsharing.org by system and assume }",
"{ grant perm DELETE on hs_office_contact#anothernewcontact to role hs_office_contact#anothernewcontact.owner by system and assume }",
"{ grant role hs_office_contact#anothernewcontact.admin to role hs_office_contact#anothernewcontact.owner by system and assume }",