From 277369a960d7e51ba5b542278ae9e3bbab1a4c35 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Tue, 2 Apr 2024 13:09:12 +0200 Subject: [PATCH 1/2] debitornumbersuffix-as-string (#30) Co-authored-by: Michael Hoennig Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/30 Reviewed-by: Timotheus Pokorra --- .../hs/office/debitor/HsOfficeDebitorEntity.java | 11 +++++++---- .../office/membership/HsOfficeMembershipEntity.java | 3 +++ .../506-debitor/5060-hs-office-debitor.sql | 2 +- .../506-debitor/5063-hs-office-debitor-rbac.sql | 2 +- .../5078-hs-office-sepamandate-test-data.sql | 8 ++++---- .../510-membership/5100-hs-office-membership.sql | 3 +-- .../HsOfficeDebitorControllerAcceptanceTest.java | 6 +++++- .../office/debitor/HsOfficeDebitorEntityUnitTest.java | 10 +++++----- .../HsOfficeDebitorRepositoryIntegrationTest.java | 8 ++++---- .../hs/office/debitor/TestHsOfficeDebitor.java | 2 +- .../hs/office/migration/ImportOfficeData.java | 2 +- 11 files changed, 33 insertions(+), 24 deletions(-) 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 1c784078..0a63d0b1 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 @@ -16,6 +16,7 @@ import org.hibernate.annotations.NotFound; import org.hibernate.annotations.NotFoundAction; import jakarta.persistence.*; +import jakarta.validation.constraints.Pattern; import java.io.IOException; import java.util.UUID; @@ -45,6 +46,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { public static final String DEBITOR_NUMBER_TAG = "D-"; + public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$"; private static Stringify stringify = stringify(HsOfficeDebitorEntity.class, "debitor") @@ -75,8 +77,9 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { @NotFound(action = NotFoundAction.IGNORE) private HsOfficePartnerEntity partner; - @Column(name = "debitornumbersuffix", columnDefinition = "numeric(2)") - private Byte debitorNumberSuffix; // TODO maybe rather as a formatted String? + @Column(name = "debitornumbersuffix", length = 2) + @Pattern(regexp = TWO_DECIMAL_DIGITS) + private String debitorNumberSuffix; @ManyToOne(cascade = { PERSIST, MERGE, REFRESH, DETACH }, optional = false) @JoinColumn(name = "debitorreluuid", nullable = false) @@ -109,7 +112,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { .filter(partner -> debitorNumberSuffix != null) .map(HsOfficePartnerEntity::getPartnerNumber) .map(Object::toString) - .map(partnerNumber -> partnerNumber + String.format("%02d", debitorNumberSuffix)) + .map(partnerNumber -> partnerNumber + debitorNumberSuffix) .orElse(null); } @@ -138,7 +141,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { JOIN hs_office_relation debitorRel ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR' WHERE debitorRel.uuid = debitor.debitorRelUuid) - || to_char(debitorNumberSuffix, 'fm00') as idName + || debitorNumberSuffix as idName FROM hs_office_debitor AS debitor """)) .withRestrictedViewOrderBy(SQL.projection("defaultPrefix")) 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 71a8b1d0..801d9033 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 @@ -14,6 +14,7 @@ import net.hostsharing.hsadminng.stringify.Stringifyable; import org.hibernate.annotations.Type; import jakarta.persistence.*; +import jakarta.validation.constraints.Pattern; import java.io.IOException; import java.time.LocalDate; import java.util.UUID; @@ -44,6 +45,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; public class HsOfficeMembershipEntity implements HasUuid, Stringifyable { public static final String MEMBER_NUMBER_TAG = "M-"; + public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$"; private static Stringify stringify = stringify(HsOfficeMembershipEntity.class) .withProp(e -> MEMBER_NUMBER_TAG + e.getMemberNumber()) @@ -61,6 +63,7 @@ public class HsOfficeMembershipEntity implements HasUuid, Stringifyable { private HsOfficePartnerEntity partner; @Column(name = "membernumbersuffix", length = 2) + @Pattern(regexp = TWO_DECIMAL_DIGITS) private String memberNumberSuffix; @Column(name = "validity", columnDefinition = "daterange") diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql index e2174eca..59ad01e0 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql @@ -7,7 +7,7 @@ create table hs_office_debitor ( uuid uuid unique references RbacObject (uuid) initially deferred, - debitorNumberSuffix numeric(2) not null, + debitorNumberSuffix char(2) not null check (debitorNumberSuffix::text ~ '^[0-9][0-9]$'), debitorRelUuid uuid not null references hs_office_relation(uuid), billable boolean not null default true, vatId varchar(24), -- TODO.spec: here or in person? diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql index 152f980e..59ac43e8 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql @@ -201,7 +201,7 @@ create trigger hs_office_debitor_insert_permission_check_tg JOIN hs_office_relation debitorRel ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR' WHERE debitorRel.uuid = debitor.debitorRelUuid) - || to_char(debitorNumberSuffix, 'fm00') as idName + || debitorNumberSuffix as idName FROM hs_office_debitor AS debitor $idName$); --// diff --git a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql index 69d39165..e664d8c5 100644 --- a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql @@ -10,7 +10,7 @@ */ create or replace procedure createHsOfficeSepaMandateTestData( forPartnerNumber numeric(5), - forDebitorSuffix numeric(2), + forDebitorSuffix char(2), forIban varchar, withReference varchar) language plpgsql as $$ @@ -48,9 +48,9 @@ end; $$; do language plpgsql $$ begin - call createHsOfficeSepaMandateTestData(10001, 11, 'DE02120300000000202051', 'ref-10001-11'); - call createHsOfficeSepaMandateTestData(10002, 12, 'DE02100500000054540402', 'ref-10002-12'); - call createHsOfficeSepaMandateTestData(10003, 13, 'DE02300209000106531065', 'ref-10003-13'); + call createHsOfficeSepaMandateTestData(10001, '11', 'DE02120300000000202051', 'ref-10001-11'); + call createHsOfficeSepaMandateTestData(10002, '12', 'DE02100500000054540402', 'ref-10002-12'); + call createHsOfficeSepaMandateTestData(10003, '13', 'DE02300209000106531065', 'ref-10003-13'); end; $$; --// diff --git a/src/main/resources/db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql b/src/main/resources/db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql index f2a560e2..28ec1249 100644 --- a/src/main/resources/db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql +++ b/src/main/resources/db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql @@ -12,8 +12,7 @@ create table if not exists hs_office_membership ( uuid uuid unique references RbacObject (uuid) initially deferred, partnerUuid uuid not null references hs_office_partner(uuid), - memberNumberSuffix char(2) not null check ( - memberNumberSuffix::text ~ '^[0-9][0-9]$'), + memberNumberSuffix char(2) not null check (memberNumberSuffix::text ~ '^[0-9][0-9]$'), validity daterange not null, reasonForTermination HsOfficeReasonForTermination not null default 'NONE', membershipFeeBillable boolean not null default true, diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java index c2e3fffd..07ecb5f5 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java @@ -722,7 +722,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu final var givenPartner = partnerRepo.findPartnerByOptionalNameLike("Fourth").get(0); final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").get(0); final var newDebitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix(++nextDebitorSuffix) + .debitorNumberSuffix(nextDebitorSuffix()) .billable(true) .debitorRel( HsOfficeRelationEntity.builder() @@ -751,4 +751,8 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu System.out.printf("deleted %d entities%n", count); }); } + + private String nextDebitorSuffix() { + return String.format("%02d", nextDebitorSuffix++); + } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java index 3ad1c8ea..cb629b2b 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java @@ -26,7 +26,7 @@ class HsOfficeDebitorEntityUnitTest { @Test void toStringContainsPartnerAndContact() { final var given = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte)67) + .debitorNumberSuffix("67") .debitorRel(givenDebitorRel) .defaultPrefix("som") .partner(HsOfficePartnerEntity.builder() @@ -43,7 +43,7 @@ class HsOfficeDebitorEntityUnitTest { void toShortStringContainsDebitorNumber() { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) - .debitorNumberSuffix((byte)67) + .debitorNumberSuffix("67") .partner(HsOfficePartnerEntity.builder() .partnerNumber(12345) .build()) @@ -58,7 +58,7 @@ class HsOfficeDebitorEntityUnitTest { void getDebitorNumberWithPartnerNumberAndDebitorNumberSuffix() { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) - .debitorNumberSuffix((byte)67) + .debitorNumberSuffix("67") .partner(HsOfficePartnerEntity.builder() .partnerNumber(12345) .build()) @@ -73,7 +73,7 @@ class HsOfficeDebitorEntityUnitTest { void getDebitorNumberWithoutPartnerReturnsNull() { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) - .debitorNumberSuffix((byte)67) + .debitorNumberSuffix("67") .partner(null) .build(); @@ -86,7 +86,7 @@ class HsOfficeDebitorEntityUnitTest { void getDebitorNumberWithoutPartnerNumberReturnsNull() { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) - .debitorNumberSuffix((byte)67) + .debitorNumberSuffix("67") .partner(HsOfficePartnerEntity.builder().build()) .build(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java index 7a3dfbb7..32f441af 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java @@ -89,7 +89,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean // when final var result = attempt(em, () -> { final var newDebitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte)21) + .debitorNumberSuffix("21") .debitorRel(HsOfficeRelationEntity.builder() .type(HsOfficeRelationType.DEBITOR) .anchor(givenPartnerPerson) @@ -121,7 +121,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean // when final var result = attempt(em, () -> { final var newDebitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte)21) + .debitorNumberSuffix("21") .debitorRel(HsOfficeRelationEntity.builder() .type(HsOfficeRelationType.DEBITOR) .anchor(givenPartnerPerson) @@ -156,7 +156,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenDebitorPerson = one(personRepo.findPersonByOptionalNameLike("Fourth eG")); final var givenContact = one(contactRepo.findContactByOptionalLabelLike("fourth contact")); final var newDebitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte)22) + .debitorNumberSuffix("22") .debitorRel(HsOfficeRelationEntity.builder() .type(HsOfficeRelationType.DEBITOR) .anchor(givenPartnerPerson) @@ -613,7 +613,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenBankAccount = bankAccountHolder != null ? one(bankAccountRepo.findByOptionalHolderLike(bankAccountHolder)) : null; final var newDebitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte)20) + .debitorNumberSuffix("20") .debitorRel(HsOfficeRelationEntity.builder() .type(HsOfficeRelationType.DEBITOR) .anchor(givenPartnerPerson) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java index 2970ea1b..4305b87a 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java @@ -10,7 +10,7 @@ import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TE @UtilityClass public class TestHsOfficeDebitor { - public byte DEFAULT_DEBITOR_SUFFIX = 0; + public String DEFAULT_DEBITOR_SUFFIX = "00"; public static final HsOfficeDebitorEntity TEST_DEBITOR = HsOfficeDebitorEntity.builder() .debitorNumberSuffix(DEFAULT_DEBITOR_SUFFIX) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java index 4010167d..8da1f12f 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java @@ -724,7 +724,7 @@ public class ImportOfficeData extends ContextBasedTest { relations.put(relationId++, debitorRel); final var debitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte) 0) + .debitorNumberSuffix("00") .partner(partner) .debitorRel(debitorRel) .defaultPrefix(rec.getString("member_code").replace("hsh00-", "")) From ad04faa21de837b8e80c8e77d9da7bcf4317d319 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Tue, 2 Apr 2024 13:14:46 +0200 Subject: [PATCH 2/2] cleanup-todos (#31) Co-authored-by: Michael Hoennig Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/31 Reviewed-by: Timotheus Pokorra --- .gitignore | 1 - README.md | 9 +---- doc/test-concept.md | 4 +- sql/historization.sql | 32 +++++++-------- .../hsadminng/context/Context.java | 19 +++++---- .../HsOfficeBankAccountEntity.java | 4 +- .../office/contact/HsOfficeContactEntity.java | 10 ++--- .../HsOfficeCoopAssetsTransactionEntity.java | 6 ++- .../HsOfficeCoopSharesTransactionEntity.java | 7 ++-- .../office/debitor/HsOfficeDebitorEntity.java | 6 +-- .../membership/HsOfficeMembershipEntity.java | 5 ++- .../partner/HsOfficePartnerDetailsEntity.java | 4 +- .../office/partner/HsOfficePartnerEntity.java | 4 +- .../partner/HsOfficePartnerRepository.java | 2 +- .../office/person/HsOfficePersonEntity.java | 4 +- .../relation/HsOfficeRelationEntity.java | 4 +- .../HsOfficeSepaMandateEntity.java | 4 +- .../hsadminng/persistence/HasUuid.java | 7 ---- .../hsadminng/rbac/rbacdef/RbacView.java | 14 +++---- .../test/cust/TestCustomerEntity.java | 4 +- .../hsadminng/test/dom/TestDomainEntity.java | 4 +- .../hsadminng/test/pac/TestPackageEntity.java | 4 +- .../rbac/rbac-role-schemas.yaml | 2 +- .../db/changelog/0-basis/010-context.sql | 8 ++-- .../db/changelog/1-rbac/1054-rbac-context.sql | 8 ++-- .../1-rbac/1057-rbac-role-builder.sql | 25 ++++-------- .../hsadminng/arch/ArchitectureTest.java | 2 +- .../hsadminng/context/ContextUnitTest.java | 39 +++++-------------- .../test/ContextBasedTestWithCleanup.java | 7 ++-- .../hsadminng/hs/office/test/EntityList.java | 4 +- .../java/net/hostsharing/test/JpaAttempt.java | 1 - .../hostsharing/test/PatchUnitTestBase.java | 4 +- 32 files changed, 108 insertions(+), 150 deletions(-) delete mode 100644 src/main/java/net/hostsharing/hsadminng/persistence/HasUuid.java 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 entityClass, + final Class 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 entityClass, + final String aliasName, final Class 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 entityClass, + final String aliasName, final Class 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 entityClass, + final String aliasName, final Class entityClass, final Column dependsOnColum) { importEntityAliasImpl(aliasName, entityClass, directlyFetchedByDependsOnColumn(), dependsOnColum, false, null); return this; } private EntityAlias importEntityAliasImpl( - final String aliasName, final Class entityClass, + final String aliasName, final Class 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 c) { + private static void generateRbacView(final Class 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 entityClass, final UUID uuidToCleanup) { + public UUID toCleanup(final Class 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 entityClass) { + protected void cleanupAllNew(final Class 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 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;