RBAC-rebuild (#140)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: #140
Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
Michael Hoennig 2025-01-02 10:02:47 +01:00
parent 9debaa1fc0
commit 71be87b36b
45 changed files with 1367 additions and 359 deletions

View File

@ -5,8 +5,8 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRbacEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.AttributeOverrides;
@ -15,20 +15,20 @@ import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import java.io.IOException;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NULLABLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.DELETE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NULLABLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.DELETE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
@Entity
@Table(schema = "hs_booking", name = "item_rv")
@ -41,7 +41,7 @@ import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
})
public class HsBookingItemRbacEntity extends HsBookingItem {
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("bookingItem", HsBookingItemRbacEntity.class)
.withIdentityView(SQL.projection("caption"))
.withRestrictedViewOrderBy(SQL.expression("validity"))

View File

@ -6,30 +6,30 @@ import lombok.Setter;
import lombok.experimental.SuperBuilder;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRbacEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import java.io.IOException;
import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.DEBITOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.DELETE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.fetchedBySql;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.DELETE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.fetchedBySql;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
@Entity
@Table(schema = "hs_booking", name = "project_rv")
@ -39,7 +39,7 @@ import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
@NoArgsConstructor
public class HsBookingProjectRbacEntity extends HsBookingProject {
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("project", HsBookingProjectRbacEntity.class)
.withIdentityView(SQL.query("""
SELECT bookingProject.uuid as uuid, debitorIV.idName || '-' || base.cleanIdentifier(bookingProject.caption) as idName

View File

@ -6,31 +6,31 @@ import lombok.Setter;
import lombok.experimental.SuperBuilder;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRbacEntity;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRbacEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import java.io.IOException;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.CaseDef.inCaseOf;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NULLABLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.DELETE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.GUEST;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.REFERRER;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.CaseDef.inCaseOf;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NULLABLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.DELETE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.GUEST;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.REFERRER;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
@Entity
@Table(schema = "hs_hosting", name = "asset_rv")
@ -40,7 +40,7 @@ import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
@NoArgsConstructor
public class HsHostingAssetRbacEntity extends HsHostingAsset {
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("asset", HsHostingAssetRbacEntity.class)
.withIdentityView(SQL.projection("identifier"))
.withRestrictedViewOrderBy(SQL.expression("identifier"))

View File

@ -4,7 +4,7 @@ import lombok.*;
import lombok.experimental.FieldNameConstants;
import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.repr.Stringify;
import net.hostsharing.hsadminng.repr.Stringifyable;
@ -12,10 +12,10 @@ import jakarta.persistence.*;
import java.io.IOException;
import java.util.UUID;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.repr.Stringify.stringify;
@Entity
@ -57,7 +57,7 @@ public class HsOfficeBankAccountEntity implements BaseEntity<HsOfficeBankAccount
return holder;
}
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("bankAccount", HsOfficeBankAccountEntity.class)
.withIdentityView(SQL.projection("iban"))
.withUpdatableColumns("holder", "iban", "bic")

View File

@ -3,17 +3,17 @@ package net.hostsharing.hsadminng.hs.office.contact;
import lombok.*;
import lombok.experimental.SuperBuilder;
import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import jakarta.persistence.*;
import java.io.IOException;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
@Entity
@Table(schema = "hs_office", name = "contact_rv")
@ -24,7 +24,7 @@ import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
@DisplayAs("RbacContact")
public class HsOfficeContactRbacEntity extends HsOfficeContact {
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("contact", HsOfficeContactRbacEntity.class)
.withIdentityView(SQL.projection("caption"))
.withUpdatableColumns("caption", "postalAddress", "emailAddresses", "phoneNumbers")

View File

@ -9,7 +9,7 @@ import lombok.Setter;
import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.repr.Stringify;
import net.hostsharing.hsadminng.repr.Stringifyable;
import org.hibernate.annotations.GenericGenerator;
@ -21,16 +21,16 @@ import java.time.LocalDate;
import java.util.UUID;
import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
import static net.hostsharing.hsadminng.repr.Stringify.stringify;
@Entity
@ -139,9 +139,9 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, BaseE
ofNullable(assetValue).orElse(BigDecimal.ZERO));
}
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("coopAssetsTransaction", HsOfficeCoopAssetsTransactionEntity.class)
.withIdentityView(RbacView.SQL.projection("reference"))
.withIdentityView(RbacSpec.SQL.projection("reference"))
.withUpdatableColumns("comment")
.importEntityAlias("membership", HsOfficeMembershipEntity.class, usingDefaultCase(),
dependsOnColumn("membershipUuid"),

View File

@ -7,9 +7,9 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import net.hostsharing.hsadminng.repr.Stringify;
import net.hostsharing.hsadminng.repr.Stringifyable;
@ -19,16 +19,16 @@ import java.time.LocalDate;
import java.util.UUID;
import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
import static net.hostsharing.hsadminng.repr.Stringify.stringify;
@Entity
@ -123,7 +123,7 @@ public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, BaseE
return "%s:%.3s:%+d".formatted(getMemberNumberTagged(), transactionType, shareCount);
}
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("coopSharesTransaction", HsOfficeCoopSharesTransactionEntity.class)
.withIdentityView(SQL.projection("reference"))
.withUpdatableColumns("comment")

View File

@ -12,8 +12,8 @@ import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelation;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRbacEntity;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import net.hostsharing.hsadminng.repr.Stringify;
import net.hostsharing.hsadminng.repr.Stringifyable;
import org.hibernate.annotations.GenericGenerator;
@ -40,17 +40,17 @@ import static jakarta.persistence.CascadeType.PERSIST;
import static jakarta.persistence.CascadeType.REFRESH;
import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.DEBITOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NULLABLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.fetchedBySql;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NULLABLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.fetchedBySql;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
import static net.hostsharing.hsadminng.repr.Stringify.stringify;
@Entity
@ -160,7 +160,7 @@ public class HsOfficeDebitorEntity implements BaseEntity<HsOfficeDebitorEntity>,
return getTaggedDebitorNumber();
}
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("debitor", HsOfficeDebitorEntity.class)
.withIdentityView(SQL.query("""
SELECT debitor.uuid AS uuid,

View File

@ -11,8 +11,8 @@ import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRbacEntity;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import net.hostsharing.hsadminng.repr.Stringify;
import net.hostsharing.hsadminng.repr.Stringifyable;
import org.hibernate.annotations.Type;
@ -38,21 +38,21 @@ import static io.hypersistence.utils.hibernate.type.range.Range.emptyRange;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.lowerInclusiveFromPostgresDateRange;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.upperInclusiveFromPostgresDateRange;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.DELETE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.fetchedBySql;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.DELETE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.fetchedBySql;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
import static net.hostsharing.hsadminng.repr.Stringify.stringify;
@Entity
@ -160,7 +160,7 @@ public class HsOfficeMembershipEntity implements BaseEntity<HsOfficeMembershipEn
}
}
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("membership", HsOfficeMembershipEntity.class)
.withIdentityView(SQL.query("""
SELECT m.uuid AS uuid,

View File

@ -3,8 +3,8 @@ package net.hostsharing.hsadminng.hs.office.partner;
import lombok.*;
import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import net.hostsharing.hsadminng.repr.Stringify;
import net.hostsharing.hsadminng.repr.Stringifyable;
@ -13,10 +13,10 @@ import java.io.IOException;
import java.time.LocalDate;
import java.util.UUID;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
import static net.hostsharing.hsadminng.repr.Stringify.stringify;
@Entity
@ -67,7 +67,7 @@ public class HsOfficePartnerDetailsEntity implements BaseEntity<HsOfficePartnerD
}
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("partnerDetails", HsOfficePartnerDetailsEntity.class)
.withIdentityView(SQL.query("""
SELECT partnerDetails.uuid as uuid, partner_iv.idName as idName

View File

@ -12,8 +12,8 @@ import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRbacEntity;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelation;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import net.hostsharing.hsadminng.repr.Stringify;
import net.hostsharing.hsadminng.repr.Stringifyable;
import org.hibernate.annotations.NotFound;
@ -24,14 +24,14 @@ import java.io.IOException;
import java.util.UUID;
import static jakarta.persistence.CascadeType.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.repr.Stringify.stringify;
@ -100,7 +100,7 @@ public class HsOfficePartnerEntity implements Stringifyable, BaseEntity<HsOffice
return getTaggedPartnerNumber();
}
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("partner", HsOfficePartnerEntity.class)
.withIdentityView(SQL.projection("'P-' || partnerNumber"))
.withUpdatableColumns("partnerRelUuid")

View File

@ -4,17 +4,17 @@ import lombok.*;
import lombok.experimental.FieldNameConstants;
import lombok.experimental.SuperBuilder;
import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import jakarta.persistence.*;
import java.io.IOException;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
@Entity
@Table(schema = "hs_office", name = "person_rv")
@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
@DisplayAs("RbacPerson")
public class HsOfficePersonRbacEntity extends HsOfficePerson<HsOfficePersonRbacEntity> {
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("person", HsOfficePersonRbacEntity.class)
.withIdentityView(SQL.projection("concat(tradeName, familyName, givenName)"))
.withUpdatableColumns("personType", "title", "salutation", "tradeName", "givenName", "familyName")

View File

@ -7,31 +7,31 @@ import lombok.experimental.SuperBuilder;
import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRbacEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRbacEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import java.io.IOException;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.CaseDef.inCaseOf;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.CaseDef.inOtherCases;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.DELETE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.REFERRER;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.CaseDef.inCaseOf;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.CaseDef.inOtherCases;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.DELETE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.UPDATE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.REFERRER;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
@Entity
@Table(schema = "hs_office", name = "relation_rv")
@ -42,7 +42,7 @@ import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
@DisplayAs("RbacRelation")
public class HsOfficeRelationRbacEntity extends HsOfficeRelation {
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("relation", HsOfficeRelationRbacEntity.class)
.withIdentityView(SQL.projection("""
(select idName from hs_office.person_iv p where p.uuid = anchorUuid)

View File

@ -8,7 +8,7 @@ import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRbacEntity;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.repr.Stringify;
import net.hostsharing.hsadminng.repr.Stringifyable;
import org.hibernate.annotations.Type;
@ -20,16 +20,16 @@ import java.util.UUID;
import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.DEBITOR;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
import static net.hostsharing.hsadminng.repr.Stringify.stringify;
@Entity
@ -100,7 +100,7 @@ public class HsOfficeSepaMandateEntity implements Stringifyable, BaseEntity<HsOf
return reference;
}
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("sepaMandate", HsOfficeSepaMandateEntity.class)
.withIdentityView(query("""
select sm.uuid as uuid, ba.iban || '-' || sm.validity as idName

View File

@ -7,20 +7,20 @@ import java.util.stream.Stream;
import static java.util.stream.Collectors.joining;
import static net.hostsharing.hsadminng.rbac.generator.PostgresTriggerReference.NEW;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacGrantDefinition.GrantType.PERM_TO_ROLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.GUEST;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacGrantDefinition.GrantType.PERM_TO_ROLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.ADMIN;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.GUEST;
import static net.hostsharing.hsadminng.rbac.generator.StringWriter.with;
import static org.apache.commons.lang3.StringUtils.capitalize;
import static org.apache.commons.lang3.StringUtils.uncapitalize;
public class InsertTriggerGenerator {
private final RbacView rbacDef;
private final RbacSpec rbacDef;
private final String liquibaseTagPrefix;
public InsertTriggerGenerator(final RbacView rbacDef, final String liqibaseTagPrefix) {
public InsertTriggerGenerator(final RbacSpec rbacDef, final String liqibaseTagPrefix) {
this.rbacDef = rbacDef;
this.liquibaseTagPrefix = liqibaseTagPrefix;
}
@ -203,8 +203,8 @@ public class InsertTriggerGenerator {
plPgSql.chopEmptyLines();
}
private void generateInsertPermissionChecksForSingleGrant(final StringWriter plPgSql, final RbacView.RbacGrantDefinition g) {
final RbacView.EntityAlias superRoleEntityAlias = g.getSuperRoleDef().getEntityAlias();
private void generateInsertPermissionChecksForSingleGrant(final StringWriter plPgSql, final RbacSpec.RbacGrantDefinition g) {
final RbacSpec.EntityAlias superRoleEntityAlias = g.getSuperRoleDef().getEntityAlias();
final var caseCondition = g.isConditional()
? ("NEW.type in (" + toStringList(g.getForCases()) + ") and ")
@ -275,15 +275,15 @@ public class InsertTriggerGenerator {
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
}
private String toStringList(final Set<RbacView.CaseDef> cases) {
private String toStringList(final Set<RbacSpec.CaseDef> cases) {
return cases.stream().map(c -> "'" + c.value + "'").collect(joining(", "));
}
private boolean isGrantToADifferentTable(final RbacView.RbacGrantDefinition g) {
private boolean isGrantToADifferentTable(final RbacSpec.RbacGrantDefinition g) {
return !rbacDef.getRootEntityAlias().getRawTableNameWithSchema().equals(g.getSuperRoleDef().getEntityAlias().getRawTableNameWithSchema());
}
private Stream<RbacView.RbacGrantDefinition> getInsertGrants() {
private Stream<RbacSpec.RbacGrantDefinition> getInsertGrants() {
return rbacDef.getGrantDefs().stream()
.filter(g -> g.grantType() == PERM_TO_ROLE)
.filter(g -> g.getPermDef().toCreate && g.getPermDef().getPermission() == INSERT);
@ -298,14 +298,14 @@ public class InsertTriggerGenerator {
g.getSuperRoleDef().getEntityAlias().isGlobal() && g.getSuperRoleDef().getRole() == GUEST);
}
private Optional<RbacView.RbacGrantDefinition> getOptionalInsertGrant() {
private Optional<RbacSpec.RbacGrantDefinition> getOptionalInsertGrant() {
return getInsertGrants()
.reduce(singleton());
}
private Optional<RbacView.RbacRoleDefinition> getOptionalInsertSuperRole() {
private Optional<RbacSpec.RbacRoleDefinition> getOptionalInsertSuperRole() {
return getInsertGrants()
.map(RbacView.RbacGrantDefinition::getSuperRoleDef)
.map(RbacSpec.RbacGrantDefinition::getSuperRoleDef)
.reduce(singleton());
}
@ -319,12 +319,12 @@ public class InsertTriggerGenerator {
};
}
private static String toVar(final RbacView.RbacRoleDefinition roleDef) {
private static String toVar(final RbacSpec.RbacRoleDefinition roleDef) {
return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().name());
}
private String toRoleDescriptor(final RbacView.RbacRoleDefinition roleDef, final String ref) {
private String toRoleDescriptor(final RbacSpec.RbacRoleDefinition roleDef, final String ref) {
final var functionName = roleDef.descriptorFunctionName();
if (roleDef.getEntityAlias().isGlobal()) {
return functionName + "()";

View File

@ -3,12 +3,12 @@ package net.hostsharing.hsadminng.rbac.generator;
import static net.hostsharing.hsadminng.rbac.generator.StringWriter.with;
public class RbacIdentityViewGenerator {
private final RbacView rbacDef;
private final RbacSpec rbacDef;
private final String liquibaseTagPrefix;
private final String simpleEntityVarName;
private final String rawTableName;
public RbacIdentityViewGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) {
public RbacIdentityViewGenerator(final RbacSpec rbacDef, final String liquibaseTagPrefix) {
this.rbacDef = rbacDef;
this.liquibaseTagPrefix = liquibaseTagPrefix;
this.simpleEntityVarName = rbacDef.getRootEntityAlias().simpleName();

View File

@ -7,7 +7,7 @@ public class RbacObjectGenerator {
private final String liquibaseTagPrefix;
private final String rawTableName;
public RbacObjectGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) {
public RbacObjectGenerator(final RbacSpec rbacDef, final String liquibaseTagPrefix) {
this.liquibaseTagPrefix = liquibaseTagPrefix;
this.rawTableName = rbacDef.getRootEntityAlias().getRawTableNameWithSchema();
}

View File

@ -0,0 +1,80 @@
package net.hostsharing.hsadminng.rbac.generator;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacGrantDefinition;
import java.util.HashSet;
import java.util.Set;
import static net.hostsharing.hsadminng.rbac.generator.StringWriter.with;
class RbacRbacSystemRebuildGenerator {
private final RbacSpec rbacDef;
private final Set<RbacGrantDefinition> rbacGrants = new HashSet<>();
private final String liquibaseTagPrefix;
private final String rawTableName;
RbacRbacSystemRebuildGenerator(final RbacSpec rbacDef, final String liquibaseTagPrefix) {
this.rbacDef = rbacDef;
this.liquibaseTagPrefix = liquibaseTagPrefix;
this.rawTableName = rbacDef.getRootEntityAlias().getRawTableNameWithSchema();
}
void generateTo(final StringWriter plPgSql) {
plPgSql.writeLn("""
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:${liquibaseTagPrefix}-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table ${rawTableName} after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table ${rawTableName}', null, <<insert executing global admin user here>>);
-- call ${rawTableName}_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `${rawTableName}.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`${rawTableName}.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure ${rawTableName}_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row ${rawTableName};
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM ${rawTableName} LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL ${rawTableName}_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//
""",
with("liquibaseTagPrefix", liquibaseTagPrefix),
with("rawTableName", rawTableName));
}
}

View File

@ -6,11 +6,11 @@ import static net.hostsharing.hsadminng.rbac.generator.StringWriter.indented;
import static net.hostsharing.hsadminng.rbac.generator.StringWriter.with;
public class RbacRestrictedViewGenerator {
private final RbacView rbacDef;
private final RbacSpec rbacDef;
private final String liquibaseTagPrefix;
private final String rawTableName;
public RbacRestrictedViewGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) {
public RbacRestrictedViewGenerator(final RbacSpec rbacDef, final String liquibaseTagPrefix) {
this.rbacDef = rbacDef;
this.liquibaseTagPrefix = liquibaseTagPrefix;
this.rawTableName = rbacDef.getRootEntityAlias().getRawTableNameWithSchema();

View File

@ -8,7 +8,7 @@ public class RbacRoleDescriptorsGenerator {
private final String simpleEntityVarName;
private final String rawTableName;
public RbacRoleDescriptorsGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) {
public RbacRoleDescriptorsGenerator(final RbacSpec rbacDef, final String liquibaseTagPrefix) {
this.liquibaseTagPrefix = liquibaseTagPrefix;
this.simpleEntityVarName = rbacDef.getRootEntityAlias().simpleName();
this.rawTableName = rbacDef.getRootEntityAlias().getRawTableNameWithSchema();

View File

@ -22,19 +22,18 @@ import static java.util.Arrays.asList;
import static java.util.Arrays.stream;
import static java.util.Collections.max;
import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacGrantDefinition.GrantType.PERM_TO_ROLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacGrantDefinition.GrantType.ROLE_TO_ROLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.Part.AUTO_FETCH;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacGrantDefinition.GrantType.PERM_TO_ROLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacGrantDefinition.GrantType.ROLE_TO_ROLE;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.Part.AUTO_FETCH;
import static org.apache.commons.collections4.SetUtils.hashSet;
import static org.apache.commons.lang3.StringUtils.capitalize;
import static org.apache.commons.lang3.StringUtils.uncapitalize;
@Getter
// TODO.refa: rename to RbacDSL
public class RbacView {
public class RbacSpec {
public static final String GLOBAL = "rbac.global";
public static final String OUTPUT_BASEDIR = "src/main/resources/db/changelog";
@ -90,11 +89,11 @@ public class RbacView {
* @param <E>
* a JPA entity class extending RbacObject
*/
public static <E extends BaseEntity<?>> RbacView rbacViewFor(final String alias, final Class<E> entityClass) {
return new RbacView(alias, entityClass);
public static <E extends BaseEntity<?>> RbacSpec rbacViewFor(final String alias, final Class<E> entityClass) {
return new RbacSpec(alias, entityClass);
}
RbacView(final String alias, final Class<? extends BaseEntity<?>> entityClass) {
RbacSpec(final String alias, final Class<? extends BaseEntity<?>> entityClass) {
rootEntityAlias = new EntityAlias(alias, entityClass);
entityAliases.put(alias, rootEntityAlias);
new RbacSubjectReference(CREATOR);
@ -110,7 +109,7 @@ public class RbacView {
* @return
* the `this` instance itself to allow chained calls.
*/
public RbacView withUpdatableColumns(final String... columnNames) {
public RbacSpec withUpdatableColumns(final String... columnNames) {
Collections.addAll(updatableColumns, columnNames);
verifyVersionColumnExists();
return this;
@ -134,7 +133,7 @@ public class RbacView {
* @return
* the `this` instance itself to allow chained calls.
*/
public RbacView withIdentityView(final SQL sqlExpression) {
public RbacSpec withIdentityView(final SQL sqlExpression) {
this.identityViewSqlQuery = sqlExpression;
return this;
}
@ -150,7 +149,7 @@ public class RbacView {
* @return
* the `this` instance itself to allow chained calls.
*/
public RbacView withRestrictedViewOrderBy(final SQL orderBySqlExpression) {
public RbacSpec withRestrictedViewOrderBy(final SQL orderBySqlExpression) {
this.orderBySqlExpression = orderBySqlExpression;
return this;
}
@ -166,7 +165,7 @@ public class RbacView {
* @return
* the `this` instance itself to allow chained calls.
*/
public RbacView createRole(final Role role, final Consumer<RbacRoleDefinition> with) {
public RbacSpec createRole(final Role role, final Consumer<RbacRoleDefinition> with) {
final RbacRoleDefinition newRoleDef = findRbacRole(rootEntityAlias, role).toCreate();
with.accept(newRoleDef);
previousRoleDef = newRoleDef;
@ -182,7 +181,7 @@ public class RbacView {
* @return
* the `this` instance itself to allow chained calls.
*/
public RbacView createSubRole(final Role role) {
public RbacSpec createSubRole(final Role role) {
final RbacRoleDefinition newRoleDef = findRbacRole(rootEntityAlias, role).toCreate();
findOrCreateGrantDef(newRoleDef, previousRoleDef).toCreate();
previousRoleDef = newRoleDef;
@ -202,7 +201,7 @@ public class RbacView {
* @return
* the `this` instance itself to allow chained calls.
*/
public RbacView createSubRole(final Role role, final Consumer<RbacRoleDefinition> with) {
public RbacSpec createSubRole(final Role role, final Consumer<RbacRoleDefinition> with) {
final RbacRoleDefinition newRoleDef = findRbacRole(rootEntityAlias, role).toCreate();
findOrCreateGrantDef(newRoleDef, previousRoleDef).toCreate();
with.accept(newRoleDef);
@ -254,7 +253,7 @@ public class RbacView {
.orElseGet(() -> new RbacPermissionDefinition(entityAlias, permission, null, true));
}
public <EC extends BaseEntity> RbacView declarePlaceholderEntityAliases(final String... aliasNames) {
public <EC extends BaseEntity> RbacSpec declarePlaceholderEntityAliases(final String... aliasNames) {
for (String alias : aliasNames) {
entityAliases.put(alias, new EntityAlias(alias));
}
@ -287,7 +286,7 @@ public class RbacView {
* @param <EC>
* a JPA entity class extending RbacObject
*/
public <EC extends BaseEntity<?>> RbacView importRootEntityAliasProxy(
public <EC extends BaseEntity<?>> RbacSpec importRootEntityAliasProxy(
final String aliasName,
final Class<? extends BaseEntity<?>> entityClass,
final ColumnValue forCase,
@ -312,7 +311,7 @@ public class RbacView {
* @param <EC>
* a JPA entity class extending RbacObject
*/
public RbacView importSubEntityAlias(
public RbacSpec importSubEntityAlias(
final String aliasName, final Class<? extends BaseEntity<?>> entityClass,
final SQL fetchSql, final Column dependsOnColum) {
importEntityAliasImpl(aliasName, entityClass, usingDefaultCase(), fetchSql, dependsOnColum, true, NOT_NULL);
@ -349,7 +348,7 @@ public class RbacView {
* @param <EC>
* a JPA entity class extending RbacObject
*/
public RbacView importEntityAlias(
public RbacSpec importEntityAlias(
final String aliasName, final Class<? extends BaseEntity<?>> entityClass, final ColumnValue usingCase,
final Column dependsOnColum, final SQL fetchSql, final Nullable nullable) {
importEntityAliasImpl(aliasName, entityClass, usingCase, fetchSql, dependsOnColum, false, nullable);
@ -379,12 +378,12 @@ public class RbacView {
return entityAlias;
}
private static RbacView rbacDefinition(final Class<? extends BaseEntity> entityClass)
private static RbacSpec rbacDefinition(final Class<? extends BaseEntity> entityClass)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
return (RbacView) entityClass.getMethod("rbac").invoke(null);
return (RbacSpec) entityClass.getMethod("rbac").invoke(null);
}
private RbacView importAsAlias(final String aliasName, final RbacView importedRbacView, final ColumnValue forCase, final boolean asSubEntity) {
private RbacSpec importAsAlias(final String aliasName, final RbacSpec importedRbacView, final ColumnValue forCase, final boolean asSubEntity) {
final var mapper = new AliasNameMapper(importedRbacView, aliasName,
asSubEntity ? entityAliases.keySet() : null);
copyOf(importedRbacView.getEntityAliases().values()).stream()
@ -416,7 +415,7 @@ public class RbacView {
return this;
}
public RbacView switchOnColumn(final String discriminatorColumName, final CaseDef... caseDefs) {
public RbacSpec switchOnColumn(final String discriminatorColumName, final CaseDef... caseDefs) {
this.discriminatorColumName = discriminatorColumName;
allCases.addAll(stream(caseDefs).toList());
@ -511,7 +510,7 @@ public class RbacView {
new RbacViewPostgresGenerator(this).generateToChangeLog(Path.of(OUTPUT_BASEDIR, baseFileName + ".sql"));
}
public RbacView limitDiagramTo(final String... aliasNames) {
public RbacSpec limitDiagramTo(final String... aliasNames) {
this.limitDiagramToAliasNames = Set.of(aliasNames);
return this;
}
@ -542,15 +541,15 @@ public class RbacView {
this.superRoleDef = findRbacRole(entityAlias, role);
}
public RbacView grantRole(final String entityAlias, final Role role) {
public RbacSpec grantRole(final String entityAlias, final Role role) {
findOrCreateGrantDef(findRbacRole(entityAlias, role), superRoleDef).toCreate();
return RbacView.this;
return RbacSpec.this;
}
public RbacView grantPermission(final Permission perm) {
public RbacSpec grantPermission(final Permission perm) {
final var forTable = rootEntityAlias.getRawTableNameWithSchema();
findOrCreateGrantDef(findRbacPerm(rootEntityAlias, perm, forTable), superRoleDef).toCreate();
return RbacView.this;
return RbacSpec.this;
}
}
@ -698,10 +697,10 @@ public class RbacView {
this.subRole = role;
}
public RbacView wouldBeGrantedTo(final String entityAlias, final Role role) {
public RbacSpec wouldBeGrantedTo(final String entityAlias, final Role role) {
this.superRoleEntity = findEntityAlias(entityAlias);
this.superRole = role;
return RbacView.this;
return RbacSpec.this;
}
}
@ -733,9 +732,9 @@ public class RbacView {
* @return
* The RbacView specification to which this permission definition belongs.
*/
public RbacView grantedTo(final String entityAlias, final Role role) {
public RbacSpec grantedTo(final String entityAlias, final Role role) {
findOrCreateGrantDef(this, findRbacRole(entityAlias, role)).toCreate();
return RbacView.this;
return RbacSpec.this;
}
@Override
@ -1186,12 +1185,12 @@ public class RbacView {
private static class AliasNameMapper {
private final RbacView importedRbacView;
private final RbacSpec importedRbacView;
private final String outerAliasName;
private final Set<String> outerAliasNames;
AliasNameMapper(final RbacView importedRbacView, final String outerAliasName, final Set<String> outerAliasNames) {
AliasNameMapper(final RbacSpec importedRbacView, final String outerAliasName, final Set<String> outerAliasNames) {
this.importedRbacView = importedRbacView;
this.outerAliasName = outerAliasName;
this.outerAliasNames = (outerAliasNames == null) ? Collections.emptySet() : outerAliasNames;
@ -1210,19 +1209,19 @@ public class RbacView {
public static class CaseDef extends ColumnValue {
final Consumer<RbacView> def;
final Consumer<RbacSpec> def;
private CaseDef(final String discriminatorColumnValue, final Consumer<RbacView> def) {
private CaseDef(final String discriminatorColumnValue, final Consumer<RbacSpec> def) {
super(discriminatorColumnValue);
this.def = def;
}
public static CaseDef inCaseOf(final String discriminatorColumnValue, final Consumer<RbacView> def) {
public static CaseDef inCaseOf(final String discriminatorColumnValue, final Consumer<RbacSpec> def) {
return new CaseDef(discriminatorColumnValue, def);
}
public static CaseDef inOtherCases(final Consumer<RbacView> def) {
public static CaseDef inOtherCases(final Consumer<RbacSpec> def) {
return new CaseDef(null, def);
}
@ -1281,7 +1280,7 @@ public class RbacView {
.filter(c -> stream(c.getDeclaredMethods())
.anyMatch(m -> m.getName().equals("rbac") && isStatic(m.getModifiers()))
)
.map(RbacView::castToSubclassOfBaseEntity)
.map(RbacSpec::castToSubclassOfBaseEntity)
.collect(Collectors.toSet());
return rbacEntityClasses;
}
@ -1296,6 +1295,6 @@ public class RbacView {
*/
public static void main(String[] args) throws Exception {
findRbacEntityClasses("net.hostsharing.hsadminng")
.forEach(RbacView::generateRbacView);
.forEach(RbacSpec::generateRbacView);
}
}

View File

@ -1,7 +1,7 @@
package net.hostsharing.hsadminng.rbac.generator;
import lombok.SneakyThrows;
import net.hostsharing.hsadminng.rbac.generator.RbacView.CaseDef;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.CaseDef;
import org.apache.commons.lang3.StringUtils;
import java.nio.file.*;
@ -12,7 +12,7 @@ import java.util.stream.Stream;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.joining;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacGrantDefinition.GrantType.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacGrantDefinition.GrantType.*;
public class RbacViewMermaidFlowchartGenerator {
@ -20,14 +20,14 @@ public class RbacViewMermaidFlowchartGenerator {
public static final String HOSTSHARING_LIGHT_ORANGE = "#feb28c";
public static final String HOSTSHARING_DARK_BLUE = "#274d6e";
public static final String HOSTSHARING_LIGHT_BLUE = "#99bcdb";
private final RbacView rbacDef;
private final RbacSpec rbacDef;
private final List<RbacView.EntityAlias> usedEntityAliases;
private final List<RbacSpec.EntityAlias> usedEntityAliases;
private final CaseDef forCase;
private final StringWriter flowchart = new StringWriter();
public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef, final CaseDef forCase) {
public RbacViewMermaidFlowchartGenerator(final RbacSpec rbacDef, final CaseDef forCase) {
this.rbacDef = rbacDef;
this.forCase = forCase;
@ -37,7 +37,7 @@ public class RbacViewMermaidFlowchartGenerator {
g.getSubRoleDef() != null ? g.getSubRoleDef().getEntityAlias() : null,
g.getPermDef() != null ? g.getPermDef().getEntityAlias() : null))
.filter(Objects::nonNull)
.sorted(comparing(RbacView.EntityAlias::aliasName))
.sorted(comparing(RbacSpec.EntityAlias::aliasName))
.distinct()
.filter(rbacDef::renderInDiagram)
.collect(Collectors.toList());
@ -50,7 +50,7 @@ public class RbacViewMermaidFlowchartGenerator {
renderGrants();
}
public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef) {
public RbacViewMermaidFlowchartGenerator(final RbacSpec rbacDef) {
this(rbacDef, null);
}
private void renderEntitySubgraphs() {
@ -61,7 +61,7 @@ public class RbacViewMermaidFlowchartGenerator {
.forEach(this::renderEntitySubgraph);
}
private void renderEntitySubgraph(final RbacView.EntityAlias entity) {
private void renderEntitySubgraph(final RbacSpec.EntityAlias entity) {
if (!rbacDef.renderInDiagram(entity)) {
return;
}
@ -128,7 +128,7 @@ public class RbacViewMermaidFlowchartGenerator {
renderGrants(PERM_TO_ROLE, "%% granting permissions to roles");
}
private void renderGrants(final RbacView.RbacGrantDefinition.GrantType grantType, final String comment) {
private void renderGrants(final RbacSpec.RbacGrantDefinition.GrantType grantType, final String comment) {
final var grantsOfRequestedType = rbacDef.getGrantDefs().stream()
.filter(g -> g.grantType() == grantType)
.filter(rbacDef::renderInDiagram)
@ -141,7 +141,7 @@ public class RbacViewMermaidFlowchartGenerator {
}
}
private boolean isToBeRenderedForThisCase(final RbacView.RbacGrantDefinition g) {
private boolean isToBeRenderedForThisCase(final RbacSpec.RbacGrantDefinition g) {
if ( g.grantType() == ROLE_TO_USER )
return true;
if ( forCase == null && !g.isConditional() )
@ -150,7 +150,7 @@ public class RbacViewMermaidFlowchartGenerator {
return isToBeRenderedInThisGraph;
}
private String grantDef(final RbacView.RbacGrantDefinition grant) {
private String grantDef(final RbacSpec.RbacGrantDefinition grant) {
final var arrow = (grant.isToCreate() ? " ==>" : " -.->")
+ (grant.isAssumed() ? " " : "|XX| ");
final var grantDef = switch (grant.grantType()) {
@ -164,19 +164,19 @@ public class RbacViewMermaidFlowchartGenerator {
return grantDef;
}
private String permDef(final RbacView.RbacPermissionDefinition perm) {
private String permDef(final RbacSpec.RbacPermissionDefinition perm) {
return permId(perm) + "{{" + perm.getEntityAlias().aliasName() + perm.getPermission() + "}}";
}
private static String permId(final RbacView.RbacPermissionDefinition permDef) {
private static String permId(final RbacSpec.RbacPermissionDefinition permDef) {
return "perm:" + permDef.getEntityAlias().aliasName() + permDef.getPermission();
}
private String roleDef(final RbacView.RbacRoleDefinition roleDef) {
private String roleDef(final RbacSpec.RbacRoleDefinition roleDef) {
return roleId(roleDef) + "[[" + roleDef.getEntityAlias().aliasName() + roleDef.getRole() + "]]";
}
private static String roleId(final RbacView.RbacRoleDefinition r) {
private static String roleId(final RbacSpec.RbacRoleDefinition r) {
return "role:" + r.getEntityAlias().aliasName() + r.getRole();
}

View File

@ -11,11 +11,11 @@ import static net.hostsharing.hsadminng.rbac.generator.StringWriter.with;
public class RbacViewPostgresGenerator {
private final RbacView rbacDef;
private final RbacSpec rbacDef;
private final String liqibaseTagPrefix;
private final StringWriter plPgSql = new StringWriter();
public RbacViewPostgresGenerator(final RbacView forRbacDef) {
public RbacViewPostgresGenerator(final RbacSpec forRbacDef) {
rbacDef = forRbacDef;
liqibaseTagPrefix = rbacDef.getRootEntityAlias().getRawTableNameWithSchema().replace("_", "-").replace(".", "-");
plPgSql.writeLn("""
@ -31,6 +31,7 @@ public class RbacViewPostgresGenerator {
new InsertTriggerGenerator(rbacDef, liqibaseTagPrefix).generateTo(plPgSql);
new RbacIdentityViewGenerator(rbacDef, liqibaseTagPrefix).generateTo(plPgSql);
new RbacRestrictedViewGenerator(rbacDef, liqibaseTagPrefix).generateTo(plPgSql);
new RbacRbacSystemRebuildGenerator(rbacDef, liqibaseTagPrefix).generateTo(plPgSql);
}
@Override

View File

@ -1,8 +1,8 @@
package net.hostsharing.hsadminng.rbac.generator;
import net.hostsharing.hsadminng.rbac.generator.RbacView.CaseDef;
import net.hostsharing.hsadminng.rbac.generator.RbacView.RbacGrantDefinition;
import net.hostsharing.hsadminng.rbac.generator.RbacView.RbacPermissionDefinition;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.CaseDef;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacGrantDefinition;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacPermissionDefinition;
import java.util.HashSet;
import java.util.List;
@ -15,22 +15,22 @@ import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toSet;
import static net.hostsharing.hsadminng.rbac.generator.PostgresTriggerReference.NEW;
import static net.hostsharing.hsadminng.rbac.generator.PostgresTriggerReference.OLD;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacGrantDefinition.GrantType.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacGrantDefinition.GrantType.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.StringWriter.with;
import static org.apache.commons.lang3.StringUtils.capitalize;
class RolesGrantsAndPermissionsGenerator {
private final RbacView rbacDef;
private final RbacSpec rbacDef;
private final Set<RbacGrantDefinition> rbacGrants = new HashSet<>();
private final String liquibaseTagPrefix;
private final String simpleEntityName;
private final String simpleEntityVarName;
private final String qualifiedRawTableName;
RolesGrantsAndPermissionsGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) {
RolesGrantsAndPermissionsGenerator(final RbacSpec rbacDef, final String liquibaseTagPrefix) {
this.rbacDef = rbacDef;
this.rbacGrants.addAll(rbacDef.getGrantDefs().stream()
.filter(RbacGrantDefinition::isToCreate)
@ -95,7 +95,7 @@ class RolesGrantsAndPermissionsGenerator {
private void generateSimplifiedUpdateTriggerFunction(final StringWriter plPgSql) {
final var updateConditions = updatableEntityAliases()
.map(RbacView.EntityAlias::dependsOnColumName)
.map(RbacSpec.EntityAlias::dependsOnColumName)
.distinct()
.map(columnName -> "NEW." + columnName + " is distinct from OLD." + columnName)
.collect(joining( "\n or "));
@ -166,7 +166,7 @@ class RolesGrantsAndPermissionsGenerator {
private boolean hasAnyUpdatableAndNullableEntityAliases() {
return updatableEntityAliases()
.filter(ea -> ea.nullable() == RbacView.Nullable.NULLABLE)
.filter(ea -> ea.nullable() == RbacSpec.Nullable.NULLABLE)
.anyMatch(e -> true);
}
@ -210,7 +210,7 @@ class RolesGrantsAndPermissionsGenerator {
generateGrants(plPgSql, PERM_TO_ROLE);
}
private Stream<RbacView.EntityAlias> referencedEntityAliases() {
private Stream<RbacSpec.EntityAlias> referencedEntityAliases() {
return rbacDef.getEntityAliases().values().stream()
.filter(ea -> !rbacDef.isRootEntityAlias(ea))
.filter(ea -> ea.dependsOnColum() != null)
@ -218,7 +218,7 @@ class RolesGrantsAndPermissionsGenerator {
.filter(ea -> ea.fetchSql() != null);
}
private Stream<RbacView.EntityAlias> updatableEntityAliases() {
private Stream<RbacSpec.EntityAlias> updatableEntityAliases() {
return referencedEntityAliases()
.filter(ea -> rbacDef.getUpdatableColumns().contains(ea.dependsOnColum().column));
}
@ -234,7 +234,7 @@ class RolesGrantsAndPermissionsGenerator {
});
updatableEntityAliases()
.map(RbacView.EntityAlias::dependsOnColum)
.map(RbacSpec.EntityAlias::dependsOnColum)
.map(c -> c.column)
.sorted()
.distinct()
@ -250,18 +250,19 @@ class RolesGrantsAndPermissionsGenerator {
private void generateFetchedVars(
final StringWriter plPgSql,
final RbacView.EntityAlias ea,
final RbacSpec.EntityAlias ea,
final PostgresTriggerReference old) {
plPgSql.writeLn(
ea.fetchSql().sql + " INTO " + entityRefVar(old, ea) + ";",
with("columns", ea.aliasName() + ".*"),
with("ref", old.name()));
if (ea.nullable() == RbacView.Nullable.NOT_NULL) {
if (ea.nullable() == RbacSpec.Nullable.NOT_NULL) {
plPgSql.writeLn(
"assert ${entityRefVar}.uuid is not null, format('${entityRefVar} must not be null for ${REF}.${dependsOnColumn} = %s', ${REF}.${dependsOnColumn});",
"assert ${entityRefVar}.uuid is not null, format('${entityRefVar} must not be null for ${REF}.${dependsOnColumn} = %s of ${rawTable}', ${REF}.${dependsOnColumn});",
with("entityRefVar", entityRefVar(old, ea)),
with("dependsOnColumn", ea.dependsOnColumName()),
with("ref", old.name()));
with("ref", old.name()),
with("rawTable", qualifiedRawTableName));
plPgSql.writeLn();
}
}
@ -352,11 +353,11 @@ class RolesGrantsAndPermissionsGenerator {
.replace("${perm}", permDef.permission.name());
}
private String refVarName(final PostgresTriggerReference ref, final RbacView.EntityAlias entityAlias) {
private String refVarName(final PostgresTriggerReference ref, final RbacSpec.EntityAlias entityAlias) {
return ref.name().toLowerCase() + capitalize(entityAlias.aliasName());
}
private String roleRef(final PostgresTriggerReference rootRefVar, final RbacView.RbacRoleDefinition roleDef) {
private String roleRef(final PostgresTriggerReference rootRefVar, final RbacSpec.RbacRoleDefinition roleDef) {
if (roleDef == null) {
System.out.println("null");
}
@ -369,17 +370,17 @@ class RolesGrantsAndPermissionsGenerator {
private String entityRefVar(
final PostgresTriggerReference rootRefVar,
final RbacView.EntityAlias entityAlias) {
final RbacSpec.EntityAlias entityAlias) {
return rbacDef.isRootEntityAlias(entityAlias)
? rootRefVar.name()
: rootRefVar.name().toLowerCase() + capitalize(entityAlias.aliasName());
}
private void createRolesWithGrantsSql(final StringWriter plPgSql, final RbacView.Role role) {
private void createRolesWithGrantsSql(final StringWriter plPgSql, final RbacSpec.Role role) {
final var isToCreate = rbacDef.getRoleDefs().stream()
.filter(roleDef -> rbacDef.isRootEntityAlias(roleDef.getEntityAlias()) && roleDef.getRole() == role)
.findFirst().map(RbacView.RbacRoleDefinition::isToCreate).orElse(false);
.findFirst().map(RbacSpec.RbacRoleDefinition::isToCreate).orElse(false);
if (!isToCreate) {
return;
}
@ -403,7 +404,7 @@ class RolesGrantsAndPermissionsGenerator {
plPgSql.writeLn(");");
}
private void generateUserGrantsForRole(final StringWriter plPgSql, final RbacView.Role role) {
private void generateUserGrantsForRole(final StringWriter plPgSql, final RbacSpec.Role role) {
final var grantsToUsers = findGrantsToUserForRole(rbacDef.getRootEntityAlias(), role);
if (!grantsToUsers.isEmpty()) {
final var arrayElements = grantsToUsers.stream()
@ -416,13 +417,13 @@ class RolesGrantsAndPermissionsGenerator {
}
}
private void generatePermissionsForRole(final StringWriter plPgSql, final RbacView.Role role) {
private void generatePermissionsForRole(final StringWriter plPgSql, final RbacSpec.Role role) {
final var permissionGrantsForRole = findPermissionsGrantsForRole(rbacDef.getRootEntityAlias(), role);
if (!permissionGrantsForRole.isEmpty()) {
final var arrayElements = permissionGrantsForRole.stream()
.map(RbacGrantDefinition::getPermDef)
.map(RbacPermissionDefinition::getPermission)
.map(RbacView.Permission::name)
.map(RbacSpec.Permission::name)
.map(p -> "'" + p + "'")
.sorted()
.toList();
@ -432,7 +433,7 @@ class RolesGrantsAndPermissionsGenerator {
}
}
private void generateIncomingSuperRolesForRole(final StringWriter plPgSql, final RbacView.Role role) {
private void generateIncomingSuperRolesForRole(final StringWriter plPgSql, final RbacSpec.Role role) {
final var unconditionalIncomingGrants = findIncomingSuperRolesForRole(rbacDef.getRootEntityAlias(), role).stream()
.filter(g -> !g.isConditional())
.toList();
@ -446,7 +447,7 @@ class RolesGrantsAndPermissionsGenerator {
}
}
private void generateOutgoingSubRolesForRole(final StringWriter plPgSql, final RbacView.Role role) {
private void generateOutgoingSubRolesForRole(final StringWriter plPgSql, final RbacSpec.Role role) {
final var unconditionalOutgoingGrants = findOutgoingSuperRolesForRole(rbacDef.getRootEntityAlias(), role).stream()
.filter(g -> !g.isConditional())
.toList();
@ -467,8 +468,8 @@ class RolesGrantsAndPermissionsGenerator {
}
private Set<RbacGrantDefinition> findPermissionsGrantsForRole(
final RbacView.EntityAlias entityAlias,
final RbacView.Role role) {
final RbacSpec.EntityAlias entityAlias,
final RbacSpec.Role role) {
final var roleDef = rbacDef.findRbacRole(entityAlias, role);
return rbacGrants.stream()
.filter(g -> g.grantType() == PERM_TO_ROLE && g.getSuperRoleDef() == roleDef)
@ -476,8 +477,8 @@ class RolesGrantsAndPermissionsGenerator {
}
private Set<RbacGrantDefinition> findGrantsToUserForRole(
final RbacView.EntityAlias entityAlias,
final RbacView.Role role) {
final RbacSpec.EntityAlias entityAlias,
final RbacSpec.Role role) {
final var roleDef = rbacDef.findRbacRole(entityAlias, role);
return rbacGrants.stream()
.filter(g -> g.grantType() == ROLE_TO_USER && g.getSubRoleDef() == roleDef)
@ -485,8 +486,8 @@ class RolesGrantsAndPermissionsGenerator {
}
private Set<RbacGrantDefinition> findIncomingSuperRolesForRole(
final RbacView.EntityAlias entityAlias,
final RbacView.Role role) {
final RbacSpec.EntityAlias entityAlias,
final RbacSpec.Role role) {
final var roleDef = rbacDef.findRbacRole(entityAlias, role);
return rbacGrants.stream()
.filter(g -> g.grantType() == ROLE_TO_ROLE && g.getSubRoleDef() == roleDef)
@ -494,8 +495,8 @@ class RolesGrantsAndPermissionsGenerator {
}
private Set<RbacGrantDefinition> findOutgoingSuperRolesForRole(
final RbacView.EntityAlias entityAlias,
final RbacView.Role role) {
final RbacSpec.EntityAlias entityAlias,
final RbacSpec.Role role) {
final var roleDef = rbacDef.findRbacRole(entityAlias, role);
return rbacGrants.stream()
.filter(g -> g.grantType() == ROLE_TO_ROLE && g.getSuperRoleDef() == roleDef)
@ -579,7 +580,7 @@ class RolesGrantsAndPermissionsGenerator {
plPgSql.writeLn();
}
private String toPlPgSqlReference(final RbacView.RbacSubjectReference userRef) {
private String toPlPgSqlReference(final RbacSpec.RbacSubjectReference userRef) {
return switch (userRef.role) {
case CREATOR -> "rbac.currentSubjectUuid()";
default -> throw new IllegalArgumentException("unknown user role: " + userRef);
@ -588,7 +589,7 @@ class RolesGrantsAndPermissionsGenerator {
private String toPlPgSqlReference(
final PostgresTriggerReference triggerRef,
final RbacView.RbacRoleDefinition roleDef,
final RbacSpec.RbacRoleDefinition roleDef,
final boolean assumed) {
final var assumedArg = assumed ? "" : ", rbac.unassumed()";
return roleDef.descriptorFunctionName() +
@ -599,7 +600,7 @@ class RolesGrantsAndPermissionsGenerator {
private static String toTriggerReference(
final PostgresTriggerReference triggerRef,
final RbacView.EntityAlias entityAlias) {
final RbacSpec.EntityAlias entityAlias) {
return triggerRef.name().toLowerCase() + capitalize(entityAlias.aliasName());
}
}

View File

@ -6,18 +6,18 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import jakarta.persistence.*;
import java.io.IOException;
import java.util.UUID;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.RbacSubjectReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
@Entity
@Table(schema = "rbactest", name = "customer_rv")
@ -41,7 +41,7 @@ public class TestCustomerEntity implements BaseEntity<TestCustomerEntity> {
@Column(name = "adminusername")
private String adminUserName;
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("customer", TestCustomerEntity.class)
.withIdentityView(SQL.projection("prefix"))
.withRestrictedViewOrderBy(SQL.expression("reference"))

View File

@ -5,21 +5,21 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import net.hostsharing.hsadminng.rbac.test.pac.TestPackageEntity;
import jakarta.persistence.*;
import java.io.IOException;
import java.util.UUID;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
@Entity
@Table(schema = "rbactest", name = "domain_rv")
@ -44,7 +44,7 @@ public class TestDomainEntity implements BaseEntity<TestDomainEntity> {
private String description;
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("domain", TestDomainEntity.class)
.withIdentityView(SQL.projection("name"))
.withUpdatableColumns("version", "packageUuid", "description")

View File

@ -5,21 +5,21 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacView;
import net.hostsharing.hsadminng.rbac.generator.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec;
import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL;
import net.hostsharing.hsadminng.rbac.test.cust.TestCustomerEntity;
import jakarta.persistence.*;
import java.io.IOException;
import java.util.UUID;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.*;
import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor;
@Entity
@Table(schema = "rbactest", name = "package_rv")
@ -45,7 +45,7 @@ public class TestPackageEntity implements BaseEntity<TestPackageEntity> {
private String description;
public static RbacView rbac() {
public static RbacSpec rbac() {
return rbacViewFor("package", TestPackageEntity.class)
.withIdentityView(SQL.projection("name"))
.withUpdatableColumns("version", "customerUuid", "description")

View File

@ -178,3 +178,56 @@ call rbac.generateRbacRestrictedView('rbactest.customer',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:rbactest-customer-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table rbactest.customer after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table rbactest.customer', null, <<insert executing global admin user here>>);
-- call rbactest.customer_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `rbactest.customer.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`rbactest.customer.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure rbactest.customer_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row rbactest.customer;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM rbactest.customer LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL rbactest.customer_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -36,7 +36,7 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM rbactest.customer WHERE uuid = NEW.customerUuid INTO newCustomer;
assert newCustomer.uuid is not null, format('newCustomer must not be null for NEW.customerUuid = %s of package', NEW.customerUuid);
assert newCustomer.uuid is not null, format('newCustomer must not be null for NEW.customerUuid = %s of rbactest.package', NEW.customerUuid);
perform rbac.defineRoleWithGrants(
@ -102,10 +102,10 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM rbactest.customer WHERE uuid = OLD.customerUuid INTO oldCustomer;
assert oldCustomer.uuid is not null, format('oldCustomer must not be null for OLD.customerUuid = %s of package', OLD.customerUuid);
assert oldCustomer.uuid is not null, format('oldCustomer must not be null for OLD.customerUuid = %s of rbactest.package', OLD.customerUuid);
SELECT * FROM rbactest.customer WHERE uuid = NEW.customerUuid INTO newCustomer;
assert newCustomer.uuid is not null, format('newCustomer must not be null for NEW.customerUuid = %s of package', NEW.customerUuid);
assert newCustomer.uuid is not null, format('newCustomer must not be null for NEW.customerUuid = %s of rbactest.package', NEW.customerUuid);
if NEW.customerUuid <> OLD.customerUuid then
@ -243,3 +243,56 @@ call rbac.generateRbacRestrictedView('rbactest.package',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:rbactest-package-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table rbactest.package after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table rbactest.package', null, <<insert executing global admin user here>>);
-- call rbactest.package_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `rbactest.package.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`rbactest.package.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure rbactest.package_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row rbactest.package;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM rbactest.package LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL rbactest.package_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -36,7 +36,7 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM rbactest.package WHERE uuid = NEW.packageUuid INTO newPackage;
assert newPackage.uuid is not null, format('newPackage must not be null for NEW.packageUuid = %s of domain', NEW.packageUuid);
assert newPackage.uuid is not null, format('newPackage must not be null for NEW.packageUuid = %s of rbactest.domain', NEW.packageUuid);
perform rbac.defineRoleWithGrants(
@ -98,10 +98,10 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM rbactest.package WHERE uuid = OLD.packageUuid INTO oldPackage;
assert oldPackage.uuid is not null, format('oldPackage must not be null for OLD.packageUuid = %s of domain', OLD.packageUuid);
assert oldPackage.uuid is not null, format('oldPackage must not be null for OLD.packageUuid = %s of rbactest.domain', OLD.packageUuid);
SELECT * FROM rbactest.package WHERE uuid = NEW.packageUuid INTO newPackage;
assert newPackage.uuid is not null, format('newPackage must not be null for NEW.packageUuid = %s of domain', NEW.packageUuid);
assert newPackage.uuid is not null, format('newPackage must not be null for NEW.packageUuid = %s of rbactest.domain', NEW.packageUuid);
if NEW.packageUuid <> OLD.packageUuid then
@ -242,3 +242,56 @@ call rbac.generateRbacRestrictedView('rbactest.domain',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:rbactest-domain-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table rbactest.domain after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table rbactest.domain', null, <<insert executing global admin user here>>);
-- call rbactest.domain_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `rbactest.domain.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`rbactest.domain.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure rbactest.domain_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row rbactest.domain;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM rbactest.domain LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL rbactest.domain_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -102,3 +102,56 @@ call rbac.generateRbacRestrictedView('hs_office.contact',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-contact-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.contact after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.contact', null, <<insert executing global admin user here>>);
-- call hs_office.contact_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.contact.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.contact.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.contact_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.contact;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.contact LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.contact_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -104,3 +104,56 @@ call rbac.generateRbacRestrictedView('hs_office.person',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-person-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.person after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.person', null, <<insert executing global admin user here>>);
-- call hs_office.person_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.person.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.person.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.person_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.person;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.person LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.person_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -38,13 +38,13 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office.person WHERE uuid = NEW.holderUuid INTO newHolderPerson;
assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s of relation', NEW.holderUuid);
assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s of hs_office.relation', NEW.holderUuid);
SELECT * FROM hs_office.person WHERE uuid = NEW.anchorUuid INTO newAnchorPerson;
assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s of relation', NEW.anchorUuid);
assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s of hs_office.relation', NEW.anchorUuid);
SELECT * FROM hs_office.contact WHERE uuid = NEW.contactUuid INTO newContact;
assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s of relation', NEW.contactUuid);
assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s of hs_office.relation', NEW.contactUuid);
perform rbac.defineRoleWithGrants(
@ -252,3 +252,56 @@ call rbac.generateRbacRestrictedView('hs_office.relation',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-relation-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.relation after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.relation', null, <<insert executing global admin user here>>);
-- call hs_office.relation_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.relation.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.relation.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.relation_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.relation;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.relation LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.relation_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -37,10 +37,10 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office.relation WHERE uuid = NEW.partnerRelUuid INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s of partner', NEW.partnerRelUuid);
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s of hs_office.partner', NEW.partnerRelUuid);
SELECT * FROM hs_office.partner_details WHERE uuid = NEW.detailsUuid INTO newPartnerDetails;
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s of partner', NEW.detailsUuid);
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s of hs_office.partner', NEW.detailsUuid);
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'DELETE'), hs_office.relation_OWNER(newPartnerRel));
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'SELECT'), hs_office.relation_TENANT(newPartnerRel));
@ -96,16 +96,16 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office.relation WHERE uuid = OLD.partnerRelUuid INTO oldPartnerRel;
assert oldPartnerRel.uuid is not null, format('oldPartnerRel must not be null for OLD.partnerRelUuid = %s of partner', OLD.partnerRelUuid);
assert oldPartnerRel.uuid is not null, format('oldPartnerRel must not be null for OLD.partnerRelUuid = %s of hs_office.partner', OLD.partnerRelUuid);
SELECT * FROM hs_office.relation WHERE uuid = NEW.partnerRelUuid INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s of partner', NEW.partnerRelUuid);
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s of hs_office.partner', NEW.partnerRelUuid);
SELECT * FROM hs_office.partner_details WHERE uuid = OLD.detailsUuid INTO oldPartnerDetails;
assert oldPartnerDetails.uuid is not null, format('oldPartnerDetails must not be null for OLD.detailsUuid = %s of partner', OLD.detailsUuid);
assert oldPartnerDetails.uuid is not null, format('oldPartnerDetails must not be null for OLD.detailsUuid = %s of hs_office.partner', OLD.detailsUuid);
SELECT * FROM hs_office.partner_details WHERE uuid = NEW.detailsUuid INTO newPartnerDetails;
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s of partner', NEW.detailsUuid);
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s of hs_office.partner', NEW.detailsUuid);
if NEW.partnerRelUuid <> OLD.partnerRelUuid then
@ -253,3 +253,56 @@ call rbac.generateRbacRestrictedView('hs_office.partner',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-partner-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.partner after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.partner', null, <<insert executing global admin user here>>);
-- call hs_office.partner_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.partner.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.partner.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.partner_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.partner;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.partner LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.partner_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -165,3 +165,56 @@ call rbac.generateRbacRestrictedView('hs_office.partner_details',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-partner-details-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.partner_details after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.partner_details', null, <<insert executing global admin user here>>);
-- call hs_office.partner_details_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.partner_details.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.partner_details.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.partner_details_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.partner_details;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.partner_details LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.partner_details_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -101,3 +101,56 @@ call rbac.generateRbacRestrictedView('hs_office.bankaccount',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-bankaccount-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.bankaccount after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.bankaccount', null, <<insert executing global admin user here>>);
-- call hs_office.bankaccount_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.bankaccount.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.bankaccount.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.bankaccount_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.bankaccount;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.bankaccount LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.bankaccount_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -44,10 +44,10 @@ begin
WHERE partnerRel.type = 'PARTNER'
AND NEW.debitorRelUuid = debitorRel.uuid
INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.debitorRelUuid = %s of debitor', NEW.debitorRelUuid);
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.debitorRelUuid = %s of hs_office.debitor', NEW.debitorRelUuid);
SELECT * FROM hs_office.relation WHERE uuid = NEW.debitorRelUuid INTO newDebitorRel;
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorRelUuid = %s of debitor', NEW.debitorRelUuid);
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorRelUuid = %s of hs_office.debitor', NEW.debitorRelUuid);
SELECT * FROM hs_office.bankaccount WHERE uuid = NEW.refundBankAccountUuid INTO newRefundBankAccount;
@ -242,3 +242,56 @@ call rbac.generateRbacRestrictedView('hs_office.debitor',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-debitor-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.debitor after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.debitor', null, <<insert executing global admin user here>>);
-- call hs_office.debitor_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.debitor.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.debitor.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.debitor_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.debitor;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.debitor LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.debitor_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -37,14 +37,14 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office.bankaccount WHERE uuid = NEW.bankAccountUuid INTO newBankAccount;
assert newBankAccount.uuid is not null, format('newBankAccount must not be null for NEW.bankAccountUuid = %s of sepamandate', NEW.bankAccountUuid);
assert newBankAccount.uuid is not null, format('newBankAccount must not be null for NEW.bankAccountUuid = %s of hs_office.sepamandate', NEW.bankAccountUuid);
SELECT debitorRel.*
FROM hs_office.relation debitorRel
JOIN hs_office.debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
WHERE debitor.uuid = NEW.debitorUuid
INTO newDebitorRel;
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorUuid = %s of sepamandate', NEW.debitorUuid);
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorUuid = %s of hs_office.sepamandate', NEW.debitorUuid);
perform rbac.defineRoleWithGrants(
@ -211,3 +211,56 @@ call rbac.generateRbacRestrictedView('hs_office.sepamandate',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-sepamandate-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.sepamandate after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.sepamandate', null, <<insert executing global admin user here>>);
-- call hs_office.sepamandate_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.sepamandate.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.sepamandate.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.sepamandate_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.sepamandate;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.sepamandate LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.sepamandate_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -40,7 +40,7 @@ begin
JOIN hs_office.relation AS partnerRel ON partnerRel.uuid = partner.partnerRelUuid
WHERE partner.uuid = NEW.partnerUuid
INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerUuid = %s of membership', NEW.partnerUuid);
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerUuid = %s of hs_office.membership', NEW.partnerUuid);
perform rbac.defineRoleWithGrants(
@ -193,3 +193,56 @@ call rbac.generateRbacRestrictedView('hs_office.membership',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-membership-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.membership after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.membership', null, <<insert executing global admin user here>>);
-- call hs_office.membership_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.membership.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.membership.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.membership_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.membership;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.membership LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.membership_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -36,7 +36,7 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office.membership WHERE uuid = NEW.membershipUuid INTO newMembership;
assert newMembership.uuid is not null, format('newMembership must not be null for NEW.membershipUuid = %s of coopshares', NEW.membershipUuid);
assert newMembership.uuid is not null, format('newMembership must not be null for NEW.membershipUuid = %s of hs_office.coopsharetx', NEW.membershipUuid);
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'SELECT'), hs_office.membership_AGENT(newMembership));
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'UPDATE'), hs_office.membership_ADMIN(newMembership));
@ -164,3 +164,56 @@ call rbac.generateRbacRestrictedView('hs_office.coopsharetx',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-coopsharetx-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.coopsharetx after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.coopsharetx', null, <<insert executing global admin user here>>);
-- call hs_office.coopsharetx_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.coopsharetx.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.coopsharetx.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.coopsharetx_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.coopsharetx;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.coopsharetx LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.coopsharetx_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -36,7 +36,7 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office.membership WHERE uuid = NEW.membershipUuid INTO newMembership;
assert newMembership.uuid is not null, format('newMembership must not be null for NEW.membershipUuid = %s of coopasset', NEW.membershipUuid);
assert newMembership.uuid is not null, format('newMembership must not be null for NEW.membershipUuid = %s of hs_office.coopassettx', NEW.membershipUuid);
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'SELECT'), hs_office.membership_AGENT(newMembership));
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'UPDATE'), hs_office.membership_ADMIN(newMembership));
@ -164,3 +164,56 @@ call rbac.generateRbacRestrictedView('hs_office.coopassettx',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-office-coopassettx-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_office.coopassettx after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_office.coopassettx', null, <<insert executing global admin user here>>);
-- call hs_office.coopassettx_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_office.coopassettx.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_office.coopassettx.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_office.coopassettx_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_office.coopassettx;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_office.coopassettx LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_office.coopassettx_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -37,14 +37,14 @@ begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office.debitor WHERE uuid = NEW.debitorUuid INTO newDebitor;
assert newDebitor.uuid is not null, format('newDebitor must not be null for NEW.debitorUuid = %s of project', NEW.debitorUuid);
assert newDebitor.uuid is not null, format('newDebitor must not be null for NEW.debitorUuid = %s of hs_booking.project', NEW.debitorUuid);
SELECT debitorRel.*
FROM hs_office.relation debitorRel
JOIN hs_office.debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
WHERE debitor.uuid = NEW.debitorUuid
INTO newDebitorRel;
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorUuid = %s or project', NEW.debitorUuid);
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorUuid = %s of hs_booking.project', NEW.debitorUuid);
perform rbac.defineRoleWithGrants(
@ -204,3 +204,56 @@ call rbac.generateRbacRestrictedView('hs_booking.project',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-booking-project-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_booking.project after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_booking.project', null, <<insert executing global admin user here>>);
-- call hs_booking.project_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_booking.project.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_booking.project.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_booking.project_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_booking.project;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_booking.project LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_booking.project_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -275,3 +275,56 @@ call rbac.generateRbacRestrictedView('hs_booking.item',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-booking-item-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_booking.item after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_booking.item', null, <<insert executing global admin user here>>);
-- call hs_booking.item_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_booking.item.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_booking.item.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_booking.item_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_booking.item;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_booking.item LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_booking.item_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -181,3 +181,56 @@ call rbac.generateRbacRestrictedView('hs_hosting.asset',
$updates$);
--//
-- ============================================================================
--changeset RbacRbacSystemRebuildGenerator:hs-hosting-asset-rbac-rebuild endDelimiter:--//
-- ----------------------------------------------------------------------------
-- HOWTO: Rebuild RBAC-system for table hs_hosting.asset after changing its RBAC specification.
--
-- begin transaction;
-- call base.defineContext('re-creating RBAC for table hs_hosting.asset', null, <<insert executing global admin user here>>);
-- call hs_hosting.asset_rebuild_rbac_system();
-- commit;
--
-- How it works:
-- 1. All grants previously created from the RBAC specification of this table will be deleted.
-- These grants are identified by `hs_hosting.asset.grantedByTriggerOf IS NOT NULL`.
-- User-induced grants (`hs_hosting.asset.grantedByTriggerOf IS NULL`) are NOT deleted.
-- 2. New role types will be created, but existing role types which are not specified anymore,
-- will NOT be deleted!
-- 3. All newly specified grants will be created.
--
-- IMPORTANT:
-- Make sure not to skip any previously defined role-types or you might break indirect grants!
-- E.g. If, in an updated version of the RBAC system for a table, you remove the AGENT role type
-- and now directly grant the TENANT role to the ADMIN role, all external grants to the AGENT role
-- of this table would be in a dead end.
create or replace procedure hs_hosting.asset_rebuild_rbac_system()
language plpgsql as $$
DECLARE
DECLARE
row hs_hosting.asset;
grantsAfter numeric;
grantsBefore numeric;
BEGIN
SELECT count(*) INTO grantsBefore FROM rbac.grants;
FOR row IN SELECT * FROM hs_hosting.asset LOOP
-- first delete all generated grants for this row from the previously defined RBAC system
DELETE FROM rbac.grants g
WHERE g.grantedbytriggerof = row.uuid;
-- then build the grants according to the currently defined RBAC rules
CALL hs_hosting.asset_build_rbac_system(row);
END LOOP;
select count(*) into grantsAfter from rbac.grants;
-- print how the total count of grants has changed
raise notice 'total grant count before -> after: % -> %', grantsBefore, grantsAfter;
END;
$$;
--//

View File

@ -290,6 +290,32 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
}
}
@Nested
class RebuildRbacSystem {
@Test
public void rebuildingTheRbacSystemWitSameRbacSpecDoesNotChangeGrantNorRoleCount() {
final var grantCountBefore = sql("SELECT COUNT(*) FROM rbac.grants");
final var roleCountBefore = sql("SELECT COUNT(*) FROM rbac.role");
jpaAttempt.transacted(() ->
em.createNativeQuery("CALL rbactest.package_rebuild_rbac_system()")
);
final var grantCountAfter = sql("SELECT COUNT(*) FROM rbac.grants");
assertThat(grantCountBefore).as("grant count must not change").isEqualTo(grantCountAfter);
final var roleCountAfter = sql("SELECT COUNT(*) FROM rbac.role");
assertThat(roleCountBefore).as("role count must not change").isEqualTo(roleCountAfter);
}
private Object sql(final String query) {
return jpaAttempt.transacted(() ->
em.createNativeQuery(query).getSingleResult()
).assumeSuccessful().returnedValue();
}
}
private RbacSubjectEntity createNewUserTransacted() {
return jpaAttempt.transacted(() -> {
final var newUserName = "test-user-" + System.currentTimeMillis() + "@example.com";