cleanup-todos (#31)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: #31
Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
Michael Hoennig 2024-04-02 13:14:46 +02:00
parent 277369a960
commit ad04faa21d
32 changed files with 108 additions and 150 deletions

1
.gitignore vendored
View File

@ -4,7 +4,6 @@
/build/www/** /build/www/**
/src/test/javascript/coverage/ /src/test/javascript/coverage/
/worktrees/ /worktrees/
TODO-progress.png
###################### ######################
# Node # Node

View File

@ -380,12 +380,6 @@ You can explore the prototype as follows:
`src/` `src/`
The actual source-code, see [Source Code Package Structure](#source-code-package-structure) for details. The actual source-code, see [Source Code Package Structure](#source-code-package-structure) for details.
`TODO.md`
Requirements of initial project. Do not touch!
`TODO-progress.png`
Generated diagram image of the project progress.
`tools/` `tools/`
Some shell-scripts to useful tasks. Some shell-scripts to useful tasks.
@ -765,5 +759,4 @@ The output will list the generated files.
## Further Documentation ## Further Documentation
- the `doc` directory contains architecture concepts and a glossary - the `doc` directory contains architecture concepts and a glossary
- TODO.md tracks requirements and progress for the contract of the initial project, - the `ideas` directory contains unstructured ideas for future development or documentation
please do not amend anything in this document

View File

@ -87,7 +87,7 @@ Acceptance-Tests run on a fully integrated and deployed system with deployed dou
Acceptance-tests, are blackbox-tests and do <u>not</u> count into test-code-coverage. Acceptance-tests, are blackbox-tests and do <u>not</u> count into test-code-coverage.
TODO: Complete the Acceptance-Tests test concept. TODO.test: Complete the Acceptance-Tests test concept.
#### Performance-Tests #### Performance-Tests
@ -107,4 +107,4 @@ We define System-Integration-Tests as test in which this system is deployed in a
System-Integration-tests, are blackbox-tests and do <u>not</u> count into test-code-coverage. System-Integration-tests, are blackbox-tests and do <u>not</u> count into test-code-coverage.
TODO: Complete the System-Integration-Tests test concept. TODO.test: Complete the System-Integration-Tests test concept.

View File

@ -18,8 +18,8 @@ CREATE OR REPLACE FUNCTION historicize()
RETURNS trigger RETURNS trigger
LANGUAGE plpgsql STRICT AS $$ LANGUAGE plpgsql STRICT AS $$
DECLARE DECLARE
currentUser VARCHAR(64); currentUser VARCHAR(63);
currentTask varchar; currentTask VARCHAR(127);
"row" RECORD; "row" RECORD;
"alive" BOOLEAN; "alive" BOOLEAN;
"sql" varchar; "sql" varchar;
@ -37,10 +37,10 @@ END IF;
-- determine task -- determine task
currentTask = current_setting('hsadminng.currentTask'); currentTask = current_setting('hsadminng.currentTask');
IF (currentTask IS NULL OR length(currentTask) < 12) THEN assert currentTask IS NOT NULL AND length(currentTask) >= 12,
RAISE EXCEPTION 'hsadminng.currentTask (%) must be defined and min 12 characters long, please use "SET LOCAL ...;"', currentTask; format('hsadminng.currentTask (%s) must be defined and min 12 characters long, please use "SET LOCAL ...;"', currentTask);
END IF; assert length(currentTask) <= 127,
RAISE NOTICE 'currentTask: %', currentTask; format('hsadminng.currentTask (%s) must not be longer than 127 characters"', currentTask);
IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN
"row" := NEW; "row" := NEW;

View File

@ -55,16 +55,15 @@ public class Context {
final String currentRequest, final String currentRequest,
final String currentUser, final String currentUser,
final String assumedRoles) { final String assumedRoles) {
final var query = em.createNativeQuery( final var query = em.createNativeQuery("""
"""
call defineContext( call defineContext(
cast(:currentTask as varchar), cast(:currentTask as varchar(127)),
cast(:currentRequest as varchar), cast(:currentRequest as text),
cast(:currentUser as varchar), cast(:currentUser as varchar(63)),
cast(:assumedRoles as varchar)); cast(:assumedRoles as varchar(1023)));
"""); """);
query.setParameter("currentTask", shortenToMaxLength(currentTask, 96)); query.setParameter("currentTask", shortenToMaxLength(currentTask, 127));
query.setParameter("currentRequest", shortenToMaxLength(currentRequest, 512)); // TODO.spec: length? query.setParameter("currentRequest", currentRequest);
query.setParameter("currentUser", currentUser); query.setParameter("currentUser", currentUser);
query.setParameter("assumedRoles", assumedRoles != null ? assumedRoles : ""); query.setParameter("assumedRoles", assumedRoles != null ? assumedRoles : "");
query.executeUpdate(); query.executeUpdate();

View File

@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.bankaccount;
import lombok.*; import lombok.*;
import lombok.experimental.FieldNameConstants; import lombok.experimental.FieldNameConstants;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable; import net.hostsharing.hsadminng.stringify.Stringifyable;
@ -30,7 +30,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@AllArgsConstructor @AllArgsConstructor
@FieldNameConstants @FieldNameConstants
@DisplayName("BankAccount") @DisplayName("BankAccount")
public class HsOfficeBankAccountEntity implements HasUuid, Stringifyable { public class HsOfficeBankAccountEntity implements RbacObject, Stringifyable {
private static Stringify<HsOfficeBankAccountEntity> toString = stringify(HsOfficeBankAccountEntity.class, "bankAccount") private static Stringify<HsOfficeBankAccountEntity> toString = stringify(HsOfficeBankAccountEntity.class, "bankAccount")
.withIdProp(HsOfficeBankAccountEntity::getIban) .withIdProp(HsOfficeBankAccountEntity::getIban)

View File

@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.contact;
import lombok.*; import lombok.*;
import lombok.experimental.FieldNameConstants; import lombok.experimental.FieldNameConstants;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
@ -30,7 +30,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@AllArgsConstructor @AllArgsConstructor
@FieldNameConstants @FieldNameConstants
@DisplayName("Contact") @DisplayName("Contact")
public class HsOfficeContactEntity implements Stringifyable, HasUuid { public class HsOfficeContactEntity implements Stringifyable, RbacObject {
private static Stringify<HsOfficeContactEntity> toString = stringify(HsOfficeContactEntity.class, "contact") private static Stringify<HsOfficeContactEntity> toString = stringify(HsOfficeContactEntity.class, "contact")
.withProp(Fields.label, HsOfficeContactEntity::getLabel) .withProp(Fields.label, HsOfficeContactEntity::getLabel)
@ -43,13 +43,13 @@ public class HsOfficeContactEntity implements Stringifyable, HasUuid {
private String label; private String label;
@Column(name = "postaladdress") @Column(name = "postaladdress")
private String postalAddress; // TODO: check if we really want multiple, if so: JSON-Array or Postgres-Array? private String postalAddress; // TODO.spec: check if we really want multiple, if so: JSON-Array or Postgres-Array?
@Column(name = "emailaddresses", columnDefinition = "json") @Column(name = "emailaddresses", columnDefinition = "json")
private String emailAddresses; // TODO: check if we can really add multiple. format: ["eins@...", "zwei@..."] private String emailAddresses; // TODO.spec: check if we can really add multiple. format: ["eins@...", "zwei@..."]
@Column(name = "phonenumbers", columnDefinition = "json") @Column(name = "phonenumbers", columnDefinition = "json")
private String phoneNumbers; // TODO: check if we can really add multiple. format: { "office": "+49 40 12345-10", "fax": "+49 40 12345-05" } private String phoneNumbers; // TODO.spec: check if we can really add multiple. format: { "office": "+49 40 12345-10", "fax": "+49 40 12345-05" }
@Override @Override
public String toString() { public String toString() {

View File

@ -8,7 +8,8 @@ import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable; import net.hostsharing.hsadminng.stringify.Stringifyable;
@ -25,6 +26,7 @@ import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import java.io.IOException; import java.io.IOException;
import java.io.IOException; import java.io.IOException;
import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Optional; import java.util.Optional;
@ -50,7 +52,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@DisplayName("CoopAssetsTransaction") @DisplayName("CoopAssetsTransaction")
public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, HasUuid { public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, RbacObject {
private static Stringify<HsOfficeCoopAssetsTransactionEntity> stringify = stringify(HsOfficeCoopAssetsTransactionEntity.class) private static Stringify<HsOfficeCoopAssetsTransactionEntity> stringify = stringify(HsOfficeCoopAssetsTransactionEntity.class)
.withIdProp(HsOfficeCoopAssetsTransactionEntity::getTaggedMemberNumber) .withIdProp(HsOfficeCoopAssetsTransactionEntity::getTaggedMemberNumber)

View File

@ -7,7 +7,9 @@ import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
@ -23,7 +25,6 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import java.io.IOException; import java.io.IOException;
import java.io.IOException;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.UUID; import java.util.UUID;
@ -47,7 +48,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@DisplayName("CoopShareTransaction") @DisplayName("CoopShareTransaction")
public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, HasUuid { public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, RbacObject {
private static Stringify<HsOfficeCoopSharesTransactionEntity> stringify = stringify(HsOfficeCoopSharesTransactionEntity.class) private static Stringify<HsOfficeCoopSharesTransactionEntity> stringify = stringify(HsOfficeCoopSharesTransactionEntity.class)
.withProp(HsOfficeCoopSharesTransactionEntity::getMemberNumberTagged) .withProp(HsOfficeCoopSharesTransactionEntity::getMemberNumberTagged)

View File

@ -5,7 +5,7 @@ import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
@ -43,7 +43,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@DisplayName("Debitor") @DisplayName("Debitor")
public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { public class HsOfficeDebitorEntity implements RbacObject, Stringifyable {
public static final String DEBITOR_NUMBER_TAG = "D-"; public static final String DEBITOR_NUMBER_TAG = "D-";
public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$"; public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$";
@ -153,7 +153,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
"vatCountryCode", "vatCountryCode",
"vatBusiness", "vatBusiness",
"vatReverseCharge", "vatReverseCharge",
"defaultPrefix" /* TODO: do we want that updatable? */) "defaultPrefix" /* TODO.spec: do we want that updatable? */)
.toRole("global", ADMIN).grantPermission(INSERT) .toRole("global", ADMIN).grantPermission(INSERT)
.importRootEntityAliasProxy("debitorRel", HsOfficeRelationEntity.class, .importRootEntityAliasProxy("debitorRel", HsOfficeRelationEntity.class,

View File

@ -5,7 +5,7 @@ import com.vladmihalcea.hibernate.type.range.Range;
import lombok.*; import lombok.*;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
@ -30,6 +30,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.OWNER; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.OWNER;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.fetchedBySql; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.fetchedBySql;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.stringify.Stringify.stringify; import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@ -42,7 +43,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@DisplayName("Membership") @DisplayName("Membership")
public class HsOfficeMembershipEntity implements HasUuid, Stringifyable { public class HsOfficeMembershipEntity implements RbacObject, Stringifyable {
public static final String MEMBER_NUMBER_TAG = "M-"; public static final String MEMBER_NUMBER_TAG = "M-";
public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$"; public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$";

View File

@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.hs.office.partner;
import lombok.*; import lombok.*;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@DisplayName("PartnerDetails") @DisplayName("PartnerDetails")
public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable { public class HsOfficePartnerDetailsEntity implements RbacObject, Stringifyable {
private static Stringify<HsOfficePartnerDetailsEntity> stringify = stringify( private static Stringify<HsOfficePartnerDetailsEntity> stringify = stringify(
HsOfficePartnerDetailsEntity.class, HsOfficePartnerDetailsEntity.class,

View File

@ -8,7 +8,7 @@ import lombok.Setter;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
@ -45,7 +45,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@DisplayName("Partner") @DisplayName("Partner")
public class HsOfficePartnerEntity implements Stringifyable, HasUuid { public class HsOfficePartnerEntity implements Stringifyable, RbacObject {
public static final String PARTNER_NUMBER_TAG = "P-"; public static final String PARTNER_NUMBER_TAG = "P-";

View File

@ -11,7 +11,7 @@ public interface HsOfficePartnerRepository extends Repository<HsOfficePartnerEnt
Optional<HsOfficePartnerEntity> findByUuid(UUID id); Optional<HsOfficePartnerEntity> findByUuid(UUID id);
List<HsOfficePartnerEntity> findAll(); // TODO: move to a repo in test sources List<HsOfficePartnerEntity> findAll(); // TODO.impl: move to a repo in test sources
@Query(""" @Query("""
SELECT partner FROM HsOfficePartnerEntity partner SELECT partner FROM HsOfficePartnerEntity partner

View File

@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.person;
import lombok.*; import lombok.*;
import lombok.experimental.FieldNameConstants; import lombok.experimental.FieldNameConstants;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
@ -30,7 +30,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@AllArgsConstructor @AllArgsConstructor
@FieldNameConstants @FieldNameConstants
@DisplayName("Person") @DisplayName("Person")
public class HsOfficePersonEntity implements HasUuid, Stringifyable { public class HsOfficePersonEntity implements RbacObject, Stringifyable {
private static Stringify<HsOfficePersonEntity> toString = stringify(HsOfficePersonEntity.class, "person") private static Stringify<HsOfficePersonEntity> toString = stringify(HsOfficePersonEntity.class, "person")
.withProp(Fields.personType, HsOfficePersonEntity::getPersonType) .withProp(Fields.personType, HsOfficePersonEntity::getPersonType)

View File

@ -4,7 +4,7 @@ import lombok.*;
import lombok.experimental.FieldNameConstants; import lombok.experimental.FieldNameConstants;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
@ -32,7 +32,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@FieldNameConstants @FieldNameConstants
public class HsOfficeRelationEntity implements HasUuid, Stringifyable { public class HsOfficeRelationEntity implements RbacObject, Stringifyable {
private static Stringify<HsOfficeRelationEntity> toString = stringify(HsOfficeRelationEntity.class, "rel") private static Stringify<HsOfficeRelationEntity> toString = stringify(HsOfficeRelationEntity.class, "rel")
.withProp(Fields.anchor, HsOfficeRelationEntity::getAnchor) .withProp(Fields.anchor, HsOfficeRelationEntity::getAnchor)

View File

@ -7,7 +7,7 @@ import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable; import net.hostsharing.hsadminng.stringify.Stringifyable;
@ -37,7 +37,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@DisplayName("SEPA-Mandate") @DisplayName("SEPA-Mandate")
public class HsOfficeSepaMandateEntity implements Stringifyable, HasUuid { public class HsOfficeSepaMandateEntity implements Stringifyable, RbacObject {
private static Stringify<HsOfficeSepaMandateEntity> stringify = stringify(HsOfficeSepaMandateEntity.class) private static Stringify<HsOfficeSepaMandateEntity> stringify = stringify(HsOfficeSepaMandateEntity.class)
.withProp(e -> e.getBankAccount().getIban()) .withProp(e -> e.getBankAccount().getIban())

View File

@ -1,7 +0,0 @@
package net.hostsharing.hsadminng.persistence;
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
// TODO: remove this interface, I just wanted to avoid to many changes in that PR
public interface HasUuid extends RbacObject {
}

View File

@ -13,7 +13,7 @@ import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity; import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.test.cust.TestCustomerEntity; import net.hostsharing.hsadminng.test.cust.TestCustomerEntity;
import net.hostsharing.hsadminng.test.dom.TestDomainEntity; import net.hostsharing.hsadminng.test.dom.TestDomainEntity;
@ -277,7 +277,7 @@ public class RbacView {
*/ */
public <EC extends RbacObject> RbacView importRootEntityAliasProxy( public <EC extends RbacObject> RbacView importRootEntityAliasProxy(
final String aliasName, final String aliasName,
final Class<? extends HasUuid> entityClass, final Class<? extends RbacObject> entityClass,
final SQL fetchSql, final SQL fetchSql,
final Column dependsOnColum) { final Column dependsOnColum) {
if (rootEntityAliasProxy != null) { if (rootEntityAliasProxy != null) {
@ -300,7 +300,7 @@ public class RbacView {
* a JPA entity class extending RbacObject * a JPA entity class extending RbacObject
*/ */
public RbacView importSubEntityAlias( public RbacView importSubEntityAlias(
final String aliasName, final Class<? extends HasUuid> entityClass, final String aliasName, final Class<? extends RbacObject> entityClass,
final SQL fetchSql, final Column dependsOnColum) { final SQL fetchSql, final Column dependsOnColum) {
importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, true, NOT_NULL); importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, true, NOT_NULL);
return this; return this;
@ -334,7 +334,7 @@ public class RbacView {
* a JPA entity class extending RbacObject * a JPA entity class extending RbacObject
*/ */
public RbacView importEntityAlias( public RbacView importEntityAlias(
final String aliasName, final Class<? extends HasUuid> entityClass, final String aliasName, final Class<? extends RbacObject> entityClass,
final Column dependsOnColum, final SQL fetchSql, final Nullable nullable) { final Column dependsOnColum, final SQL fetchSql, final Nullable nullable) {
importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, false, nullable); importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, false, nullable);
return this; return this;
@ -342,14 +342,14 @@ public class RbacView {
// TODO: remove once it's not used in HsOffice...Entity anymore // TODO: remove once it's not used in HsOffice...Entity anymore
public RbacView importEntityAlias( public RbacView importEntityAlias(
final String aliasName, final Class<? extends HasUuid> entityClass, final String aliasName, final Class<? extends RbacObject> entityClass,
final Column dependsOnColum) { final Column dependsOnColum) {
importEntityAliasImpl(aliasName, entityClass, directlyFetchedByDependsOnColumn(), dependsOnColum, false, null); importEntityAliasImpl(aliasName, entityClass, directlyFetchedByDependsOnColumn(), dependsOnColum, false, null);
return this; return this;
} }
private EntityAlias importEntityAliasImpl( private EntityAlias importEntityAliasImpl(
final String aliasName, final Class<? extends HasUuid> entityClass, final String aliasName, final Class<? extends RbacObject> entityClass,
final SQL fetchSql, final Column dependsOnColum, boolean asSubEntity, final Nullable nullable) { final SQL fetchSql, final Column dependsOnColum, boolean asSubEntity, final Nullable nullable) {
final var entityAlias = new EntityAlias(aliasName, entityClass, fetchSql, dependsOnColum, asSubEntity, nullable); final var entityAlias = new EntityAlias(aliasName, entityClass, fetchSql, dependsOnColum, asSubEntity, nullable);
entityAliases.put(aliasName, entityAlias); entityAliases.put(aliasName, entityAlias);
@ -1046,7 +1046,7 @@ public class RbacView {
} }
} }
private static void generateRbacView(final Class<? extends HasUuid> c) { private static void generateRbacView(final Class<? extends RbacObject> c) {
final Method mainMethod = stream(c.getMethods()).filter( final Method mainMethod = stream(c.getMethods()).filter(
m -> isStatic(m.getModifiers()) && m.getName().equals("main") m -> isStatic(m.getModifiers()) && m.getName().equals("main")
) )

View File

@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
@ -24,7 +24,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
@Setter @Setter
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class TestCustomerEntity implements HasUuid { public class TestCustomerEntity implements RbacObject {
@Id @Id
@GeneratedValue @GeneratedValue

View File

@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.test.pac.TestPackageEntity; import net.hostsharing.hsadminng.test.pac.TestPackageEntity;
@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
@Setter @Setter
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class TestDomainEntity implements HasUuid { public class TestDomainEntity implements RbacObject {
@Id @Id
@GeneratedValue @GeneratedValue

View File

@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.test.cust.TestCustomerEntity; import net.hostsharing.hsadminng.test.cust.TestCustomerEntity;
@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
@Setter @Setter
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class TestPackageEntity implements HasUuid { public class TestPackageEntity implements RbacObject {
@Id @Id
@GeneratedValue @GeneratedValue

View File

@ -23,7 +23,7 @@ components:
- ADMIN - ADMIN
- AGENT - AGENT
- TENANT - TENANT
- GUEST
- REFERRER - REFERRER
- GUEST
roleName: roleName:
type: string type: string

View File

@ -10,10 +10,10 @@
This function will be overwritten by later changesets. This function will be overwritten by later changesets.
*/ */
create procedure contextDefined( create procedure contextDefined(
currentTask varchar, currentTask varchar(127),
currentRequest varchar, currentRequest text,
currentUser varchar, currentUser varchar(63),
assumedRoles varchar assumedRoles varchar(1023)
) )
language plpgsql as $$ language plpgsql as $$
begin begin

View File

@ -85,10 +85,10 @@ end; $$;
This function will be overwritten by later changesets. This function will be overwritten by later changesets.
*/ */
create or replace procedure contextDefined( create or replace procedure contextDefined(
currentTask varchar, currentTask varchar(127),
currentRequest varchar, currentRequest text,
currentUser varchar, currentUser varchar(63),
assumedRoles varchar assumedRoles varchar(1023)
) )
language plpgsql as $$ language plpgsql as $$
declare declare

View File

@ -1,18 +1,5 @@
--liquibase formatted sql --liquibase formatted sql
-- ============================================================================
-- PERMISSIONS
--changeset rbac-role-builder-to-uuids:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create or replace function toPermissionUuids(forObjectUuid uuid, permitOps RbacOp[])
returns uuid[]
language plpgsql
strict as $$
begin
return createPermissions(forObjectUuid, permitOps);
end; $$;
-- ================================================================= -- =================================================================
-- CREATE ROLE -- CREATE ROLE
@ -32,6 +19,8 @@ create or replace function createRoleWithGrants(
language plpgsql as $$ language plpgsql as $$
declare declare
roleUuid uuid; roleUuid uuid;
permission RbacOp;
permissionUuid uuid;
subRoleDesc RbacRoleDescriptor; subRoleDesc RbacRoleDescriptor;
superRoleDesc RbacRoleDescriptor; superRoleDesc RbacRoleDescriptor;
subRoleUuid uuid; subRoleUuid uuid;
@ -41,9 +30,11 @@ declare
begin begin
roleUuid := createRole(roleDescriptor); roleUuid := createRole(roleDescriptor);
if cardinality(permissions) > 0 then foreach permission in array permissions
call grantPermissionsToRole(roleUuid, toPermissionUuids(roleDescriptor.objectuuid, permissions)); loop
end if; permissionUuid := createPermission(roleDescriptor.objectuuid, permission);
call grantPermissionToRole(permissionUuid, roleUuid);
end loop;
foreach superRoleDesc in array array_remove(incomingSuperRoles, null) foreach superRoleDesc in array array_remove(incomingSuperRoles, null)
loop loop
@ -60,7 +51,7 @@ begin
if cardinality(userUuids) > 0 then if cardinality(userUuids) > 0 then
-- direct grants to users need a grantedByRole which can revoke the grant -- direct grants to users need a grantedByRole which can revoke the grant
if grantedByRole is null then if grantedByRole is null then
userGrantsByRoleUuid := roleUuid; -- TODO: or do we want to require an explicit userGrantsByRoleUuid? userGrantsByRoleUuid := roleUuid; -- TODO.spec: or do we want to require an explicit userGrantsByRoleUuid?
else else
userGrantsByRoleUuid := getRoleId(grantedByRole); userGrantsByRoleUuid := getRoleId(grantedByRole);
end if; end if;

View File

@ -121,7 +121,7 @@ public class ArchitectureTest {
.should().onlyBeAccessed().byClassesThat() .should().onlyBeAccessed().byClassesThat()
.resideInAnyPackage( .resideInAnyPackage(
"..hs.office.(*)..", "..hs.office.(*)..",
"..rbac.rbacgrant" // TODO: just because of RbacGrantsDiagramServiceIntegrationTest "..rbac.rbacgrant" // TODO.test: just because of RbacGrantsDiagramServiceIntegrationTest
); );
@ArchTest @ArchTest

View File

@ -28,10 +28,10 @@ class ContextUnitTest {
private static final String DEFINE_CONTEXT_QUERY_STRING = """ private static final String DEFINE_CONTEXT_QUERY_STRING = """
call defineContext( call defineContext(
cast(:currentTask as varchar), cast(:currentTask as varchar(127)),
cast(:currentRequest as varchar), cast(:currentRequest as text),
cast(:currentUser as varchar), cast(:currentUser as varchar(63)),
cast(:assumedRoles as varchar)); cast(:assumedRoles as varchar(1023)));
"""; """;
@Nested @Nested
@ -71,7 +71,7 @@ class ContextUnitTest {
context.define("current-user"); context.define("current-user");
verify(em).createNativeQuery(DEFINE_CONTEXT_QUERY_STRING); verify(em).createNativeQuery(DEFINE_CONTEXT_QUERY_STRING);
verify(nativeQuery).setParameter("currentRequest", ""); verify(nativeQuery).setParameter("currentRequest", null);
} }
} }
@ -142,8 +142,8 @@ class ContextUnitTest {
} }
@Test @Test
void shortensCurrentTaskTo96Chars() throws IOException { void shortensCurrentTaskToMaxLength() throws IOException {
givenRequest("GET", "http://localhost:9999/api/endpoint/" + "0123456789".repeat(10), givenRequest("GET", "http://localhost:9999/api/endpoint/" + "0123456789".repeat(13),
Map.ofEntries( Map.ofEntries(
Map.entry("current-user", "given-user"), Map.entry("current-user", "given-user"),
Map.entry("content-type", "application/json"), Map.entry("content-type", "application/json"),
@ -153,26 +153,7 @@ class ContextUnitTest {
context.define("current-user"); context.define("current-user");
verify(em).createNativeQuery(DEFINE_CONTEXT_QUERY_STRING); verify(em).createNativeQuery(DEFINE_CONTEXT_QUERY_STRING);
verify(nativeQuery).setParameter(eq("currentTask"), argThat((String t) -> t.length() == 96)); verify(nativeQuery).setParameter(eq("currentTask"), argThat((String t) -> t.length() == 127));
}
@Test
void shortensCurrentRequestTo512Chars() throws IOException {
givenRequest("GET", "http://localhost:9999/api/endpoint",
Map.ofEntries(
Map.entry("current-user", "given-user"),
Map.entry("content-type", "application/json"),
Map.entry("user-agent", "given-user-agent")),
"""
{
"dummy": "%s"
}
""".formatted("0123456789".repeat(60)));
context.define("current-user");
verify(em).createNativeQuery(DEFINE_CONTEXT_QUERY_STRING);
verify(nativeQuery).setParameter(eq("currentRequest"), argThat((String t) -> t.length() == 512));
} }
private void givenRequest(final String method, final String url, final Map<String, String> headers, final String body) private void givenRequest(final String method, final String url, final Map<String, String> headers, final String body)

View File

@ -1,11 +1,10 @@
package net.hostsharing.hsadminng.hs.office.test; package net.hostsharing.hsadminng.hs.office.test;
import net.hostsharing.hsadminng.context.ContextBasedTest; import net.hostsharing.hsadminng.context.ContextBasedTest;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantEntity; import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantEntity;
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository; import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository;
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService; import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService;
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleEntity; import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleEntity;
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository; import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository;
import net.hostsharing.test.JpaAttempt; import net.hostsharing.test.JpaAttempt;
@ -66,7 +65,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
return merged; return merged;
} }
public UUID toCleanup(final Class<? extends HasUuid> entityClass, final UUID uuidToCleanup) { public UUID toCleanup(final Class<? extends RbacObject> entityClass, final UUID uuidToCleanup) {
out.println("toCleanup(" + entityClass.getSimpleName() + ", " + uuidToCleanup); out.println("toCleanup(" + entityClass.getSimpleName() + ", " + uuidToCleanup);
entitiesToCleanup.put(uuidToCleanup, entityClass); entitiesToCleanup.put(uuidToCleanup, entityClass);
return uuidToCleanup; return uuidToCleanup;
@ -81,7 +80,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
return entity; return entity;
} }
protected void cleanupAllNew(final Class<? extends HasUuid> entityClass) { protected void cleanupAllNew(final Class<? extends RbacObject> entityClass) {
if (initialRbacObjects == null) { if (initialRbacObjects == null) {
out.println("skipping cleanupAllNew: " + entityClass.getSimpleName()); out.println("skipping cleanupAllNew: " + entityClass.getSimpleName());
return; // TODO: seems @AfterEach is called without any @BeforeEach return; // TODO: seems @AfterEach is called without any @BeforeEach

View File

@ -1,6 +1,6 @@
package net.hostsharing.hsadminng.hs.office.test; package net.hostsharing.hsadminng.hs.office.test;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import java.util.List; import java.util.List;
@ -8,7 +8,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class EntityList { public class EntityList {
public static <E extends HasUuid> E one(final List<E> entities) { public static <E extends RbacObject> E one(final List<E> entities) {
assertThat(entities).hasSize(1); assertThat(entities).hasSize(1);
return entities.stream().findFirst().orElseThrow(); return entities.stream().findFirst().orElseThrow();
} }

View File

@ -130,7 +130,6 @@ public class JpaAttempt {
final Class<? extends RuntimeException> expectedExceptionClass, final Class<? extends RuntimeException> expectedExceptionClass,
final String... expectedRootCauseMessages) { final String... expectedRootCauseMessages) {
assertThat(wasSuccessful()).as("wasSuccessful").isFalse(); assertThat(wasSuccessful()).as("wasSuccessful").isFalse();
// TODO: also check the expected exception class itself
final String firstRootCauseMessageLine = firstRootCauseMessageLineOf(caughtException(expectedExceptionClass)); final String firstRootCauseMessageLine = firstRootCauseMessageLineOf(caughtException(expectedExceptionClass));
for (String expectedRootCauseMessage : expectedRootCauseMessages) { for (String expectedRootCauseMessage : expectedRootCauseMessages) {
assertThat(firstRootCauseMessageLine).contains(expectedRootCauseMessage); assertThat(firstRootCauseMessageLine).contains(expectedRootCauseMessage);

View File

@ -1,6 +1,6 @@
package net.hostsharing.test; package net.hostsharing.test;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.mapper.EntityPatcher; import net.hostsharing.hsadminng.mapper.EntityPatcher;
import org.junit.jupiter.api.Named; import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -233,7 +233,7 @@ public abstract class PatchUnitTestBase<R, E> {
} }
} }
protected static class JsonNullableProperty<R, RV, E extends HasUuid, EV> extends Property<R, RV, E, EV> { protected static class JsonNullableProperty<R, RV, E extends RbacObject, EV> extends Property<R, RV, E, EV> {
private final BiConsumer<R, JsonNullable<RV>> resourceSetter; private final BiConsumer<R, JsonNullable<RV>> resourceSetter;
public final RV givenPatchValue; public final RV givenPatchValue;