diff --git a/.gitignore b/.gitignore
index d6a2e347..522bf4fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,6 @@
/build/www/**
/src/test/javascript/coverage/
/worktrees/
-TODO-progress.png
######################
# Node
diff --git a/README.md b/README.md
index 23209dd2..4d03a6d3 100644
--- a/README.md
+++ b/README.md
@@ -380,12 +380,6 @@ You can explore the prototype as follows:
`src/`
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/`
Some shell-scripts to useful tasks.
@@ -765,5 +759,4 @@ The output will list the generated files.
## Further Documentation
- the `doc` directory contains architecture concepts and a glossary
-- TODO.md tracks requirements and progress for the contract of the initial project,
- please do not amend anything in this document
+- the `ideas` directory contains unstructured ideas for future development or documentation
diff --git a/doc/test-concept.md b/doc/test-concept.md
index c8946342..690d1558 100644
--- a/doc/test-concept.md
+++ b/doc/test-concept.md
@@ -87,7 +87,7 @@ Acceptance-Tests run on a fully integrated and deployed system with deployed dou
Acceptance-tests, are blackbox-tests and do not count into test-code-coverage.
-TODO: Complete the Acceptance-Tests test concept.
+TODO.test: Complete the Acceptance-Tests test concept.
#### 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 not count into test-code-coverage.
-TODO: Complete the System-Integration-Tests test concept.
+TODO.test: Complete the System-Integration-Tests test concept.
diff --git a/sql/historization.sql b/sql/historization.sql
index 2f4087b4..1bd0db44 100644
--- a/sql/historization.sql
+++ b/sql/historization.sql
@@ -18,8 +18,8 @@ CREATE OR REPLACE FUNCTION historicize()
RETURNS trigger
LANGUAGE plpgsql STRICT AS $$
DECLARE
-currentUser VARCHAR(64);
- currentTask varchar;
+ currentUser VARCHAR(63);
+ currentTask VARCHAR(127);
"row" RECORD;
"alive" BOOLEAN;
"sql" varchar;
@@ -37,27 +37,27 @@ END IF;
-- determine task
currentTask = current_setting('hsadminng.currentTask');
- IF (currentTask IS NULL OR length(currentTask) < 12) THEN
- RAISE EXCEPTION 'hsadminng.currentTask (%) must be defined and min 12 characters long, please use "SET LOCAL ...;"', currentTask;
-END IF;
- RAISE NOTICE 'currentTask: %', currentTask;
+ assert currentTask IS NOT NULL AND length(currentTask) >= 12,
+ format('hsadminng.currentTask (%s) must be defined and min 12 characters long, please use "SET LOCAL ...;"', currentTask);
+ assert length(currentTask) <= 127,
+ format('hsadminng.currentTask (%s) must not be longer than 127 characters"', currentTask);
IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN
"row" := NEW;
"alive" := TRUE;
-ELSE -- DELETE or TRUNCATE
- "row" := OLD;
- "alive" := FALSE;
-END IF;
+ ELSE -- DELETE or TRUNCATE
+ "row" := OLD;
+ "alive" := FALSE;
+ END IF;
-sql := format('INSERT INTO tx_history VALUES (txid_current(), now(), %1L, %2L) ON CONFLICT DO NOTHING', currentUser, currentTask);
+ sql := format('INSERT INTO tx_history VALUES (txid_current(), now(), %1L, %2L) ON CONFLICT DO NOTHING', currentUser, currentTask);
RAISE NOTICE 'sql: %', sql;
-EXECUTE sql;
-sql := format('INSERT INTO %3$I_versions VALUES (DEFAULT, txid_current(), %1$L, %2$L, $1.*)', TG_OP, alive, TG_TABLE_NAME);
- RAISE NOTICE 'sql: %', sql;
-EXECUTE sql USING "row";
+ EXECUTE sql;
+ sql := format('INSERT INTO %3$I_versions VALUES (DEFAULT, txid_current(), %1$L, %2$L, $1.*)', TG_OP, alive, TG_TABLE_NAME);
+ RAISE NOTICE 'sql: %', sql;
+ EXECUTE sql USING "row";
-RETURN "row";
+ RETURN "row";
END; $$;
CREATE OR REPLACE PROCEDURE create_historical_view(baseTable varchar)
diff --git a/src/main/java/net/hostsharing/hsadminng/context/Context.java b/src/main/java/net/hostsharing/hsadminng/context/Context.java
index 2730147d..9a5084f0 100644
--- a/src/main/java/net/hostsharing/hsadminng/context/Context.java
+++ b/src/main/java/net/hostsharing/hsadminng/context/Context.java
@@ -55,16 +55,15 @@ public class Context {
final String currentRequest,
final String currentUser,
final String assumedRoles) {
- final var query = em.createNativeQuery(
- """
- call defineContext(
- cast(:currentTask as varchar),
- cast(:currentRequest as varchar),
- cast(:currentUser as varchar),
- cast(:assumedRoles as varchar));
- """);
- query.setParameter("currentTask", shortenToMaxLength(currentTask, 96));
- query.setParameter("currentRequest", shortenToMaxLength(currentRequest, 512)); // TODO.spec: length?
+ final var query = em.createNativeQuery("""
+ call defineContext(
+ cast(:currentTask as varchar(127)),
+ cast(:currentRequest as text),
+ cast(:currentUser as varchar(63)),
+ cast(:assumedRoles as varchar(1023)));
+ """);
+ query.setParameter("currentTask", shortenToMaxLength(currentTask, 127));
+ query.setParameter("currentRequest", currentRequest);
query.setParameter("currentUser", currentUser);
query.setParameter("assumedRoles", assumedRoles != null ? assumedRoles : "");
query.executeUpdate();
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java
index 99bb50ea..6542084e 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java
@@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.bankaccount;
import lombok.*;
import lombok.experimental.FieldNameConstants;
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.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable;
@@ -30,7 +30,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@AllArgsConstructor
@FieldNameConstants
@DisplayName("BankAccount")
-public class HsOfficeBankAccountEntity implements HasUuid, Stringifyable {
+public class HsOfficeBankAccountEntity implements RbacObject, Stringifyable {
private static Stringify toString = stringify(HsOfficeBankAccountEntity.class, "bankAccount")
.withIdProp(HsOfficeBankAccountEntity::getIban)
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java
index 4927b4bc..1ce3a557 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java
@@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.contact;
import lombok.*;
import lombok.experimental.FieldNameConstants;
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.SQL;
import net.hostsharing.hsadminng.stringify.Stringify;
@@ -30,7 +30,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@AllArgsConstructor
@FieldNameConstants
@DisplayName("Contact")
-public class HsOfficeContactEntity implements Stringifyable, HasUuid {
+public class HsOfficeContactEntity implements Stringifyable, RbacObject {
private static Stringify toString = stringify(HsOfficeContactEntity.class, "contact")
.withProp(Fields.label, HsOfficeContactEntity::getLabel)
@@ -43,13 +43,13 @@ public class HsOfficeContactEntity implements Stringifyable, HasUuid {
private String label;
@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")
- 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")
- 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
public String toString() {
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java
index af2ea582..cf8e2adf 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java
@@ -8,7 +8,8 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import net.hostsharing.hsadminng.errors.DisplayName;
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.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable;
@@ -25,6 +26,7 @@ import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.io.IOException;
import java.io.IOException;
+import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Optional;
@@ -50,7 +52,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor
@AllArgsConstructor
@DisplayName("CoopAssetsTransaction")
-public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, HasUuid {
+public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, RbacObject {
private static Stringify stringify = stringify(HsOfficeCoopAssetsTransactionEntity.class)
.withIdProp(HsOfficeCoopAssetsTransactionEntity::getTaggedMemberNumber)
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java
index c62c1605..8e8d32e5 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java
@@ -7,7 +7,9 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import net.hostsharing.hsadminng.errors.DisplayName;
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.SQL;
import net.hostsharing.hsadminng.stringify.Stringify;
@@ -23,7 +25,6 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.io.IOException;
-import java.io.IOException;
import java.time.LocalDate;
import java.util.UUID;
@@ -47,7 +48,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor
@AllArgsConstructor
@DisplayName("CoopShareTransaction")
-public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, HasUuid {
+public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, RbacObject {
private static Stringify stringify = stringify(HsOfficeCoopSharesTransactionEntity.class)
.withProp(HsOfficeCoopSharesTransactionEntity::getMemberNumberTagged)
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java
index 0a63d0b1..08c70f66 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java
@@ -5,7 +5,7 @@ import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
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.SQL;
import net.hostsharing.hsadminng.stringify.Stringify;
@@ -43,7 +43,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor
@AllArgsConstructor
@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 TWO_DECIMAL_DIGITS = "^([0-9]{2})$";
@@ -153,7 +153,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
"vatCountryCode",
"vatBusiness",
"vatReverseCharge",
- "defaultPrefix" /* TODO: do we want that updatable? */)
+ "defaultPrefix" /* TODO.spec: do we want that updatable? */)
.toRole("global", ADMIN).grantPermission(INSERT)
.importRootEntityAliasProxy("debitorRel", HsOfficeRelationEntity.class,
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java
index 801d9033..0e6560db 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java
@@ -5,7 +5,7 @@ import com.vladmihalcea.hibernate.type.range.Range;
import lombok.*;
import net.hostsharing.hsadminng.errors.DisplayName;
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.rbac.rbacdef.RbacView;
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.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.rbacViewFor;
import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@@ -42,7 +43,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor
@AllArgsConstructor
@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 TWO_DECIMAL_DIGITS = "^([0-9]{2})$";
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java
index a18dbc77..6fae8dc0 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java
@@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.hs.office.partner;
import lombok.*;
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.SQL;
import net.hostsharing.hsadminng.stringify.Stringify;
@@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor
@AllArgsConstructor
@DisplayName("PartnerDetails")
-public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable {
+public class HsOfficePartnerDetailsEntity implements RbacObject, Stringifyable {
private static Stringify stringify = stringify(
HsOfficePartnerDetailsEntity.class,
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java
index 7c9346ea..43b78fca 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java
@@ -8,7 +8,7 @@ import lombok.Setter;
import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
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.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
@@ -45,7 +45,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor
@AllArgsConstructor
@DisplayName("Partner")
-public class HsOfficePartnerEntity implements Stringifyable, HasUuid {
+public class HsOfficePartnerEntity implements Stringifyable, RbacObject {
public static final String PARTNER_NUMBER_TAG = "P-";
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java
index d334c741..6594cb1b 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java
@@ -11,7 +11,7 @@ public interface HsOfficePartnerRepository extends Repository findByUuid(UUID id);
- List findAll(); // TODO: move to a repo in test sources
+ List findAll(); // TODO.impl: move to a repo in test sources
@Query("""
SELECT partner FROM HsOfficePartnerEntity partner
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java
index e8865ce5..4d07790d 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java
@@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.person;
import lombok.*;
import lombok.experimental.FieldNameConstants;
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.SQL;
import net.hostsharing.hsadminng.stringify.Stringify;
@@ -30,7 +30,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@AllArgsConstructor
@FieldNameConstants
@DisplayName("Person")
-public class HsOfficePersonEntity implements HasUuid, Stringifyable {
+public class HsOfficePersonEntity implements RbacObject, Stringifyable {
private static Stringify toString = stringify(HsOfficePersonEntity.class, "person")
.withProp(Fields.personType, HsOfficePersonEntity::getPersonType)
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java
index 2077cf4a..8d6c6fe8 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java
@@ -4,7 +4,7 @@ import lombok.*;
import lombok.experimental.FieldNameConstants;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
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.SQL;
import net.hostsharing.hsadminng.stringify.Stringify;
@@ -32,7 +32,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
-public class HsOfficeRelationEntity implements HasUuid, Stringifyable {
+public class HsOfficeRelationEntity implements RbacObject, Stringifyable {
private static Stringify toString = stringify(HsOfficeRelationEntity.class, "rel")
.withProp(Fields.anchor, HsOfficeRelationEntity::getAnchor)
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java
index 403e2972..6ae8ff64 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java
@@ -7,7 +7,7 @@ import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
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.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable;
@@ -37,7 +37,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@NoArgsConstructor
@AllArgsConstructor
@DisplayName("SEPA-Mandate")
-public class HsOfficeSepaMandateEntity implements Stringifyable, HasUuid {
+public class HsOfficeSepaMandateEntity implements Stringifyable, RbacObject {
private static Stringify stringify = stringify(HsOfficeSepaMandateEntity.class)
.withProp(e -> e.getBankAccount().getIban())
diff --git a/src/main/java/net/hostsharing/hsadminng/persistence/HasUuid.java b/src/main/java/net/hostsharing/hsadminng/persistence/HasUuid.java
deleted file mode 100644
index 03e6abf3..00000000
--- a/src/main/java/net/hostsharing/hsadminng/persistence/HasUuid.java
+++ /dev/null
@@ -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 {
-}
diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java
index 6bba2b12..cb048455 100644
--- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java
@@ -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.relation.HsOfficeRelationEntity;
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.test.cust.TestCustomerEntity;
import net.hostsharing.hsadminng.test.dom.TestDomainEntity;
@@ -277,7 +277,7 @@ public class RbacView {
*/
public RbacView importRootEntityAliasProxy(
final String aliasName,
- final Class extends HasUuid> entityClass,
+ final Class extends RbacObject> entityClass,
final SQL fetchSql,
final Column dependsOnColum) {
if (rootEntityAliasProxy != null) {
@@ -300,7 +300,7 @@ public class RbacView {
* a JPA entity class extending RbacObject
*/
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) {
importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, true, NOT_NULL);
return this;
@@ -334,7 +334,7 @@ public class RbacView {
* a JPA entity class extending RbacObject
*/
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) {
importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, false, nullable);
return this;
@@ -342,14 +342,14 @@ public class RbacView {
// TODO: remove once it's not used in HsOffice...Entity anymore
public RbacView importEntityAlias(
- final String aliasName, final Class extends HasUuid> entityClass,
+ final String aliasName, final Class extends RbacObject> entityClass,
final Column dependsOnColum) {
importEntityAliasImpl(aliasName, entityClass, directlyFetchedByDependsOnColumn(), dependsOnColum, false, null);
return this;
}
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 var entityAlias = new EntityAlias(aliasName, entityClass, fetchSql, dependsOnColum, asSubEntity, nullable);
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(
m -> isStatic(m.getModifiers()) && m.getName().equals("main")
)
diff --git a/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java b/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java
index 94caa1de..19340440 100644
--- a/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java
@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
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.SQL;
@@ -24,7 +24,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
@Setter
@NoArgsConstructor
@AllArgsConstructor
-public class TestCustomerEntity implements HasUuid {
+public class TestCustomerEntity implements RbacObject {
@Id
@GeneratedValue
diff --git a/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java b/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java
index d3d387d7..b6d659c5 100644
--- a/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java
@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
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.SQL;
import net.hostsharing.hsadminng.test.pac.TestPackageEntity;
@@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
@Setter
@NoArgsConstructor
@AllArgsConstructor
-public class TestDomainEntity implements HasUuid {
+public class TestDomainEntity implements RbacObject {
@Id
@GeneratedValue
diff --git a/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java b/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java
index 3ac28f34..e8430863 100644
--- a/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java
@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
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.SQL;
import net.hostsharing.hsadminng.test.cust.TestCustomerEntity;
@@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
@Setter
@NoArgsConstructor
@AllArgsConstructor
-public class TestPackageEntity implements HasUuid {
+public class TestPackageEntity implements RbacObject {
@Id
@GeneratedValue
diff --git a/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml b/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml
index 45736dc3..4e5b5f4d 100644
--- a/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml
+++ b/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml
@@ -23,7 +23,7 @@ components:
- ADMIN
- AGENT
- TENANT
- - GUEST
- REFERRER
+ - GUEST
roleName:
type: string
diff --git a/src/main/resources/db/changelog/0-basis/010-context.sql b/src/main/resources/db/changelog/0-basis/010-context.sql
index 3bb37037..8ea73f45 100644
--- a/src/main/resources/db/changelog/0-basis/010-context.sql
+++ b/src/main/resources/db/changelog/0-basis/010-context.sql
@@ -10,10 +10,10 @@
This function will be overwritten by later changesets.
*/
create procedure contextDefined(
- currentTask varchar,
- currentRequest varchar,
- currentUser varchar,
- assumedRoles varchar
+ currentTask varchar(127),
+ currentRequest text,
+ currentUser varchar(63),
+ assumedRoles varchar(1023)
)
language plpgsql as $$
begin
diff --git a/src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql b/src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql
index faae1782..ab3a9bd5 100644
--- a/src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql
+++ b/src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql
@@ -85,10 +85,10 @@ end; $$;
This function will be overwritten by later changesets.
*/
create or replace procedure contextDefined(
- currentTask varchar,
- currentRequest varchar,
- currentUser varchar,
- assumedRoles varchar
+ currentTask varchar(127),
+ currentRequest text,
+ currentUser varchar(63),
+ assumedRoles varchar(1023)
)
language plpgsql as $$
declare
diff --git a/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql b/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql
index 57a97a2f..57ba3cb7 100644
--- a/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql
+++ b/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql
@@ -1,18 +1,5 @@
--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
@@ -32,6 +19,8 @@ create or replace function createRoleWithGrants(
language plpgsql as $$
declare
roleUuid uuid;
+ permission RbacOp;
+ permissionUuid uuid;
subRoleDesc RbacRoleDescriptor;
superRoleDesc RbacRoleDescriptor;
subRoleUuid uuid;
@@ -41,9 +30,11 @@ declare
begin
roleUuid := createRole(roleDescriptor);
- if cardinality(permissions) > 0 then
- call grantPermissionsToRole(roleUuid, toPermissionUuids(roleDescriptor.objectuuid, permissions));
- end if;
+ foreach permission in array permissions
+ loop
+ permissionUuid := createPermission(roleDescriptor.objectuuid, permission);
+ call grantPermissionToRole(permissionUuid, roleUuid);
+ end loop;
foreach superRoleDesc in array array_remove(incomingSuperRoles, null)
loop
@@ -60,7 +51,7 @@ begin
if cardinality(userUuids) > 0 then
-- direct grants to users need a grantedByRole which can revoke the grant
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
userGrantsByRoleUuid := getRoleId(grantedByRole);
end if;
diff --git a/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java b/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java
index be612e90..497c60de 100644
--- a/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java
@@ -121,7 +121,7 @@ public class ArchitectureTest {
.should().onlyBeAccessed().byClassesThat()
.resideInAnyPackage(
"..hs.office.(*)..",
- "..rbac.rbacgrant" // TODO: just because of RbacGrantsDiagramServiceIntegrationTest
+ "..rbac.rbacgrant" // TODO.test: just because of RbacGrantsDiagramServiceIntegrationTest
);
@ArchTest
diff --git a/src/test/java/net/hostsharing/hsadminng/context/ContextUnitTest.java b/src/test/java/net/hostsharing/hsadminng/context/ContextUnitTest.java
index af78c76a..2104f297 100644
--- a/src/test/java/net/hostsharing/hsadminng/context/ContextUnitTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/context/ContextUnitTest.java
@@ -27,12 +27,12 @@ import static org.mockito.Mockito.verify;
class ContextUnitTest {
private static final String DEFINE_CONTEXT_QUERY_STRING = """
- call defineContext(
- cast(:currentTask as varchar),
- cast(:currentRequest as varchar),
- cast(:currentUser as varchar),
- cast(:assumedRoles as varchar));
- """;
+ call defineContext(
+ cast(:currentTask as varchar(127)),
+ cast(:currentRequest as text),
+ cast(:currentUser as varchar(63)),
+ cast(:assumedRoles as varchar(1023)));
+ """;
@Nested
class WithoutHttpRequest {
@@ -71,7 +71,7 @@ class ContextUnitTest {
context.define("current-user");
verify(em).createNativeQuery(DEFINE_CONTEXT_QUERY_STRING);
- verify(nativeQuery).setParameter("currentRequest", "");
+ verify(nativeQuery).setParameter("currentRequest", null);
}
}
@@ -142,8 +142,8 @@ class ContextUnitTest {
}
@Test
- void shortensCurrentTaskTo96Chars() throws IOException {
- givenRequest("GET", "http://localhost:9999/api/endpoint/" + "0123456789".repeat(10),
+ void shortensCurrentTaskToMaxLength() throws IOException {
+ givenRequest("GET", "http://localhost:9999/api/endpoint/" + "0123456789".repeat(13),
Map.ofEntries(
Map.entry("current-user", "given-user"),
Map.entry("content-type", "application/json"),
@@ -153,26 +153,7 @@ class ContextUnitTest {
context.define("current-user");
verify(em).createNativeQuery(DEFINE_CONTEXT_QUERY_STRING);
- verify(nativeQuery).setParameter(eq("currentTask"), argThat((String t) -> t.length() == 96));
- }
-
- @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));
+ verify(nativeQuery).setParameter(eq("currentTask"), argThat((String t) -> t.length() == 127));
}
private void givenRequest(final String method, final String url, final Map headers, final String body)
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java b/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java
index 722fd87e..fc0b81c3 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java
@@ -1,11 +1,10 @@
package net.hostsharing.hsadminng.hs.office.test;
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.RbacGrantRepository;
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.RbacRoleRepository;
import net.hostsharing.test.JpaAttempt;
@@ -66,7 +65,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
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);
entitiesToCleanup.put(uuidToCleanup, entityClass);
return uuidToCleanup;
@@ -81,7 +80,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
return entity;
}
- protected void cleanupAllNew(final Class extends HasUuid> entityClass) {
+ protected void cleanupAllNew(final Class extends RbacObject> entityClass) {
if (initialRbacObjects == null) {
out.println("skipping cleanupAllNew: " + entityClass.getSimpleName());
return; // TODO: seems @AfterEach is called without any @BeforeEach
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/test/EntityList.java b/src/test/java/net/hostsharing/hsadminng/hs/office/test/EntityList.java
index 1699a5d2..2cc55e61 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/test/EntityList.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/test/EntityList.java
@@ -1,6 +1,6 @@
package net.hostsharing.hsadminng.hs.office.test;
-import net.hostsharing.hsadminng.persistence.HasUuid;
+import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import java.util.List;
@@ -8,7 +8,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class EntityList {
- public static E one(final List entities) {
+ public static E one(final List entities) {
assertThat(entities).hasSize(1);
return entities.stream().findFirst().orElseThrow();
}
diff --git a/src/test/java/net/hostsharing/test/JpaAttempt.java b/src/test/java/net/hostsharing/test/JpaAttempt.java
index 86a332cd..d0ddd040 100644
--- a/src/test/java/net/hostsharing/test/JpaAttempt.java
+++ b/src/test/java/net/hostsharing/test/JpaAttempt.java
@@ -130,7 +130,6 @@ public class JpaAttempt {
final Class extends RuntimeException> expectedExceptionClass,
final String... expectedRootCauseMessages) {
assertThat(wasSuccessful()).as("wasSuccessful").isFalse();
- // TODO: also check the expected exception class itself
final String firstRootCauseMessageLine = firstRootCauseMessageLineOf(caughtException(expectedExceptionClass));
for (String expectedRootCauseMessage : expectedRootCauseMessages) {
assertThat(firstRootCauseMessageLine).contains(expectedRootCauseMessage);
diff --git a/src/test/java/net/hostsharing/test/PatchUnitTestBase.java b/src/test/java/net/hostsharing/test/PatchUnitTestBase.java
index ce7ff865..56f97938 100644
--- a/src/test/java/net/hostsharing/test/PatchUnitTestBase.java
+++ b/src/test/java/net/hostsharing/test/PatchUnitTestBase.java
@@ -1,6 +1,6 @@
package net.hostsharing.test;
-import net.hostsharing.hsadminng.persistence.HasUuid;
+import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.mapper.EntityPatcher;
import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Test;
@@ -233,7 +233,7 @@ public abstract class PatchUnitTestBase {
}
}
- protected static class JsonNullableProperty extends Property {
+ protected static class JsonNullableProperty extends Property {
private final BiConsumer> resourceSetter;
public final RV givenPatchValue;