fix indrirect permission by indirect foreign key
This commit is contained in:
parent
78ecf98913
commit
e6ef5b59c7
@ -21,6 +21,7 @@ import java.util.UUID;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NULLABLE;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
|
||||
@ -165,8 +166,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
||||
FROM hs_office_bankaccount AS b
|
||||
WHERE b.uuid = ${REF}.refundBankAccountUuid
|
||||
"""),
|
||||
NULLABLE
|
||||
)
|
||||
NULLABLE)
|
||||
.toRole("refundBankAccount", ADMIN).grantRole("debitorRel", AGENT)
|
||||
.toRole("debitorRel", AGENT).grantRole("refundBankAccount", REFERRER)
|
||||
|
||||
@ -179,8 +179,8 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
||||
ON debitorRel.type = 'DEBITOR' AND debitorRel.anchorUuid = partnerRel.holderUuid
|
||||
WHERE partnerRel.type = 'PARTNER'
|
||||
AND ${REF}.debitorRelUuid = debitorRel.uuid
|
||||
""")
|
||||
)
|
||||
"""),
|
||||
NOT_NULL)
|
||||
.toRole("partnerRel", ADMIN).grantRole("debitorRel", ADMIN)
|
||||
.toRole("partnerRel", AGENT).grantRole("debitorRel", AGENT)
|
||||
.toRole("debitorRel", AGENT).grantRole("partnerRel", TENANT)
|
||||
|
@ -20,6 +20,7 @@ import java.util.UUID;
|
||||
|
||||
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
@ -135,7 +136,8 @@ public class HsOfficeMembershipEntity implements HasUuid, Stringifyable {
|
||||
FROM hs_office_partner AS p
|
||||
JOIN hs_office_relation AS r ON r.uuid = p.partnerRelUuid
|
||||
WHERE p.uuid = ${REF}.partnerUuid
|
||||
"""))
|
||||
"""),
|
||||
NOT_NULL)
|
||||
.toRole("partnerRel", ADMIN).grantPermission(INSERT)
|
||||
|
||||
.createRole(OWNER, (with) -> {
|
||||
|
@ -16,6 +16,7 @@ import java.util.UUID;
|
||||
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.GLOBAL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
|
||||
@ -90,16 +91,16 @@ public class HsOfficeRelationEntity implements HasUuid, Stringifyable {
|
||||
.withUpdatableColumns("contactUuid")
|
||||
.importEntityAlias("anchorPerson", HsOfficePersonEntity.class,
|
||||
dependsOnColumn("anchorUuid"),
|
||||
fetchedBySql("select * from hs_office_person as p where p.uuid = ${REF}.anchorUuid")
|
||||
)
|
||||
fetchedBySql("select * from hs_office_person as p where p.uuid = ${REF}.anchorUuid"),
|
||||
NOT_NULL)
|
||||
.importEntityAlias("holderPerson", HsOfficePersonEntity.class,
|
||||
dependsOnColumn("holderUuid"),
|
||||
fetchedBySql("select * from hs_office_person as p where p.uuid = ${REF}.holderUuid")
|
||||
)
|
||||
fetchedBySql("select * from hs_office_person as p where p.uuid = ${REF}.holderUuid"),
|
||||
NOT_NULL)
|
||||
.importEntityAlias("contact", HsOfficeContactEntity.class,
|
||||
dependsOnColumn("contactUuid"),
|
||||
fetchedBySql("select * from hs_office_contact as c where c.uuid = ${REF}.contactUuid")
|
||||
)
|
||||
fetchedBySql("select * from hs_office_contact as c where c.uuid = ${REF}.contactUuid"),
|
||||
NOT_NULL)
|
||||
.createRole(OWNER, (with) -> {
|
||||
with.owningUser(CREATOR);
|
||||
with.incomingSuperRole(GLOBAL, ADMIN);
|
||||
|
@ -21,6 +21,7 @@ import java.util.UUID;
|
||||
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.GLOBAL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
|
||||
@ -110,12 +111,12 @@ public class HsOfficeSepaMandateEntity implements Stringifyable, HasUuid {
|
||||
FROM hs_office_relation debitorRel
|
||||
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
||||
WHERE debitor.uuid = ${REF}.debitorUuid
|
||||
""")
|
||||
)
|
||||
"""),
|
||||
NOT_NULL)
|
||||
.importEntityAlias("bankAccount", HsOfficeBankAccountEntity.class,
|
||||
dependsOnColumn("bankAccountUuid"),
|
||||
autoFetched()
|
||||
)
|
||||
autoFetched(),
|
||||
NOT_NULL)
|
||||
|
||||
.createRole(OWNER, (with) -> {
|
||||
with.owningUser(CREATOR);
|
||||
|
@ -114,7 +114,16 @@ public class InsertTriggerGenerator {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
generateInsertPermissionTriggerAllowByRoleOfDirectForeignKey(plPgSql, g);
|
||||
final var superRoleEntityAlias = g.getSuperRoleDef().getEntityAlias();
|
||||
|
||||
// TODO: Maybe this should depend on the indirection degree of the fetchSql?
|
||||
// Maybe we need a separate fetchedBy method for all the simple, direct cases?
|
||||
if (superRoleEntityAlias.fetchSql().sql.contains("JOIN ")) {
|
||||
generateInsertPermissionTriggerAllowByRoleOfIndirectForeignKey(plPgSql, g);
|
||||
} else {
|
||||
generateInsertPermissionTriggerAllowByRoleOfDirectForeignKey(plPgSql, g);
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
() -> {
|
||||
@ -149,6 +158,50 @@ public class InsertTriggerGenerator {
|
||||
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName()));
|
||||
}
|
||||
|
||||
private void generateInsertPermissionTriggerAllowByRoleOfIndirectForeignKey(
|
||||
final StringWriter plPgSql,
|
||||
final RbacView.RbacGrantDefinition g) {
|
||||
plPgSql.writeLn("""
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable},
|
||||
where the check is performed by an indirect role.
|
||||
|
||||
An indirect role is a role FIXME.
|
||||
*/
|
||||
create or replace function ${rawSubTable}_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
if ( not hasInsertPermission(
|
||||
( SELECT ${varName}.uuid FROM
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||
with("varName", g.getSuperRoleDef().getEntityAlias().aliasName()));
|
||||
plPgSql.indented(3, () -> {
|
||||
plPgSql.writeLn(
|
||||
"(" + g.getSuperRoleDef().getEntityAlias().fetchSql().sql + ") AS ${varName}",
|
||||
with("varName", g.getSuperRoleDef().getEntityAlias().aliasName()),
|
||||
with("ref", NEW.name()));
|
||||
});
|
||||
plPgSql.writeLn("""
|
||||
|
||||
), 'INSERT', '${rawSubTable}') ) then
|
||||
raise exception
|
||||
'[403] insert into ${rawSubTable} not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end if;
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger ${rawSubTable}_insert_permission_check_tg
|
||||
before insert on ${rawSubTable}
|
||||
for each row
|
||||
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||
}
|
||||
|
||||
private void generateInsertPermissionTriggerAllowOnlyGlobalAdmin(final StringWriter plPgSql) {
|
||||
plPgSql.writeLn("""
|
||||
/**
|
||||
|
@ -66,6 +66,21 @@ public class RbacView {
|
||||
private EntityAlias rootEntityAliasProxy;
|
||||
private RbacRoleDefinition previousRoleDef;
|
||||
|
||||
/** Crates an RBAC definition template for the given entity class and defining the given alias.
|
||||
*
|
||||
* @param alias
|
||||
* an alias name for this entity/table, which can be used in further grants
|
||||
*
|
||||
* @param entityClass
|
||||
* the Java class for which this RBAC definition is to be defined
|
||||
* (the class to which the calling method belongs)
|
||||
*
|
||||
* @return
|
||||
* the newly created RBAC definition template
|
||||
*
|
||||
* @param <E>
|
||||
* a JPA entity class extending RbacObject
|
||||
*/
|
||||
public static <E extends RbacObject> RbacView rbacViewFor(final String alias, final Class<E> entityClass) {
|
||||
return new RbacView(alias, entityClass);
|
||||
}
|
||||
@ -77,22 +92,71 @@ public class RbacView {
|
||||
entityAliases.put("global", new EntityAlias("global"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies, which columns of the restricted view are updatable at all.
|
||||
*
|
||||
* @param columnNames
|
||||
* A list of the updatable columns.
|
||||
*
|
||||
* @return
|
||||
* the `this` instance itself to allow chained calls.
|
||||
*/
|
||||
public RbacView withUpdatableColumns(final String... columnNames) {
|
||||
Collections.addAll(updatableColumns, columnNames);
|
||||
verifyVersionColumnExists();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Specifies the SQL query which creates the identity view for this entity.
|
||||
*
|
||||
* <p>An identity view is a view which maps an objectUuid to an idName.
|
||||
* The idName should be a human-readable representation of the row, but as short as possible.
|
||||
* The idName must only consist of letters (A-Z, a-z), digits (0-9), dash (-), dot (.) and unserscore '_'.
|
||||
* It's used to create the object-specific-role-names like test_customer#abc.admin - here 'abc' is the idName.
|
||||
* The idName not necessarily unique in a table, but it should be avoided.
|
||||
* </p>
|
||||
*
|
||||
* @param sqlExpression
|
||||
* Either specify an SQL projection (the part between SELECT and FROM), e.g. `SQL.projection("columnName")
|
||||
* or the whole SELECT query returning the uuid and idName columns,
|
||||
* e.g. `SQL.query("SELECT ... AS uuid, ... AS idName FROM ... JOIN ...").
|
||||
* Only add really important columns, just enough to create a short human-readable representation.
|
||||
*
|
||||
* @return
|
||||
* the `this` instance itself to allow chained calls.
|
||||
*/
|
||||
public RbacView withIdentityView(final SQL sqlExpression) {
|
||||
this.identityViewSqlQuery = sqlExpression;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a ORDER BY clause for the generated restricted view.
|
||||
*
|
||||
* <p>A restricted view is generated, no matter if the order was specified or not.</p>
|
||||
*
|
||||
* @param orderBySqlExpression
|
||||
* That's the part behind `ORDER BY`, e.g. `SQL.expression("prefix").
|
||||
*
|
||||
* @return
|
||||
* the `this` instance itself to allow chained calls.
|
||||
*/
|
||||
public RbacView withRestrictedViewOrderBy(final SQL orderBySqlExpression) {
|
||||
this.orderBySqlExpression = orderBySqlExpression;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that the given role (OWNER, ADMIN, ...) is to be created for new/updated roles in this table.
|
||||
*
|
||||
* @param role
|
||||
* OWNER, ADMIN, AGENT etc.
|
||||
* @param with
|
||||
* a lambda which receives the created role to create grants and permissions to and from the newly created role,
|
||||
* e.g. the owning user, incoming superroles, outgoing subroles
|
||||
* @return
|
||||
* the `this` instance itself to allow chained calls.
|
||||
*/
|
||||
public RbacView createRole(final Role role, final Consumer<RbacRoleDefinition> with) {
|
||||
final RbacRoleDefinition newRoleDef = findRbacRole(rootEntityAlias, role).toCreate();
|
||||
with.accept(newRoleDef);
|
||||
@ -100,6 +164,15 @@ public class RbacView {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that the given role (OWNER, ADMIN, ...) is to be created for new/updated roles in this table,
|
||||
* which is becomes sub-role of the previously created role.
|
||||
*
|
||||
* @param role
|
||||
* OWNER, ADMIN, AGENT etc.
|
||||
* @return
|
||||
* the `this` instance itself to allow chained calls.
|
||||
*/
|
||||
public RbacView createSubRole(final Role role) {
|
||||
final RbacRoleDefinition newRoleDef = findRbacRole(rootEntityAlias, role).toCreate();
|
||||
findOrCreateGrantDef(newRoleDef, previousRoleDef).toCreate();
|
||||
@ -107,6 +180,19 @@ public class RbacView {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies that the given role (OWNER, ADMIN, ...) is to be created for new/updated roles in this table,
|
||||
* which is becomes sub-role of the previously created role.
|
||||
*
|
||||
* @param role
|
||||
* OWNER, ADMIN, AGENT etc.
|
||||
* @param with
|
||||
* a lambda which receives the created role to create grants and permissions to and from the newly created role,
|
||||
* e.g. the owning user, incoming superroles, outgoing subroles
|
||||
* @return
|
||||
* the `this` instance itself to allow chained calls.
|
||||
*/
|
||||
public RbacView createSubRole(final Role role, final Consumer<RbacRoleDefinition> with) {
|
||||
final RbacRoleDefinition newRoleDef = findRbacRole(rootEntityAlias, role).toCreate();
|
||||
findOrCreateGrantDef(newRoleDef, previousRoleDef).toCreate();
|
||||
@ -115,10 +201,38 @@ public class RbacView {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that the given permission is to be created for each new row in the target table.
|
||||
*
|
||||
* <p>Grants to permissions created by this method have to be specified separately,
|
||||
* often it's easier to read to use createRole/createSubRole and use with.permission(...).</p>
|
||||
*
|
||||
* @param permission
|
||||
* e.g. INSERT, SELECT, UPDATE, DELETE
|
||||
*
|
||||
* @return
|
||||
* the newly created permission definition
|
||||
*/
|
||||
public RbacPermissionDefinition createPermission(final Permission permission) {
|
||||
return createPermission(rootEntityAlias, permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that the given permission is to be created for each new row in the target table,
|
||||
* but for another table, e.g. a table with details data with different access rights.
|
||||
*
|
||||
* <p>Grants to permissions created by this method have to be specified separately,
|
||||
* often it's easier to read to use createRole/createSubRole and use with.permission(...).</p>
|
||||
*
|
||||
* @param entityAliasName
|
||||
* A previously defined entity alias name.
|
||||
*
|
||||
* @param permission
|
||||
* e.g. INSERT, SELECT, UPDATE, DELETE
|
||||
*
|
||||
* @return
|
||||
* the newly created permission definition
|
||||
*/
|
||||
public RbacPermissionDefinition createPermission(final String entityAliasName, final Permission permission) {
|
||||
return createPermission(findEntityAlias(entityAliasName), permission);
|
||||
}
|
||||
@ -134,6 +248,32 @@ public class RbacView {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports the RBAC template from the given entity class and defines an alias name for it.
|
||||
* This method is especially for proxy-entities, if the root entity does not have its own
|
||||
* roles, a proxy-entity can be specified and its roles can be used instead.
|
||||
*
|
||||
* @param aliasName
|
||||
* An alias name for the entity class. The same entity class can be imported multiple times,
|
||||
* if multiple references to its table exist, then distinct alias names habe to be defined.
|
||||
*
|
||||
* @param entityClass
|
||||
* A JPA entity class extending RbacObject which also implements an `rbac` method returning
|
||||
* its RBAC specification.
|
||||
*
|
||||
* @param fetchSql
|
||||
* An SQL SELECT statement which fetches the referenced row. Use `${REF}` to speficiy the
|
||||
* newly created or updated row (will be replaced by NEW/OLD from the trigger method).
|
||||
*
|
||||
* @param dependsOnColum
|
||||
* The column, usually containing an uuid, on which this other table depends.
|
||||
*
|
||||
* @return
|
||||
* the newly created permission definition
|
||||
*
|
||||
* @param <EC>
|
||||
* a JPA entity class extending RbacObject
|
||||
*/
|
||||
public <EC extends RbacObject> RbacView importRootEntityAliasProxy(
|
||||
final String aliasName,
|
||||
final Class<? extends HasUuid> entityClass,
|
||||
@ -146,6 +286,18 @@ public class RbacView {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports the RBAC template from the given entity class and defines an alias name for it.
|
||||
* This method is especially to declare sub-entities, e.g. details to a main object.
|
||||
*
|
||||
* @see {@link}
|
||||
*
|
||||
* @return
|
||||
* the newly created permission definition
|
||||
*
|
||||
* @param <EC>
|
||||
* a JPA entity class extending RbacObject
|
||||
*/
|
||||
public RbacView importSubEntityAlias(
|
||||
final String aliasName, final Class<? extends HasUuid> entityClass,
|
||||
final SQL fetchSql, final Column dependsOnColum) {
|
||||
@ -153,6 +305,33 @@ public class RbacView {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports the RBAC template from the given entity class and defines an anlias name for it.
|
||||
*
|
||||
* @param aliasName
|
||||
* An alias name for the entity class. The same entity class can be imported multiple times,
|
||||
* if multiple references to its table exist, then distinct alias names habe to be defined.
|
||||
*
|
||||
* @param entityClass
|
||||
* A JPA entity class extending RbacObject which also implements an `rbac` method returning
|
||||
* its RBAC specification.
|
||||
*
|
||||
* @param fetchSql
|
||||
* An SQL SELECT statement which fetches the referenced row. Use `${REF}` to speficiy the
|
||||
* newly created or updated row (will be replaced by NEW/OLD from the trigger method).
|
||||
*
|
||||
* @param dependsOnColum
|
||||
* The column, usually containing an uuid, on which this other table depends.
|
||||
*
|
||||
* @param nullable
|
||||
* Specifies whether the dependsOnColum is nullable or not.
|
||||
*
|
||||
* @return
|
||||
* the newly created permission definition
|
||||
*
|
||||
* @param <EC>
|
||||
* a JPA entity class extending RbacObject
|
||||
*/
|
||||
public RbacView importEntityAlias(
|
||||
final String aliasName, final Class<? extends HasUuid> entityClass,
|
||||
final Column dependsOnColum, final SQL fetchSql, final Nullable nullable) {
|
||||
@ -160,13 +339,7 @@ public class RbacView {
|
||||
return this;
|
||||
}
|
||||
|
||||
public RbacView importEntityAlias(
|
||||
final String aliasName, final Class<? extends HasUuid> entityClass,
|
||||
final Column dependsOnColum, final SQL fetchSql) {
|
||||
importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, false, NOT_NULL);
|
||||
return this;
|
||||
}
|
||||
|
||||
// TODO: remove once it's not used in HsOffice...Entity anymore
|
||||
public RbacView importEntityAlias(
|
||||
final String aliasName, final Class<? extends HasUuid> entityClass,
|
||||
final Column dependsOnColum) {
|
||||
@ -232,6 +405,16 @@ public class RbacView {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts declaring a grant to a given role.
|
||||
*
|
||||
* @param entityAlias
|
||||
* A previously speciried entity alias name.
|
||||
* @param role
|
||||
* OWNER, ADMIN, AGENT, ...
|
||||
* @return
|
||||
* a grant builder
|
||||
*/
|
||||
public RbacGrantBuilder toRole(final String entityAlias, final Role role) {
|
||||
return new RbacGrantBuilder(entityAlias, role);
|
||||
}
|
||||
@ -430,6 +613,16 @@ public class RbacView {
|
||||
permDefs.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants the permission under definition to the given role.
|
||||
*
|
||||
* @param entityAlias
|
||||
* A previously declared entity alias name.
|
||||
* @param role
|
||||
* OWNER, ADMIN, ...
|
||||
* @return
|
||||
* The RbacView specification to which this permission definition belongs.
|
||||
*/
|
||||
public RbacView grantedTo(final String entityAlias, final Role role) {
|
||||
findOrCreateGrantDef(this, findRbacRole(entityAlias, role)).toCreate();
|
||||
return RbacView.this;
|
||||
@ -460,19 +653,61 @@ public class RbacView {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies which user becomes the owner of newly created objects.
|
||||
* @param userRole
|
||||
* GLOBAL_ADMIN, CREATOR, ...
|
||||
* @return
|
||||
* The grant definition for further chained calls.
|
||||
*/
|
||||
public RbacGrantDefinition owningUser(final RbacUserReference.UserRole userRole) {
|
||||
return grantRoleToUser(this, findUserRef(userRole));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies which permission is to be created for newly created objects.
|
||||
* @param permission
|
||||
* INSERT, SELECT, ...
|
||||
* @return
|
||||
* The grant definition for further chained calls.
|
||||
*/
|
||||
public RbacGrantDefinition permission(final Permission permission) {
|
||||
return grantPermissionToRole(createPermission(entityAlias, permission), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies in incoming super role which gets granted the role under definition.
|
||||
*
|
||||
* <p>Incoming means an incoming grant arrow in our grant-diagrams.
|
||||
* Super-role means that it's the role to which another role is granted.
|
||||
* Both means actually the same, just in different aspects.</p>
|
||||
*
|
||||
* @param entityAlias
|
||||
* A previously declared entity alias name.
|
||||
* @param role
|
||||
* OWNER, ADMIN, ...
|
||||
* @return
|
||||
* The grant definition for further chained calls.
|
||||
*/
|
||||
public RbacGrantDefinition incomingSuperRole(final String entityAlias, final Role role) {
|
||||
final var incomingSuperRole = findRbacRole(entityAlias, role);
|
||||
return grantSubRoleToSuperRole(this, incomingSuperRole);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies in outgoing sub role which gets granted the role under definition.
|
||||
*
|
||||
* <p>Outgoing means an outgoing grant arrow in our grant-diagrams.
|
||||
* Sub-role means which is granted to another role.
|
||||
* Both means actually the same, just in different aspects.</p>
|
||||
*
|
||||
* @param entityAlias
|
||||
* A previously declared entity alias name.
|
||||
* @param role
|
||||
* OWNER, ADMIN, ...
|
||||
* @return
|
||||
* The grant definition for further chained calls.
|
||||
*/
|
||||
public RbacGrantDefinition outgoingSubRole(final String entityAlias, final Role role) {
|
||||
final var outgoingSubRole = findRbacRole(entityAlias, role);
|
||||
return grantSubRoleToSuperRole(outgoingSubRole, this);
|
||||
@ -802,6 +1037,26 @@ public class RbacView {
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateRbacView(final Class<? extends HasUuid> c) {
|
||||
final Method mainMethod = stream(c.getMethods()).filter(
|
||||
m -> isStatic(m.getModifiers()) && m.getName().equals("main")
|
||||
)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (mainMethod != null) {
|
||||
try {
|
||||
mainMethod.invoke(null, new Object[] { null });
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
System.err.println("WARNING: no main method in: " + c.getName() + " => no RBAC rules generated");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This main method generates the RbacViews (PostgreSQL+diagram) for all given entity classes.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Stream.of(
|
||||
TestCustomerEntity.class,
|
||||
@ -818,21 +1073,6 @@ public class RbacView {
|
||||
HsOfficeSepaMandateEntity.class,
|
||||
HsOfficeCoopSharesTransactionEntity.class,
|
||||
HsOfficeMembershipEntity.class
|
||||
).forEach(c -> {
|
||||
final Method mainMethod = stream(c.getMethods()).filter(
|
||||
m -> isStatic(m.getModifiers()) && m.getName().equals("main")
|
||||
)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (mainMethod != null) {
|
||||
try {
|
||||
mainMethod.invoke(null, new Object[] { null });
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
System.err.println("WARNING: no main method in: " + c.getName() + " => no RBAC rules generated");
|
||||
}
|
||||
});
|
||||
).forEach(RbacView::generateRbacView);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import lombok.SneakyThrows;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.*;
|
||||
@ -149,14 +148,13 @@ public class RbacViewMermaidFlowchartGenerator {
|
||||
"""
|
||||
### rbac %{entityAlias}
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at %{timestamp}.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%{flowchart}
|
||||
```
|
||||
"""
|
||||
.replace("%{entityAlias}", rbacDef.getRootEntityAlias().aliasName())
|
||||
.replace("%{timestamp}", LocalDateTime.now().toString())
|
||||
.replace("%{flowchart}", flowchart.toString()),
|
||||
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
|
||||
System.out.println("Markdown-File: " + path.toAbsolutePath());
|
||||
|
@ -5,7 +5,6 @@ import lombok.SneakyThrows;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.PostgresTriggerReference.NEW;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.StringWriter.with;
|
||||
@ -21,10 +20,9 @@ public class RbacViewPostgresGenerator {
|
||||
liqibaseTagPrefix = rbacDef.getRootEntityAlias().getRawTableName().replace("_", "-");
|
||||
plPgSql.writeLn("""
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by ${generator} at ${timestamp}.
|
||||
-- This code generated was by ${generator}, do not amend manually.
|
||||
""",
|
||||
with("generator", getClass().getSimpleName()),
|
||||
with("timestamp", LocalDateTime.now().toString()),
|
||||
with("ref", NEW.name()));
|
||||
|
||||
new RbacObjectGenerator(rbacDef, liqibaseTagPrefix).generateTo(plPgSql);
|
||||
|
@ -28,8 +28,8 @@ public class RawRbacGrantEntity implements Comparable {
|
||||
@Column(name = "grantedbyroleidname", updatable = false, insertable = false)
|
||||
private String grantedByRoleIdName;
|
||||
|
||||
@Column(name = "usergrantsbyroleuuid", updatable = false, insertable = false)
|
||||
private UUID userGrantsByRoleUuid;
|
||||
@Column(name = "grantedbyroleuuid", updatable = false, insertable = false)
|
||||
private UUID grantedByRoleUuid;
|
||||
|
||||
@Column(name = "ascendantidname", updatable = false, insertable = false)
|
||||
private String ascendantIdName;
|
||||
@ -50,7 +50,7 @@ public class RawRbacGrantEntity implements Comparable {
|
||||
// @formatter:off
|
||||
return "{ grant " + descendantIdName +
|
||||
" to " + ascendantIdName +
|
||||
" by " + ( userGrantsByRoleUuid == null
|
||||
" by " + ( grantedByRoleUuid == null
|
||||
? "system"
|
||||
: grantedByRoleIdName ) +
|
||||
( assumed ? " and assume" : "") +
|
||||
|
@ -22,8 +22,8 @@ public class RbacGrantEntity {
|
||||
@Column(name = "grantedbyroleidname", updatable = false, insertable = false)
|
||||
private String grantedByRoleIdName;
|
||||
|
||||
@Column(name = "usergrantsbyroleuuid", updatable = false, insertable = false)
|
||||
private UUID userGrantsByRoleUuid;
|
||||
@Column(name = "grantedbyroleuuid", updatable = false, insertable = false)
|
||||
private UUID grantedByRoleUuid;
|
||||
|
||||
@Column(name = "grantedroleidname", updatable = false, insertable = false)
|
||||
private String grantedRoleIdName;
|
||||
|
@ -14,6 +14,7 @@ import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
|
||||
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;
|
||||
@ -52,7 +53,8 @@ public class TestDomainEntity implements HasUuid {
|
||||
fetchedBySql("""
|
||||
SELECT * FROM test_package p
|
||||
WHERE p.uuid= ${ref}.packageUuid
|
||||
"""))
|
||||
"""),
|
||||
NOT_NULL)
|
||||
.toRole("package", ADMIN).grantPermission(INSERT)
|
||||
|
||||
.createRole(OWNER, (with) -> {
|
||||
|
@ -14,6 +14,7 @@ import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
|
||||
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.*;
|
||||
@ -53,7 +54,8 @@ public class TestPackageEntity implements HasUuid {
|
||||
fetchedBySql("""
|
||||
SELECT * FROM test_customer c
|
||||
WHERE c.uuid= ${ref}.customerUuid
|
||||
"""))
|
||||
"""),
|
||||
NOT_NULL)
|
||||
.toRole("customer", ADMIN).grantPermission(INSERT)
|
||||
|
||||
.createRole(OWNER, (with) -> {
|
||||
|
@ -160,6 +160,7 @@ create or replace function cleanIdentifier(rawIdentifier varchar)
|
||||
declare
|
||||
cleanIdentifier varchar;
|
||||
begin
|
||||
-- TODO: remove the ':' from the list of allowed characters as soon as it's not used anymore
|
||||
cleanIdentifier := regexp_replace(rawIdentifier, '[^A-Za-z0-9\-._:]+', '', 'g');
|
||||
return cleanIdentifier;
|
||||
end; $$;
|
||||
|
@ -300,7 +300,7 @@ create or replace function deleteRbacGrantsOfRbacRole()
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP = 'DELETE' then
|
||||
delete from RbacGrants g where old.uuid in (g.userGrantsByRoleUuid, g.ascendantuuid, g.descendantuuid);
|
||||
delete from RbacGrants g where old.uuid in (g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid);
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
|
||||
end if;
|
||||
@ -519,12 +519,12 @@ create table RbacGrants
|
||||
(
|
||||
uuid uuid primary key default uuid_generate_v4(),
|
||||
grantedByTriggerOf uuid references RbacObject (uuid) on delete cascade initially deferred ,
|
||||
userGrantsByRoleUuid uuid references RbacRole (uuid),
|
||||
grantedByRoleUuid uuid references RbacRole (uuid),
|
||||
ascendantUuid uuid references RbacReference (uuid),
|
||||
descendantUuid uuid references RbacReference (uuid),
|
||||
assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false)
|
||||
unique (ascendantUuid, descendantUuid),
|
||||
constraint rbacGrant_createdBy check ( userGrantsByRoleUuid is null or grantedByTriggerOf is null) );
|
||||
constraint rbacGrant_createdBy check ( grantedByRoleUuid is null or grantedByTriggerOf is null) );
|
||||
create index on RbacGrants (ascendantUuid);
|
||||
create index on RbacGrants (descendantUuid);
|
||||
|
||||
|
@ -20,52 +20,50 @@ begin
|
||||
return currentSubjectsUuids[1];
|
||||
end; $$;
|
||||
|
||||
create or replace procedure grantRoleToUserUnchecked(userGrantsByRoleUuid uuid, roleUuid uuid, userUuid uuid, doAssume boolean = true)
|
||||
create or replace procedure grantRoleToUserUnchecked(grantedByRoleUuid uuid, roleUuid uuid, userUuid uuid, doAssume boolean = true)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
perform assertReferenceType('grantingRoleUuid', userGrantsByRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('roleId (descendant)', roleUuid, 'RbacRole');
|
||||
perform assertReferenceType('userId (ascendant)', userUuid, 'RbacUser');
|
||||
|
||||
raise notice 'role % grants role % to user %, assumed=%', userGrantsByRoleUuid, roleUuid, userUuid, doAssume;
|
||||
|
||||
insert
|
||||
into RbacGrants (userGrantsByRoleUuid, ascendantUuid, descendantUuid, assumed)
|
||||
values (userGrantsByRoleUuid, userUuid, roleUuid, doAssume);
|
||||
into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
|
||||
values (grantedByRoleUuid, userUuid, roleUuid, doAssume);
|
||||
-- TODO.spec: What should happen on multiple grants? What if options (doAssume) are not the same?
|
||||
-- Most powerful or latest grant wins? What about managed?
|
||||
-- on conflict do nothing; -- allow granting multiple times
|
||||
end; $$;
|
||||
|
||||
create or replace procedure grantRoleToUser(userGrantsByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true)
|
||||
create or replace procedure grantRoleToUser(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
grantedByRoleIdName text;
|
||||
grantedRoleIdName text;
|
||||
begin
|
||||
perform assertReferenceType('grantingRoleUuid', userGrantsByRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('userUuid (ascendant)', userUuid, 'RbacUser');
|
||||
|
||||
assert userGrantsByRoleUuid is not null, 'userGrantsByRoleUuid must not be null';
|
||||
assert grantedByRoleUuid is not null, 'grantedByRoleUuid must not be null';
|
||||
assert grantedRoleUuid is not null, 'grantedRoleUuid must not be null';
|
||||
assert userUuid is not null, 'userUuid must not be null';
|
||||
|
||||
if NOT isGranted(currentSubjectsUuids(), userGrantsByRoleUuid) then
|
||||
select roleIdName from rbacRole_ev where uuid=userGrantsByRoleUuid into grantedByRoleIdName;
|
||||
if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
|
||||
select roleIdName from rbacRole_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
|
||||
raise exception '[403] Access to granted-by-role % (%) forbidden for % (%)',
|
||||
grantedByRoleIdName, userGrantsByRoleUuid, currentSubjects(), currentSubjectsUuids();
|
||||
grantedByRoleIdName, grantedByRoleUuid, currentSubjects(), currentSubjectsUuids();
|
||||
end if;
|
||||
if NOT isGranted(userGrantsByRoleUuid, grantedRoleUuid) then
|
||||
select roleIdName from rbacRole_ev where uuid=userGrantsByRoleUuid into grantedByRoleIdName;
|
||||
if NOT isGranted(grantedByRoleUuid, grantedRoleUuid) then
|
||||
select roleIdName from rbacRole_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
|
||||
select roleIdName from rbacRole_ev where uuid=grantedRoleUuid into grantedRoleIdName;
|
||||
raise exception '[403] Access to granted role % (%) forbidden for % (%)',
|
||||
grantedRoleIdName, grantedRoleUuid, grantedByRoleIdName, userGrantsByRoleUuid;
|
||||
grantedRoleIdName, grantedRoleUuid, grantedByRoleIdName, grantedByRoleUuid;
|
||||
end if;
|
||||
|
||||
insert
|
||||
into RbacGrants (userGrantsByRoleUuid, ascendantUuid, descendantUuid, assumed)
|
||||
values (userGrantsByRoleUuid, userUuid, grantedRoleUuid, doAssume);
|
||||
into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
|
||||
values (grantedByRoleUuid, userUuid, grantedRoleUuid, doAssume);
|
||||
-- TODO.spec: What should happen on mupltiple grants? What if options (doAssume) are not the same?
|
||||
-- Most powerful or latest grant wins? What about managed?
|
||||
-- on conflict do nothing; -- allow granting multiple times
|
||||
@ -77,40 +75,40 @@ end; $$;
|
||||
--changeset rbac-user-grant-REVOKE-ROLE-FROM-USER:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure checkRevokeRoleFromUserPreconditions(userGrantsByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid)
|
||||
create or replace procedure checkRevokeRoleFromUserPreconditions(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
perform assertReferenceType('userGrantsByRoleUuid', userGrantsByRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('grantedByRoleUuid', grantedByRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('userUuid (ascendant)', userUuid, 'RbacUser');
|
||||
|
||||
if NOT isGranted(currentSubjectsUuids(), userGrantsByRoleUuid) then
|
||||
raise exception '[403] Revoking role created by % is forbidden for %.', userGrantsByRoleUuid, currentSubjects();
|
||||
if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
|
||||
raise exception '[403] Revoking role created by % is forbidden for %.', grantedByRoleUuid, currentSubjects();
|
||||
end if;
|
||||
|
||||
if NOT isGranted(userGrantsByRoleUuid, grantedRoleUuid) then
|
||||
if NOT isGranted(grantedByRoleUuid, grantedRoleUuid) then
|
||||
raise exception '[403] Revoking role % is forbidden for %.', grantedRoleUuid, currentSubjects();
|
||||
end if;
|
||||
|
||||
--raise exception 'isGranted(%, %)', currentSubjectsUuids(), userGrantsByRoleUuid;
|
||||
if NOT isGranted(currentSubjectsUuids(), userGrantsByRoleUuid) then
|
||||
raise exception '[403] Revoking role granted by % is forbidden for %.', userGrantsByRoleUuid, currentSubjects();
|
||||
--raise exception 'isGranted(%, %)', currentSubjectsUuids(), grantedByRoleUuid;
|
||||
if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
|
||||
raise exception '[403] Revoking role granted by % is forbidden for %.', grantedByRoleUuid, currentSubjects();
|
||||
end if;
|
||||
|
||||
if NOT isGranted(userUuid, grantedRoleUuid) then
|
||||
raise exception '[404] No such grant found granted by % for user % to role %.', userGrantsByRoleUuid, userUuid, grantedRoleUuid;
|
||||
raise exception '[404] No such grant found granted by % for user % to role %.', grantedByRoleUuid, userUuid, grantedRoleUuid;
|
||||
end if;
|
||||
end; $$;
|
||||
|
||||
create or replace procedure revokeRoleFromUser(userGrantsByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid)
|
||||
create or replace procedure revokeRoleFromUser(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
call checkRevokeRoleFromUserPreconditions(userGrantsByRoleUuid, grantedRoleUuid, userUuid);
|
||||
call checkRevokeRoleFromUserPreconditions(grantedByRoleUuid, grantedRoleUuid, userUuid);
|
||||
|
||||
raise INFO 'delete from RbacGrants where ascendantUuid = % and descendantUuid = %', userUuid, grantedRoleUuid;
|
||||
delete from RbacGrants as g
|
||||
where g.ascendantUuid = userUuid and g.descendantUuid = grantedRoleUuid
|
||||
and g.userGrantsByRoleUuid = revokeRoleFromUser.userGrantsByRoleUuid;
|
||||
and g.grantedByRoleUuid = revokeRoleFromUser.grantedByRoleUuid;
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
@ -139,7 +139,6 @@ begin
|
||||
raise exception '[401] currentUserUuid cannot be determined, please call `defineContext(...)` first;"';
|
||||
end if;
|
||||
end if;
|
||||
raise notice 'currentUserUuid %', currentUserUuid;
|
||||
return currentUserUuid::uuid;
|
||||
end; $$;
|
||||
--//
|
||||
|
@ -60,14 +60,14 @@ create or replace view rbacgrants_ev as
|
||||
go.objectTable || '#' || findIdNameByObjectUuid(go.objectTable, go.uuid) || '.' || r.roletype as grantedByRoleIdName,
|
||||
x.ascendingIdName as ascendantIdName,
|
||||
x.descendingIdName as descendantIdName,
|
||||
x.userGrantsByRoleUuid,
|
||||
x.grantedByRoleUuid,
|
||||
x.ascendantUuid as ascendantUuid,
|
||||
x.descendantUuid as descendantUuid,
|
||||
x.assumed
|
||||
from (
|
||||
select g.uuid as grantUuid,
|
||||
g.grantedbytriggerof as grantedbytriggerof,
|
||||
g.userGrantsByRoleUuid, g.ascendantuuid, g.descendantuuid, g.assumed,
|
||||
g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed,
|
||||
|
||||
coalesce(
|
||||
'user ' || au.name,
|
||||
@ -91,7 +91,7 @@ create or replace view rbacgrants_ev as
|
||||
left outer join rbacpermission dp on dp.uuid = g.descendantUuid
|
||||
left outer join rbacobject as dpo on dpo.uuid = dp.objectUuid
|
||||
) as x
|
||||
left outer join rbacrole as r on r.uuid = userGrantsByRoleUuid
|
||||
left outer join rbacrole as r on r.uuid = grantedByRoleUuid
|
||||
left outer join rbacuser u on u.uuid = x.ascendantuuid
|
||||
left outer join rbacobject go on go.uuid = r.objectuuid
|
||||
|
||||
@ -112,10 +112,10 @@ create or replace view rbacgrants_rv as
|
||||
-- @formatter:off
|
||||
select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) || '.' || r.roletype as grantedByRoleIdName,
|
||||
g.objectTable || '#' || g.objectIdName || '.' || g.roletype as grantedRoleIdName, g.userName, g.assumed,
|
||||
g.userGrantsByRoleUuid, g.descendantUuid as grantedRoleUuid, g.ascendantUuid as userUuid,
|
||||
g.grantedByRoleUuid, g.descendantUuid as grantedRoleUuid, g.ascendantUuid as userUuid,
|
||||
g.objectTable, g.objectUuid, g.objectIdName, g.roleType as grantedRoleType
|
||||
from (
|
||||
select g.userGrantsByRoleUuid, g.ascendantuuid, g.descendantuuid, g.assumed,
|
||||
select g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed,
|
||||
u.name as userName, o.objecttable, r.objectuuid, r.roletype,
|
||||
findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
|
||||
from rbacgrants as g
|
||||
@ -124,7 +124,7 @@ select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) ||
|
||||
left outer join rbacuser u on u.uuid = g.ascendantuuid
|
||||
where isGranted(currentSubjectsUuids(), r.uuid)
|
||||
) as g
|
||||
join RbacRole as r on r.uuid = userGrantsByRoleUuid
|
||||
join RbacRole as r on r.uuid = grantedByRoleUuid
|
||||
join RbacObject as o on o.uuid = r.objectUuid
|
||||
order by grantedRoleIdName;
|
||||
-- @formatter:on
|
||||
@ -177,7 +177,7 @@ create or replace function deleteRbacGrant()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
call revokeRoleFromUser(old.userGrantsByRoleUuid, old.grantedRoleUuid, old.userUuid);
|
||||
call revokeRoleFromUser(old.grantedByRoleUuid, old.grantedRoleUuid, old.userUuid);
|
||||
return old;
|
||||
end; $$;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac customer
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-22T14:44:19.425403022.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
@ -21,6 +21,7 @@ subgraph customer["`**customer**`"]
|
||||
subgraph customer:permissions[ ]
|
||||
style customer:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:customer:INSERT{{customer:INSERT}}
|
||||
perm:customer:DELETE{{customer:DELETE}}
|
||||
perm:customer:UPDATE{{customer:UPDATE}}
|
||||
perm:customer:SELECT{{customer:SELECT}}
|
||||
@ -36,6 +37,7 @@ role:customer:owner ==> role:customer:admin
|
||||
role:customer:admin ==> role:customer:tenant
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:admin ==> perm:customer:INSERT
|
||||
role:customer:owner ==> perm:customer:DELETE
|
||||
role:customer:admin ==> perm:customer:UPDATE
|
||||
role:customer:tenant ==> perm:customer:SELECT
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-22T14:44:19.441879428.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -80,6 +80,46 @@ execute procedure insertTriggerForTestCustomer_tf();
|
||||
--changeset test-customer-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO test_customer permissions for the related global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
permissionUuid uuid;
|
||||
roleUuid uuid;
|
||||
begin
|
||||
call defineContext('create INSERT INTO test_customer permissions for the related global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
LOOP
|
||||
roleUuid := findRoleId(globalAdmin());
|
||||
permissionUuid := createPermission(row.uuid, 'INSERT', 'test_customer');
|
||||
call grantPermissionToRole(permissionUuid, roleUuid);
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds test_customer INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function test_customer_global_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'test_customer'),
|
||||
globalAdmin());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_test_customer_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure test_customer_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to test_customer,
|
||||
where only global-admin has that permission.
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac package
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-22T14:44:19.484173294.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-22T12:01:44.554331877.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -195,32 +195,22 @@ execute procedure test_package_test_customer_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to test_package,
|
||||
where the check is performed by an indirect role.
|
||||
where the check is performed by a direct role.
|
||||
|
||||
An indirect role is a role FIXME.
|
||||
A direct role is a role depending on a foreign key directly available in the NEW row.
|
||||
*/
|
||||
create or replace function test_package_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
if ( not hasInsertPermission(
|
||||
( SELECT customer.uuid FROM
|
||||
|
||||
(SELECT * FROM test_customer c
|
||||
WHERE c.uuid= NEW.customerUuid
|
||||
) AS customer
|
||||
|
||||
), 'INSERT', 'test_package') ) then
|
||||
raise exception
|
||||
'[403] insert into test_package not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end if;
|
||||
return NEW;
|
||||
raise exception '[403] insert into test_package not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger test_package_insert_permission_check_tg
|
||||
before insert on test_package
|
||||
for each row
|
||||
when ( not hasInsertPermission(NEW.customerUuid, 'INSERT', 'test_package') )
|
||||
execute procedure test_package_insert_permission_missing_tf();
|
||||
--//
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac domain
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-22T14:44:19.510830235.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,6 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T11:29:11.645391647.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-OBJECT:1 endDelimiter:--//
|
||||
@ -33,9 +34,12 @@ declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM test_package p
|
||||
WHERE p.uuid= NEW.packageUuid
|
||||
into newPackage;
|
||||
INTO newPackage;
|
||||
assert newPackage.uuid is not null, format('newPackage must not be null for NEW.packageUuid = %s', NEW.packageUuid);
|
||||
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testDomainOwner(NEW),
|
||||
@ -71,9 +75,9 @@ create trigger insertTriggerForTestDomain_tg
|
||||
after insert on test_domain
|
||||
for each row
|
||||
execute procedure insertTriggerForTestDomain_tf();
|
||||
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-update-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
@ -97,14 +101,18 @@ begin
|
||||
|
||||
SELECT * FROM test_package p
|
||||
WHERE p.uuid= OLD.packageUuid
|
||||
into oldPackage;
|
||||
INTO oldPackage;
|
||||
assert oldPackage.uuid is not null, format('oldPackage must not be null for OLD.packageUuid = %s', OLD.packageUuid);
|
||||
|
||||
SELECT * FROM test_package p
|
||||
WHERE p.uuid= NEW.packageUuid
|
||||
into newPackage;
|
||||
INTO newPackage;
|
||||
assert newPackage.uuid is not null, format('newPackage must not be null for NEW.packageUuid = %s', NEW.packageUuid);
|
||||
|
||||
|
||||
if NEW.packageUuid <> OLD.packageUuid then
|
||||
|
||||
call revokePermissionFromRole(findPermissionId(OLD.uuid, 'INSERT'), testPackageAdmin(oldPackage));
|
||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'INSERT'), testPackageAdmin(oldPackage));
|
||||
|
||||
call revokeRoleFromRole(testDomainOwner(OLD), testPackageAdmin(oldPackage));
|
||||
call grantRoleToRole(testDomainOwner(NEW), testPackageAdmin(newPackage));
|
||||
@ -137,9 +145,9 @@ create trigger updateTriggerForTestDomain_tg
|
||||
after update on test_domain
|
||||
for each row
|
||||
execute procedure updateTriggerForTestDomain_tf();
|
||||
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
@ -178,13 +186,17 @@ begin
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_test_domain_test_package_insert_tg
|
||||
after insert on test_package
|
||||
for each row
|
||||
execute procedure test_domain_test_package_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to test_domain.
|
||||
Checks if the user or assumed roles are allowed to insert a row to test_domain,
|
||||
where the check is performed by a direct role.
|
||||
|
||||
A direct role is a role depending on a foreign key directly available in the NEW row.
|
||||
*/
|
||||
create or replace function test_domain_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
@ -199,8 +211,8 @@ create trigger test_domain_insert_permission_check_tg
|
||||
for each row
|
||||
when ( not hasInsertPermission(NEW.packageUuid, 'INSERT', 'test_domain') )
|
||||
execute procedure test_domain_insert_permission_missing_tf();
|
||||
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
@ -208,13 +220,15 @@ create trigger test_domain_insert_permission_check_tg
|
||||
call generateRbacIdentityViewFromProjection('test_domain', $idName$
|
||||
name
|
||||
$idName$);
|
||||
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('test_domain',
|
||||
'name',
|
||||
$orderBy$
|
||||
name
|
||||
$orderBy$,
|
||||
$updates$
|
||||
version = new.version,
|
||||
packageUuid = new.packageUuid,
|
||||
@ -222,4 +236,3 @@ call generateRbacRestrictedView('test_domain',
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac contact
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-14T09:00:15.762621659.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-14T09:00:15.769718298.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -109,26 +109,16 @@ create or replace function hs_office_contact_global_insert_tf()
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
globalGuest(),
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_contact'));
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_contact'),
|
||||
globalGuest());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_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; $$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
@ -148,7 +138,7 @@ call generateRbacRestrictedView('hs_office_contact',
|
||||
label
|
||||
$orderBy$,
|
||||
$updates$
|
||||
label = new.label,
|
||||
label = new.label,
|
||||
postalAddress = new.postalAddress,
|
||||
emailAddresses = new.emailAddresses,
|
||||
phoneNumbers = new.phoneNumbers
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac person
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-18T13:35:44.716916229.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-18T13:35:44.726508114.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -142,15 +142,6 @@ call generateRbacRestrictedView('hs_office_person',
|
||||
tradeName = new.tradeName,
|
||||
givenName = new.givenName,
|
||||
familyName = new.familyName
|
||||
$updates$
|
||||
,
|
||||
$columns$
|
||||
uuid,
|
||||
personType,
|
||||
tradeName,
|
||||
givenName,
|
||||
familyName
|
||||
$columns$
|
||||
);
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac relation
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-15T17:17:00.854621634.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-15T17:17:00.864301165.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -65,21 +65,21 @@ begin
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationAgent(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePersonAdmin(newHolderPerson),
|
||||
hsOfficeRelationAdmin(NEW)]
|
||||
hsOfficeRelationAdmin(NEW),
|
||||
hsOfficePersonAdmin(newHolderPerson)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationTenant(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeRelationAgent(NEW),
|
||||
hsOfficePersonAdmin(newHolderPerson),
|
||||
hsOfficeContactAdmin(newContact),
|
||||
hsOfficePersonAdmin(newHolderPerson)],
|
||||
hsOfficeRelationAgent(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeContactReferrer(newContact),
|
||||
hsOfficePersonReferrer(newHolderPerson),
|
||||
hsOfficePersonReferrer(newAnchorPerson)]
|
||||
hsOfficePersonReferrer(newAnchorPerson),
|
||||
hsOfficeContactReferrer(newContact)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
@ -220,34 +220,30 @@ begin
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_office_relation_hs_office_person_insert_tg
|
||||
after insert on hs_office_person
|
||||
for each row
|
||||
execute procedure hs_office_relation_hs_office_person_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_relation.
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_relation,
|
||||
where the check is performed by a direct role.
|
||||
|
||||
A direct role is a role depending on a foreign key directly available in the NEW row.
|
||||
*/
|
||||
create or replace function hs_office_relation_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
if ( not hasInsertPermission(
|
||||
( SELECT anchorPerson.uuid FROM
|
||||
|
||||
(select * from hs_office_person as p where p.uuid = NEW.anchorUuid) AS anchorPerson
|
||||
|
||||
), 'INSERT', 'hs_office_relation') ) then
|
||||
raise exception
|
||||
'[403] insert into hs_office_relation not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end if;
|
||||
return NEW;
|
||||
raise exception '[403] insert into hs_office_relation not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_relation_insert_permission_check_tg
|
||||
before insert on hs_office_relation
|
||||
for each row
|
||||
when ( not hasInsertPermission(NEW.anchorUuid, 'INSERT', 'hs_office_relation') )
|
||||
execute procedure hs_office_relation_insert_permission_missing_tf();
|
||||
--//
|
||||
|
||||
@ -271,7 +267,7 @@ call generateRbacRestrictedView('hs_office_relation',
|
||||
(select idName from hs_office_person_iv p where p.uuid = target.holderUuid)
|
||||
$orderBy$,
|
||||
$updates$
|
||||
contactUuid = new.contactUuid
|
||||
contactUuid = new.contactUuid
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac partner
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-18T09:31:47.361311186.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-18T09:31:47.368892199.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -131,36 +131,6 @@ begin
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
-- raise exception 'RBAC updated from rel % to %', OLD.partnerReluuid, NEW.partnerReluuid;
|
||||
end; $$;
|
||||
|
||||
|
||||
|
||||
create or replace procedure updateRbacRulesForHsOfficePartnerX(
|
||||
OLD hs_office_partner,
|
||||
NEW hs_office_partner
|
||||
)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
partnerRel hs_office_relation;
|
||||
grantCount int;
|
||||
|
||||
begin
|
||||
assert OLD.uuid = NEW.uuid, 'uuid did change, but should not';
|
||||
assert OLD.partnerReluuid <> NEW.partnerReluuid, 'partnerReluuid did not change, but should have';
|
||||
|
||||
delete from rbacgrants where grantedbytriggerof = OLD.uuid;
|
||||
select count(*) from rbacgrants where grantedbytriggerof=NEW.uuid into grantCount;
|
||||
assert grantCount=0, format('unexpected grantCount>0: %d', grantCount);
|
||||
|
||||
call buildRbacSystemForHsOfficePartner(NEW);
|
||||
select * from hs_office_relation where uuid=NEW.partnerReluuid into partnerRel;
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(partnerRel));
|
||||
select count(*) from rbacgrants where grantedbytriggerof=NEW.uuid into grantCount;
|
||||
assert grantCount>0, format('unexpected grantCount=0: %d', grantCount);
|
||||
raise warning 'WARNING grantCount=%', grantCount;
|
||||
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@ -172,7 +142,7 @@ create or replace function updateTriggerForHsOfficePartner_tf()
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call updateRbacRulesForHsOfficePartnerX(OLD, NEW);
|
||||
call updateRbacRulesForHsOfficePartner(OLD, NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
@ -228,7 +198,8 @@ create trigger z_hs_office_partner_global_insert_tg
|
||||
execute procedure hs_office_partner_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner.
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner,
|
||||
where only global-admin has that permission.
|
||||
*/
|
||||
create or replace function hs_office_partner_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
@ -262,7 +233,7 @@ call generateRbacRestrictedView('hs_office_partner',
|
||||
'P-' || partnerNumber
|
||||
$orderBy$,
|
||||
$updates$
|
||||
partnerRelUuid = new.partnerRelUuid
|
||||
partnerRelUuid = new.partnerRelUuid
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac partnerDetails
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-16T12:04:37.309540020.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-16T12:04:37.319601283.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -102,7 +102,8 @@ create trigger z_hs_office_partner_details_global_insert_tg
|
||||
execute procedure hs_office_partner_details_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner_details.
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner_details,
|
||||
where only global-admin has that permission.
|
||||
*/
|
||||
create or replace function hs_office_partner_details_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
@ -140,7 +141,7 @@ call generateRbacRestrictedView('hs_office_partner_details',
|
||||
uuid
|
||||
$orderBy$,
|
||||
$updates$
|
||||
registrationOffice = new.registrationOffice,
|
||||
registrationOffice = new.registrationOffice,
|
||||
registrationNumber = new.registrationNumber,
|
||||
birthPlace = new.birthPlace,
|
||||
birthName = new.birthName,
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac bankAccount
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-14T08:55:11.118624882.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-14T08:55:11.127959896.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -109,26 +109,16 @@ create or replace function hs_office_bankaccount_global_insert_tf()
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
globalGuest(),
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_bankaccount'));
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_bankaccount'),
|
||||
globalGuest());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_office_bankaccount_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure hs_office_bankaccount_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_bankaccount.
|
||||
*/
|
||||
create or replace function hs_office_bankaccount_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into hs_office_bankaccount not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
@ -148,7 +138,7 @@ call generateRbacRestrictedView('hs_office_bankaccount',
|
||||
iban
|
||||
$orderBy$,
|
||||
$updates$
|
||||
holder = new.holder,
|
||||
holder = new.holder,
|
||||
iban = new.iban,
|
||||
bic = new.bic
|
||||
$updates$);
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac sepaMandate
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-18T16:07:14.011240343.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-18T16:07:14.019894954.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -64,8 +64,8 @@ begin
|
||||
hsOfficeSepaMandateAgent(NEW),
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeRelationAgent(newDebitorRel),
|
||||
hsOfficeBankAccountReferrer(newBankAccount)]
|
||||
hsOfficeBankAccountReferrer(newBankAccount),
|
||||
hsOfficeRelationAgent(newDebitorRel)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
@ -146,7 +146,10 @@ create trigger z_hs_office_sepamandate_hs_office_relation_insert_tg
|
||||
execute procedure hs_office_sepamandate_hs_office_relation_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_sepamandate.
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_sepamandate,
|
||||
where the check is performed by an indirect role.
|
||||
|
||||
An indirect role is a role FIXME.
|
||||
*/
|
||||
create or replace function hs_office_sepamandate_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
@ -195,7 +198,7 @@ call generateRbacRestrictedView('hs_office_sepamandate',
|
||||
validity
|
||||
$orderBy$,
|
||||
$updates$
|
||||
reference = new.reference,
|
||||
reference = new.reference,
|
||||
agreement = new.agreement,
|
||||
validity = new.validity
|
||||
$updates$);
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac debitor
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-16T13:52:18.484919583.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-20T13:55:16.722860098.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -177,7 +177,8 @@ create trigger z_hs_office_debitor_global_insert_tg
|
||||
execute procedure hs_office_debitor_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_debitor.
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_debitor,
|
||||
where only global-admin has that permission.
|
||||
*/
|
||||
create or replace function hs_office_debitor_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
@ -221,7 +222,7 @@ call generateRbacRestrictedView('hs_office_debitor',
|
||||
defaultPrefix
|
||||
$orderBy$,
|
||||
$updates$
|
||||
debitorRelUuid = new.debitorRelUuid,
|
||||
debitorRelUuid = new.debitorRelUuid,
|
||||
billable = new.billable,
|
||||
refundBankAccountUuid = new.refundBankAccountUuid,
|
||||
vatId = new.vatId,
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac membership
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-21T17:09:08.826781619.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-21T17:09:08.832004329.
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
@ -54,8 +54,8 @@ begin
|
||||
hsOfficeMembershipAdmin(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeMembershipOwner(NEW),
|
||||
hsOfficeRelationAgent(newPartnerRel)]
|
||||
hsOfficeRelationAgent(newPartnerRel),
|
||||
hsOfficeMembershipOwner(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
@ -133,7 +133,10 @@ create trigger z_hs_office_membership_hs_office_relation_insert_tg
|
||||
execute procedure hs_office_membership_hs_office_relation_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_membership.
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_membership,
|
||||
where the check is performed by an indirect role.
|
||||
|
||||
An indirect role is a role FIXME.
|
||||
*/
|
||||
create or replace function hs_office_membership_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
@ -183,7 +186,7 @@ call generateRbacRestrictedView('hs_office_membership',
|
||||
validity
|
||||
$orderBy$,
|
||||
$updates$
|
||||
validity = new.validity,
|
||||
validity = new.validity,
|
||||
membershipFeeBillable = new.membershipFeeBillable,
|
||||
reasonForTermination = new.reasonForTermination
|
||||
$updates$);
|
||||
|
@ -4,8 +4,9 @@ spring:
|
||||
platform: postgres
|
||||
|
||||
datasource:
|
||||
url: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers
|
||||
url-tc: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers
|
||||
url-local: jdbc:postgresql://localhost:5432/postgres
|
||||
url: ${spring.datasource.url-tc}
|
||||
username: postgres
|
||||
password: password
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user