improved RBAC generators #26

Merged
hsh-michaelhoennig merged 17 commits from improved-rbac-generator into master 2024-03-26 11:25:18 +01:00
20 changed files with 94 additions and 84 deletions
Showing only changes of commit 260de22fd6 - Show all commits

View File

@ -161,23 +161,28 @@ public class InsertTriggerGenerator {
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}, Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable},
where the check is performed by an indirect role. where the check is performed by an indirect role.
An indirect role is a role FIXME. An indirect role is a role which depends on an object uuid which is not a direct foreign key
of the source entity, but needs to be fetched via joined tables.
*/ */
create or replace function ${rawSubTable}_insert_permission_check_tf() create or replace function ${rawSubTable}_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare declare
superRoleObjectUuid uuid; superRoleObjectUuid uuid;
begin
begin
""", """,
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
plPgSql.chopEmptyLines();
plPgSql.indented(2, () -> { plPgSql.indented(2, () -> {
plPgSql.writeLn( plPgSql.writeLn(
"superRoleObjectUuid := (" + g.getSuperRoleDef().getEntityAlias().fetchSql().sql + ");", "superRoleObjectUuid := (" + g.getSuperRoleDef().getEntityAlias().fetchSql().sql + ");\n" +
"assert superRoleObjectUuid is not null, 'superRoleObjectUuid must not be null';",
with("columns", g.getSuperRoleDef().getEntityAlias().aliasName() + ".uuid"), with("columns", g.getSuperRoleDef().getEntityAlias().aliasName() + ".uuid"),
with("ref", NEW.name())); with("ref", NEW.name()));
}); });
plPgSql.writeLn();
plPgSql.writeLn(""" plPgSql.writeLn("""
if ( not hasInsertPermission(superRoleObjectUuid, 'INSERT', '${rawSubTable}') ) then if ( not hasInsertPermission(superRoleObjectUuid, 'INSERT', '${rawSubTable}') ) then
raise exception raise exception

View File

@ -26,18 +26,20 @@ public class RbacIdentityViewGenerator {
plPgSql.writeLn( plPgSql.writeLn(
switch (rbacDef.getIdentityViewSqlQuery().part) { switch (rbacDef.getIdentityViewSqlQuery().part) {
case SQL_PROJECTION -> """ case SQL_PROJECTION -> """
call generateRbacIdentityViewFromProjection('${rawTableName}', $idName$ call generateRbacIdentityViewFromProjection('${rawTableName}',
${identityViewSqlPart} $idName$
${identityViewSqlPart}
$idName$); $idName$);
"""; """;
case SQL_QUERY -> """ case SQL_QUERY -> """
call generateRbacIdentityViewFromQuery('${rawTableName}', $idName$ call generateRbacIdentityViewFromQuery('${rawTableName}',
${identityViewSqlPart} $idName$
${identityViewSqlPart}
$idName$); $idName$);
"""; """;
default -> throw new IllegalStateException("illegal SQL part given"); default -> throw new IllegalStateException("illegal SQL part given");
}, },
with("identityViewSqlPart", rbacDef.getIdentityViewSqlQuery().sql), with("identityViewSqlPart", StringWriter.indented(2, rbacDef.getIdentityViewSqlQuery().sql)),
with("rawTableName", rawTableName)); with("rawTableName", rawTableName));
plPgSql.writeLn("--//"); plPgSql.writeLn("--//");

View File

@ -32,10 +32,10 @@ public class RbacRestrictedViewGenerator {
""", """,
with("liquibaseTagPrefix", liquibaseTagPrefix), with("liquibaseTagPrefix", liquibaseTagPrefix),
with("orderBy", indented(rbacDef.getOrderBySqlExpression().sql, 2)), with("orderBy", indented(2, rbacDef.getOrderBySqlExpression().sql)),
with("updates", indented(rbacDef.getUpdatableColumns().stream() with("updates", indented(2, rbacDef.getUpdatableColumns().stream()
.map(c -> c + " = new." + c) .map(c -> c + " = new." + c)
.collect(joining(",\n")), 2)), .collect(joining(",\n")))),
with("rawTableName", rawTableName)); with("rawTableName", rawTableName));
} }
} }

View File

@ -7,6 +7,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toSet; import static java.util.stream.Collectors.toSet;
import static net.hostsharing.hsadminng.rbac.rbacdef.PostgresTriggerReference.NEW; import static net.hostsharing.hsadminng.rbac.rbacdef.PostgresTriggerReference.NEW;
@ -233,6 +234,7 @@ class RolesGrantsAndPermissionsGenerator {
final PostgresTriggerReference old) { final PostgresTriggerReference old) {
plPgSql.writeLn( plPgSql.writeLn(
ea.fetchSql().sql + " INTO " + entityRefVar(old, ea) + ";", ea.fetchSql().sql + " INTO " + entityRefVar(old, ea) + ";",
with("columns", ea.aliasName() + ".*"),
with("ref", old.name())); with("ref", old.name()));
if (ea.nullable() == RbacView.Nullable.NOT_NULL) { if (ea.nullable() == RbacView.Nullable.NOT_NULL) {
plPgSql.writeLn( plPgSql.writeLn(
@ -244,14 +246,11 @@ class RolesGrantsAndPermissionsGenerator {
} }
} }
private boolean isUpdatable(final RbacView.Column c) {
return rbacDef.getUpdatableColumns().contains(c);
}
private void updateGrantsDependingOn(final StringWriter plPgSql, final String columnName) { private void updateGrantsDependingOn(final StringWriter plPgSql, final String columnName) {
rbacDef.getGrantDefs().stream() rbacDef.getGrantDefs().stream()
.filter(RbacView.RbacGrantDefinition::isToCreate) .filter(RbacView.RbacGrantDefinition::isToCreate)
.filter(g -> g.dependsOnColumn(columnName)) .filter(g -> g.dependsOnColumn(columnName))
.filter(g -> !isInsertPermissionGrant(g))
.forEach(g -> { .forEach(g -> {
plPgSql.ensureSingleEmptyLine(); plPgSql.ensureSingleEmptyLine();
plPgSql.writeLn(generateRevoke(g)); plPgSql.writeLn(generateRevoke(g));
@ -260,6 +259,11 @@ class RolesGrantsAndPermissionsGenerator {
}); });
} }
private static Boolean isInsertPermissionGrant(final RbacView.RbacGrantDefinition g) {
final var isInsertPermissionGrant = ofNullable(g.getPermDef()).map(RbacPermissionDefinition::getPermission).map(p -> p == INSERT).orElse(false);
return isInsertPermissionGrant;
}
private void generateGrants(final StringWriter plPgSql, final RbacView.RbacGrantDefinition.GrantType grantType) { private void generateGrants(final StringWriter plPgSql, final RbacView.RbacGrantDefinition.GrantType grantType) {
plPgSql.ensureSingleEmptyLine(); plPgSql.ensureSingleEmptyLine();
rbacGrants.stream() rbacGrants.stream()
@ -406,7 +410,7 @@ class RolesGrantsAndPermissionsGenerator {
if (!incomingGrants.isEmpty()) { if (!incomingGrants.isEmpty()) {
final var arrayElements = incomingGrants.stream() final var arrayElements = incomingGrants.stream()
.map(g -> toPlPgSqlReference(NEW, g.getSuperRoleDef(), g.isAssumed())) .map(g -> toPlPgSqlReference(NEW, g.getSuperRoleDef(), g.isAssumed()))
.toList(); .sorted().toList();
plPgSql.indented(() -> plPgSql.indented(() ->
plPgSql.writeLn("incomingSuperRoles => array[" + joinArrayElements(arrayElements, 1) + "],\n")); plPgSql.writeLn("incomingSuperRoles => array[" + joinArrayElements(arrayElements, 1) + "],\n"));
rbacGrants.removeAll(incomingGrants); rbacGrants.removeAll(incomingGrants);
@ -418,7 +422,7 @@ class RolesGrantsAndPermissionsGenerator {
if (!outgoingGrants.isEmpty()) { if (!outgoingGrants.isEmpty()) {
final var arrayElements = outgoingGrants.stream() final var arrayElements = outgoingGrants.stream()
.map(g -> toPlPgSqlReference(NEW, g.getSubRoleDef(), g.isAssumed())) .map(g -> toPlPgSqlReference(NEW, g.getSubRoleDef(), g.isAssumed()))
.toList(); .sorted().toList();
plPgSql.indented(() -> plPgSql.indented(() ->
plPgSql.writeLn("outgoingSubRoles => array[" + joinArrayElements(arrayElements, 1) + "],\n")); plPgSql.writeLn("outgoingSubRoles => array[" + joinArrayElements(arrayElements, 1) + "],\n"));
rbacGrants.removeAll(outgoingGrants); rbacGrants.removeAll(outgoingGrants);

View File

@ -82,7 +82,7 @@ public class StringWriter {
return string.toString(); return string.toString();
} }
public static String indented(final String text, final int indentLevel) { public static String indented(final int indentLevel, final String text) {
final var indentation = StringUtils.repeat(" ", indentLevel); final var indentation = StringUtils.repeat(" ", indentLevel);
final var indented = stream(text.split("\n")) final var indented = stream(text.split("\n"))
.map(line -> line.trim().isBlank() ? "" : indentation + line) .map(line -> line.trim().isBlank() ? "" : indentation + line)
@ -94,7 +94,7 @@ public class StringWriter {
if ( indentLevel == 0) { if ( indentLevel == 0) {
return text; return text;
} }
return indented(text, indentLevel); return indented(indentLevel, text);
} }
record VarDef(String name, String value){} record VarDef(String name, String value){}

View File

@ -71,10 +71,6 @@ public class RbacGrantsDiagramService {
private void traverseGrantsTo(final Set<RawRbacGrantEntity> graph, final UUID refUuid, final EnumSet<Include> includes) { private void traverseGrantsTo(final Set<RawRbacGrantEntity> graph, final UUID refUuid, final EnumSet<Include> includes) {
final var grants = rawGrantRepo.findByAscendingUuid(refUuid); final var grants = rawGrantRepo.findByAscendingUuid(refUuid);
grants.forEach(g -> { grants.forEach(g -> {
if ( g.getDescendantIdName() == null ) {
// FIXME: what's that?
return;
}
if (!includes.contains(PERMISSIONS) && g.getDescendantIdName().startsWith("perm ")) { if (!includes.contains(PERMISSIONS) && g.getDescendantIdName().startsWith("perm ")) {
return; return;
} }

View File

@ -691,7 +691,7 @@ declare
superRoleId uuid; superRoleId uuid;
subRoleId uuid; subRoleId uuid;
begin begin
-- FIXME: maybe separate method grantRoleToRoleIfNotNull(...)? -- TODO: maybe separate method grantRoleToRoleIfNotNull(...) for NULLABLE references
if superRole.objectUuid is null or subRole.objectuuid is null then if superRole.objectUuid is null or subRole.objectuuid is null then
return; return;
end if; end if;

View File

@ -60,7 +60,7 @@ begin
if cardinality(userUuids) > 0 then if cardinality(userUuids) > 0 then
-- direct grants to users need a grantedByRole which can revoke the grant -- direct grants to users need a grantedByRole which can revoke the grant
if grantedByRole is null then if grantedByRole is null then
userGrantsByRoleUuid := roleUuid; -- FIXME: or do we want to require an explicit userGrantsByRoleUuid? userGrantsByRoleUuid := roleUuid; -- TODO: or do we want to require an explicit userGrantsByRoleUuid?
else else
userGrantsByRoleUuid := getRoleId(grantedByRole); userGrantsByRoleUuid := getRoleId(grantedByRole);
end if; end if;

View File

@ -143,8 +143,9 @@ create trigger test_customer_insert_permission_check_tg
--changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('test_customer', $idName$ call generateRbacIdentityViewFromProjection('test_customer',
prefix $idName$
prefix
$idName$); $idName$);
--// --//

View File

@ -110,8 +110,6 @@ begin
if NEW.customerUuid <> OLD.customerUuid then if NEW.customerUuid <> OLD.customerUuid then
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'INSERT'), testCustomerAdmin(oldCustomer));
call revokeRoleFromRole(testPackageOwner(OLD), testCustomerAdmin(oldCustomer)); call revokeRoleFromRole(testPackageOwner(OLD), testCustomerAdmin(oldCustomer));
call grantRoleToRole(testPackageOwner(NEW), testCustomerAdmin(newCustomer)); call grantRoleToRole(testPackageOwner(NEW), testCustomerAdmin(newCustomer));
@ -212,8 +210,9 @@ create trigger test_package_insert_permission_check_tg
--changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('test_package', $idName$ call generateRbacIdentityViewFromProjection('test_package',
name $idName$
name
$idName$); $idName$);
--// --//

View File

@ -106,8 +106,6 @@ begin
if NEW.packageUuid <> OLD.packageUuid then if NEW.packageUuid <> OLD.packageUuid then
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'INSERT'), testPackageAdmin(oldPackage));
call revokeRoleFromRole(testDomainOwner(OLD), testPackageAdmin(oldPackage)); call revokeRoleFromRole(testDomainOwner(OLD), testPackageAdmin(oldPackage));
call grantRoleToRole(testDomainOwner(NEW), testPackageAdmin(newPackage)); call grantRoleToRole(testDomainOwner(NEW), testPackageAdmin(newPackage));
@ -211,8 +209,9 @@ create trigger test_domain_insert_permission_check_tg
--changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('test_domain', $idName$ call generateRbacIdentityViewFromProjection('test_domain',
name $idName$
name
$idName$); $idName$);
--// --//

View File

@ -103,8 +103,9 @@ create trigger hs_office_contact_insert_permission_check_tg
--changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_contact', $idName$ call generateRbacIdentityViewFromProjection('hs_office_contact',
label $idName$
label
$idName$); $idName$);
--// --//

View File

@ -103,8 +103,9 @@ create trigger hs_office_person_insert_permission_check_tg
--changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_person', $idName$ call generateRbacIdentityViewFromProjection('hs_office_person',
concat(tradeName, familyName, givenName) $idName$
concat(tradeName, familyName, givenName)
$idName$); $idName$);
--// --//

View File

@ -54,15 +54,15 @@ begin
hsOfficeRelationAdmin(NEW), hsOfficeRelationAdmin(NEW),
permissions => array['UPDATE'], permissions => array['UPDATE'],
incomingSuperRoles => array[ incomingSuperRoles => array[
hsOfficeRelationOwner(NEW), hsOfficePersonAdmin(newAnchorPerson),
hsOfficePersonAdmin(newAnchorPerson)] hsOfficeRelationOwner(NEW)]
); );
perform createRoleWithGrants( perform createRoleWithGrants(
hsOfficeRelationAgent(NEW), hsOfficeRelationAgent(NEW),
incomingSuperRoles => array[ incomingSuperRoles => array[
hsOfficeRelationAdmin(NEW), hsOfficePersonAdmin(newHolderPerson),
hsOfficePersonAdmin(newHolderPerson)] hsOfficeRelationAdmin(NEW)]
); );
perform createRoleWithGrants( perform createRoleWithGrants(
@ -73,9 +73,9 @@ begin
hsOfficePersonAdmin(newHolderPerson), hsOfficePersonAdmin(newHolderPerson),
hsOfficeRelationAgent(NEW)], hsOfficeRelationAgent(NEW)],
outgoingSubRoles => array[ outgoingSubRoles => array[
hsOfficePersonReferrer(newHolderPerson),
hsOfficeContactReferrer(newContact), hsOfficeContactReferrer(newContact),
hsOfficePersonReferrer(newAnchorPerson)] hsOfficePersonReferrer(newAnchorPerson),
hsOfficePersonReferrer(newHolderPerson)]
); );
call leaveTriggerForObjectUuid(NEW.uuid); call leaveTriggerForObjectUuid(NEW.uuid);
@ -169,11 +169,11 @@ create trigger hs_office_relation_insert_permission_check_tg
--changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_relation', $idName$ call generateRbacIdentityViewFromProjection('hs_office_relation',
(select idName from hs_office_person_iv p where p.uuid = anchorUuid) $idName$
|| '-with-' || target.type || '-' (select idName from hs_office_person_iv p where p.uuid = anchorUuid)
|| (select idName from hs_office_person_iv p where p.uuid = holderUuid) || '-with-' || target.type || '-'
|| (select idName from hs_office_person_iv p where p.uuid = holderUuid)
$idName$); $idName$);
--// --//

View File

@ -220,12 +220,12 @@ create trigger hs_office_partner_insert_permission_check_tg
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_partner', $idName$ call generateRbacIdentityViewFromQuery('hs_office_partner',
SELECT partner.partnerNumber $idName$
|| ':' || (SELECT idName FROM hs_office_person_iv p WHERE p.uuid = partner.personUuid) SELECT partner.partnerNumber
|| '-' || (SELECT idName FROM hs_office_contact_iv c WHERE c.uuid = partner.contactUuid) || ':' || (SELECT idName FROM hs_office_person_iv p WHERE p.uuid = partner.personUuid)
FROM hs_office_partner AS partner || '-' || (SELECT idName FROM hs_office_contact_iv c WHERE c.uuid = partner.contactUuid)
FROM hs_office_partner AS partner
$idName$); $idName$);
--// --//

View File

@ -35,7 +35,7 @@ declare
begin begin
call enterTriggerForObjectUuid(NEW.uuid); call enterTriggerForObjectUuid(NEW.uuid);
SELECT ${columns} SELECT partnerRel.*
FROM hs_office_relation AS partnerRel FROM hs_office_relation AS partnerRel
JOIN hs_office_partner AS partner JOIN hs_office_partner AS partner
ON partner.detailsUuid = NEW.uuid ON partner.detailsUuid = NEW.uuid
@ -133,12 +133,12 @@ create trigger hs_office_partner_details_insert_permission_check_tg
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_partner_details', $idName$ call generateRbacIdentityViewFromQuery('hs_office_partner_details',
SELECT partner_iv.idName || '-details' $idName$
FROM hs_office_partner_details AS partnerDetails SELECT partner_iv.idName || '-details'
JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid FROM hs_office_partner_details AS partnerDetails
JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid
JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid
$idName$); $idName$);
--// --//

View File

@ -103,8 +103,9 @@ create trigger hs_office_bankaccount_insert_permission_check_tg
--changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_bankaccount', $idName$ call generateRbacIdentityViewFromProjection('hs_office_bankaccount',
iban || ':' || holder $idName$
iban || ':' || holder
$idName$); $idName$);
--// --//

View File

@ -57,17 +57,17 @@ begin
hsOfficeSepaMandateAgent(NEW), hsOfficeSepaMandateAgent(NEW),
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)], incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)],
outgoingSubRoles => array[ outgoingSubRoles => array[
hsOfficeRelationAgent(newDebitorRel), hsOfficeBankAccountReferrer(newBankAccount),
hsOfficeBankAccountReferrer(newBankAccount)] hsOfficeRelationAgent(newDebitorRel)]
); );
perform createRoleWithGrants( perform createRoleWithGrants(
hsOfficeSepaMandateReferrer(NEW), hsOfficeSepaMandateReferrer(NEW),
permissions => array['SELECT'], permissions => array['SELECT'],
incomingSuperRoles => array[ incomingSuperRoles => array[
hsOfficeSepaMandateAgent(NEW), hsOfficeBankAccountAdmin(newBankAccount),
hsOfficeRelationAgent(newDebitorRel), hsOfficeRelationAgent(newDebitorRel),
hsOfficeBankAccountAdmin(newBankAccount)], hsOfficeSepaMandateAgent(NEW)],
outgoingSubRoles => array[hsOfficeRelationTenant(newDebitorRel)] outgoingSubRoles => array[hsOfficeRelationTenant(newDebitorRel)]
); );
@ -121,8 +121,9 @@ create trigger hs_office_sepamandate_insert_permission_check_tg
--changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_sepamandate', $idName$ call generateRbacIdentityViewFromProjection('hs_office_sepamandate',
concat(tradeName, familyName, givenName) $idName$
concat(tradeName, familyName, givenName)
$idName$); $idName$);
--// --//

View File

@ -185,18 +185,18 @@ create trigger hs_office_debitor_insert_permission_check_tg
--changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_debitor', $idName$ call generateRbacIdentityViewFromQuery('hs_office_debitor',
SELECT debitor.uuid, $idName$
'D-' || (SELECT partner.partnerNumber SELECT debitor.uuid,
FROM hs_office_partner partner 'D-' || (SELECT partner.partnerNumber
JOIN hs_office_relation partnerRel FROM hs_office_partner partner
ON partnerRel.uuid = partner.partnerRelUUid AND partnerRel.type = 'PARTNER' JOIN hs_office_relation partnerRel
JOIN hs_office_relation debitorRel ON partnerRel.uuid = partner.partnerRelUUid AND partnerRel.type = 'PARTNER'
ON debitorRel.anchorUuid = partnerRel.holderUuid AND partnerRel.type = 'DEBITOR' JOIN hs_office_relation debitorRel
WHERE debitorRel.uuid = debitor.debitorRelUuid) ON debitorRel.anchorUuid = partnerRel.holderUuid AND partnerRel.type = 'DEBITOR'
|| to_char(debitorNumberSuffix, 'fm00') WHERE debitorRel.uuid = debitor.debitorRelUuid)
from hs_office_debitor as debitor || to_char(debitorNumberSuffix, 'fm00')
from hs_office_debitor as debitor
$idName$); $idName$);
--// --//

View File

@ -462,7 +462,7 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
.header("current-user", "superuser-alex@hostsharing.net") .header("current-user", "superuser-alex@hostsharing.net")
.header("assumed-roles", "hs_office_partner#FirstGmbH-firstcontact.agent") .header("assumed-roles", "hs_office_partner#10001:FirstGmbH-firstcontact.admin")
.port(port) .port(port)
.when() .when()
.delete("http://localhost/api/hs/office/memberships/" + givenMembership.getUuid()) .delete("http://localhost/api/hs/office/memberships/" + givenMembership.getUuid())