Compare commits

..

No commits in common. "650ae365e5f19781f39ae3d47107fb214c2f721a" and "ec53934f3077b1398b5efd11d7a0ff6239a4b35c" have entirely different histories.

43 changed files with 115 additions and 212 deletions

View File

@ -20,7 +20,6 @@ For architecture consider the files in the `doc` and `adr` folder.
- [Directory and Package Structure](#directory-and-package-structure) - [Directory and Package Structure](#directory-and-package-structure)
- [General Directory Structure](#general-directory-structure) - [General Directory Structure](#general-directory-structure)
- [Source Code Package Structure](#source-code-package-structure) - [Source Code Package Structure](#source-code-package-structure)
- [Run Tests from Command Line](#run-tests-from-command-line)
- [Spotless Code Formatting](#spotless-code-formatting) - [Spotless Code Formatting](#spotless-code-formatting)
- [JaCoCo Test Code Coverage Check](#jacoco-test-code-coverage-check) - [JaCoCo Test Code Coverage Check](#jacoco-test-code-coverage-check)
- [PiTest Mutation Testing](#pitest-mutation-testing) - [PiTest Mutation Testing](#pitest-mutation-testing)
@ -40,7 +39,6 @@ For architecture consider the files in the `doc` and `adr` folder.
- [How to Use a Persistent Database for Integration Tests?](#how-to-use-a-persistent-database-for-integration-tests?) - [How to Use a Persistent Database for Integration Tests?](#how-to-use-a-persistent-database-for-integration-tests?)
- [How to Amend Liquibase SQL Changesets?](#how-to-amend-liquibase-sql-changesets?) - [How to Amend Liquibase SQL Changesets?](#how-to-amend-liquibase-sql-changesets?)
- [How to Re-Generate Spring-Controller-Interfaces from OpenAPI specs?](#how-to-re-generate-spring-controller-interfaces-from-openapi-specs?) - [How to Re-Generate Spring-Controller-Interfaces from OpenAPI specs?](#how-to-re-generate-spring-controller-interfaces-from-openapi-specs?)
- [How to Generate Database Table Diagrams?](#how-to-generate-database-table-diagrams?)
- [Further Documentation](#further-documentation) - [Further Documentation](#further-documentation)
<!-- generated TOC end. --> <!-- generated TOC end. -->
@ -201,7 +199,7 @@ To generate the TOC (Table of Contents), a little bash script from a
Given this is in PATH as `md-toc`, use: Given this is in PATH as `md-toc`, use:
```shell ```shell
md-toc <README.md 2 4 | cut -c5-' md-toc <README.md 2 4 | sed -e 's/^ //g'
``` ```
To render the Markdown files, especially to watch embedded PlantUML diagrams, you can use one of the following methods: To render the Markdown files, especially to watch embedded PlantUML diagrams, you can use one of the following methods:
@ -235,19 +233,12 @@ sudo apt install graphviz
##### Ubuntu Linux command line ##### Ubuntu Linux command line
1. Install Pandoc with some extra libraries: ```sh
```shell
sudo apt-get install pandoc texlive-latex-base texlive-fonts-recommended texlive-extra-utils texlive-latex-extra pandoc-plantuml-filter sudo apt-get install pandoc texlive-latex-base texlive-fonts-recommended texlive-extra-utils texlive-latex-extra pandoc-plantuml-filter
``` ```
2. Install mermaid-filter, e.g. this way: ```sh
```shell pandoc --filter pandoc-plantuml rbac.md -o rbac.pdf
npm install -g mermaid-filter
```
3. Run Pandoc to generate a PDF from a Markdown file with PlantUML and Mermaid diagrams:
```shell
pandoc --filter mermaid-filter --filter pandoc-plantuml rbac.md -o rbac.pdf
``` ```
##### for other IDEs / operating systems ##### for other IDEs / operating systems
@ -256,7 +247,7 @@ If you have figured out how it works, please add instructions above this section
#### Render Markdown Embedded Mermaid Diagrams #### Render Markdown Embedded Mermaid Diagrams
The source of RBAC role diagrams are much easier to read with Mermaid than with PlantUML or GraphViz, that's also the main reason Mermaid is used. The source of RBAC role diagrams are much easier to read with Mermaid than with PlantUML or GraphViz, that's the main reason Mermaid ist used too.
Can you see the following diagram right in your IDE? Can you see the following diagram right in your IDE?
I mean a real graphic diagram, not just some markup code. I mean a real graphic diagram, not just some markup code.
@ -280,11 +271,8 @@ If not, you need to install some tooling.
##### for IntelliJ IDEA (or derived products) ##### for IntelliJ IDEA (or derived products)
1. Activate the bundled Jebrains Markdown PlantUML Extension via You just need the bundled Markdown plugin enabled and install and activate the Mermaid plugin in its [settings](jetbrains://idea/settings?name=Languages+%26+Frameworks--Markdown).
[File | Settings | Languages & Frameworks | Markdown](jetbrains://idea/settings?name=Languages+%26+Frameworks--Markdown)
2. Install the Jetbrains Mermaid plugin: https://plugins.jetbrains.com/plugin/20146-mermaid, it also works embedded in Markdown files.
Now the above diagram should be rendered.
##### for other IDEs / command-line / operating systems ##### for other IDEs / command-line / operating systems
@ -294,23 +282,13 @@ If you have figured out how it works, please add instructions above this section
#### IntelliJ IDEA #### IntelliJ IDEA
##### Build Settings
Go to [Gradle Settings}(jetbrains://idea/settings?name=Build%2C+Execution%2C+Deployment--Build+Tools--Gradle) and select "Build and run using" and "Run tests using" both to "gradle". Go to [Gradle Settings}(jetbrains://idea/settings?name=Build%2C+Execution%2C+Deployment--Build+Tools--Gradle) and select "Build and run using" and "Run tests using" both to "gradle".
Otherwise, settings from `build.gradle`, like compiler arguments, are not applied when compiling through *IntelliJ IDEA*. Otherwise, settings from `build.gradle`, like compiler arguments, are not applied when compiling through *IntelliJ IDEA*.
##### Annotation Processor
Go to [Annotations Processors](jetbrains://idea/settings?name=Build%2C+Execution%2C+Deployment--Compiler--Annotation+Processors) and activate annotation processing. Go to [Annotations Processors](jetbrains://idea/settings?name=Build%2C+Execution%2C+Deployment--Compiler--Annotation+Processors) and activate annotation processing.
Otherwise, *IntelliJ IDEA* can't see *Lombok* generated classes Otherwise, *IntelliJ IDEA* can't see *Lombok* generated classes
and will show false errors (missing identifiers). and will show false errors (missing identifiers).
##### Suggested Plugins
- [Jetbrains Mermaid Integration](https://plugins.jetbrains.com/plugin/20146-mermaid)
- [Vojtěch Krása PlantUML Integration](https://plugins.jetbrains.com/plugin/7017-plantuml-integration)
### Other Tools ### Other Tools
**jq**: a JSON formatter. **jq**: a JSON formatter.

View File

@ -50,6 +50,8 @@ ext {
set('testcontainersVersion', "1.17.3") set('testcontainersVersion', "1.17.3")
} }
// wrapper
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-rest' implementation 'org.springframework.boot:spring-boot-starter-data-rest'
@ -69,17 +71,6 @@ dependencies {
implementation 'org.iban4j:iban4j:3.2.7-RELEASE' implementation 'org.iban4j:iban4j:3.2.7-RELEASE'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
// fixes vulnerability CVE-2022-1471
// The dependency usually comes from Spring Boot, just in the wrong version.
// TODO: Remove this explicit dependency once we are on SpringBoot 3.2.x
// as well as the related exclude in settings.gradle
// and the dependency suppression in owasp-dependency-check-suppression.xml.
implementation('org.yaml:snakeyaml') {
version {
strictly('2.2')
}
}
compileOnly 'org.projectlombok:lombok' compileOnly 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok' testCompileOnly 'org.projectlombok:lombok'
@ -182,7 +173,7 @@ openApiGenerate.dependsOn processSpring
// Spotless Code Formatting // Spotless Code Formatting
spotless { spotless {
java { java {
removeUnusedImports() // removeUnusedImports() TODO: reactivate once it can deal with multi-line-strings
indentWithSpaces(4) indentWithSpaces(4)
endWithNewline() endWithNewline()
toggleOffOn() toggleOffOn()
@ -193,14 +184,8 @@ spotless {
} }
} }
} }
project.tasks.spotlessJava.dependsOn(tasks.generateLicenseReport, tasks.processResources, tasks.processTestResources)
project.tasks.check.dependsOn(spotlessCheck) project.tasks.check.dependsOn(spotlessCheck)
// HACK: no idea why spotless uses the output of these tasks, but we get warnings without those
project.tasks.spotlessJava.dependsOn(
tasks.generateLicenseReport,
tasks.pitest,
tasks.jacocoTestReport,
tasks.processResources,
tasks.processTestResources)
// OWASP Dependency Security Test // OWASP Dependency Security Test
dependencyCheck { dependencyCheck {
@ -308,7 +293,7 @@ pitest {
targetTests = ['net.hostsharing.hsadminng.**.*UnitTest', 'net.hostsharing.hsadminng.**.*RestTest'] targetTests = ['net.hostsharing.hsadminng.**.*UnitTest', 'net.hostsharing.hsadminng.**.*RestTest']
excludedTestClasses = ['**AcceptanceTest*', '**IntegrationTest*'] excludedTestClasses = ['**AcceptanceTest*', '**IntegrationTest*']
pitestVersion = '1.15.3' pitestVersion = '1.9.9'
junit5PluginVersion = '1.1.0' junit5PluginVersion = '1.1.0'
threads = 4 threads = 4

View File

@ -49,13 +49,4 @@
<packageUrl regex="true">^pkg:maven/org\.pitest/pitest\-command\-line@.*$</packageUrl> <packageUrl regex="true">^pkg:maven/org\.pitest/pitest\-command\-line@.*$</packageUrl>
<cpe>cpe:/a:line:line</cpe> <cpe>cpe:/a:line:line</cpe>
</suppress> </suppress>
<suppress>
<notes><![CDATA[
We've explicitly bumped to 2.2, but the dependency checker does not seem to notice that.
TODO: Remove this suppression once we are on SpringBoot 3.2,
as well as the explicit version bump and the transient dependency exclude.
]]></notes>
<packageUrl regex="true">^pkg:maven/org\.yaml/snakeyaml@.*$</packageUrl>
<cve>CVE-2022-1471</cve>
</suppress>
</suppressions> </suppressions>

View File

@ -7,21 +7,4 @@ pluginManagement {
} }
} }
dependencyResolutionManagement {
components {
all {
allVariants {
withDependencies {
removeAll {
// TODO: Remove this transient dependency exclude once we are on SpringBoot 3.2.x
// as well as the related explicit dependency in build.gradle
// and the dependency suppression in owasp-dependency-check-suppression.xml.
it.module in [ 'snakeyaml' ]
}
}
}
}
}
}
rootProject.name = 'hsadmin-ng' rootProject.name = 'hsadmin-ng'

View File

@ -14,7 +14,7 @@ public interface HsOfficeContactRepository extends Repository<HsOfficeContactEnt
@Query(""" @Query("""
SELECT c FROM HsOfficeContactEntity c SELECT c FROM HsOfficeContactEntity c
WHERE :label is null WHERE :label is null
OR c.label like concat(cast(:label as text), '%') OR c.label like concat(:label, '%')
""") """)
List<HsOfficeContactEntity> findContactByOptionalLabelLike(String label); List<HsOfficeContactEntity> findContactByOptionalLabelLike(String label);

View File

@ -1,11 +1,13 @@
package net.hostsharing.hsadminng.hs.office.coopassets; package net.hostsharing.hsadminng.hs.office.coopassets;
import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType;
import lombok.*; import lombok.*;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable; import net.hostsharing.hsadminng.stringify.Stringifyable;
import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -45,6 +47,7 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable {
@Column(name = "transactiontype") @Column(name = "transactiontype")
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
//@Type(PostgreSQLEnumType.class)
private HsOfficeCoopAssetsTransactionType transactionType; private HsOfficeCoopAssetsTransactionType transactionType;
@Column(name = "valuedate") @Column(name = "valuedate")

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.coopassets; package net.hostsharing.hsadminng.hs.office.coopassets;
import net.hostsharing.hsadminng.hs.office.coopshares.HsOfficeCoopSharesTransactionEntity;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository; import org.springframework.data.repository.Repository;

View File

@ -1,10 +1,12 @@
package net.hostsharing.hsadminng.hs.office.coopshares; package net.hostsharing.hsadminng.hs.office.coopshares;
import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType;
import lombok.*; import lombok.*;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable; import net.hostsharing.hsadminng.stringify.Stringifyable;
import org.hibernate.annotations.Type;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.time.LocalDate; import java.time.LocalDate;
@ -41,6 +43,7 @@ public class HsOfficeCoopSharesTransactionEntity implements Stringifyable {
@Column(name = "transactiontype") @Column(name = "transactiontype")
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
//@Type(PostgreSQLEnumType.class)
private HsOfficeCoopSharesTransactionType transactionType; private HsOfficeCoopSharesTransactionType transactionType;
@Column(name = "valuedate") @Column(name = "valuedate")

View File

@ -23,11 +23,11 @@ public interface HsOfficeDebitorRepository extends Repository<HsOfficeDebitorEnt
JOIN HsOfficePersonEntity person ON person.uuid = partner.person.uuid JOIN HsOfficePersonEntity person ON person.uuid = partner.person.uuid
JOIN HsOfficeContactEntity contact ON contact.uuid = debitor.billingContact.uuid JOIN HsOfficeContactEntity contact ON contact.uuid = debitor.billingContact.uuid
WHERE :name is null WHERE :name is null
OR partner.details.birthName like concat(cast(:name as text), '%') OR partner.details.birthName like concat(:name, '%')
OR person.tradeName like concat(cast(:name as text), '%') OR person.tradeName like concat(:name, '%')
OR person.familyName like concat(cast(:name as text), '%') OR person.familyName like concat(:name, '%')
OR person.givenName like concat(cast(:name as text), '%') OR person.givenName like concat(:name, '%')
OR contact.label like concat(cast(:name as text), '%') OR contact.label like concat(:name, '%')
""") """)
List<HsOfficeDebitorEntity> findDebitorByOptionalNameLike(String name); List<HsOfficeDebitorEntity> findDebitorByOptionalNameLike(String name);

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.membership; package net.hostsharing.hsadminng.hs.office.membership;
import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType;
import com.vladmihalcea.hibernate.type.range.PostgreSQLRangeType; import com.vladmihalcea.hibernate.type.range.PostgreSQLRangeType;
import com.vladmihalcea.hibernate.type.range.Range; import com.vladmihalcea.hibernate.type.range.Range;
import lombok.*; import lombok.*;
@ -60,6 +61,7 @@ public class HsOfficeMembershipEntity implements Stringifyable {
@Column(name = "reasonfortermination") @Column(name = "reasonfortermination")
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
//@Type(PostgreSQLEnumType.class)
private HsOfficeReasonForTermination reasonForTermination; private HsOfficeReasonForTermination reasonForTermination;
public void setValidFrom(final LocalDate validFrom) { public void setValidFrom(final LocalDate validFrom) {

View File

@ -16,11 +16,11 @@ public interface HsOfficePartnerRepository extends Repository<HsOfficePartnerEnt
JOIN HsOfficeContactEntity contact ON contact.uuid = partner.contact.uuid JOIN HsOfficeContactEntity contact ON contact.uuid = partner.contact.uuid
JOIN HsOfficePersonEntity person ON person.uuid = partner.person.uuid JOIN HsOfficePersonEntity person ON person.uuid = partner.person.uuid
WHERE :name is null WHERE :name is null
OR partner.details.birthName like concat(cast(:name as text), '%') OR partner.details.birthName like concat(:name, '%')
OR contact.label like concat(cast(:name as text), '%') OR contact.label like concat(:name, '%')
OR person.tradeName like concat(cast(:name as text), '%') OR person.tradeName like concat(:name, '%')
OR person.givenName like concat(cast(:name as text), '%') OR person.givenName like concat(:name, '%')
OR person.familyName like concat(cast(:name as text), '%') OR person.familyName like concat(:name, '%')
""") """)
List<HsOfficePartnerEntity> findPartnerByOptionalNameLike(String name); List<HsOfficePartnerEntity> findPartnerByOptionalNameLike(String name);

View File

@ -1,11 +1,13 @@
package net.hostsharing.hsadminng.hs.office.person; package net.hostsharing.hsadminng.hs.office.person;
import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType;
import lombok.*; import lombok.*;
import lombok.experimental.FieldNameConstants; import lombok.experimental.FieldNameConstants;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable; import net.hostsharing.hsadminng.stringify.Stringifyable;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.Type;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.util.UUID; import java.util.UUID;
@ -35,6 +37,7 @@ public class HsOfficePersonEntity implements Stringifyable {
@Column(name = "persontype") @Column(name = "persontype")
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
//@Type(PostgreSQLEnumType.class)
private HsOfficePersonType personType; private HsOfficePersonType personType;
@Column(name = "tradename") @Column(name = "tradename")

View File

@ -14,9 +14,9 @@ public interface HsOfficePersonRepository extends Repository<HsOfficePersonEntit
@Query(""" @Query("""
SELECT p FROM HsOfficePersonEntity p SELECT p FROM HsOfficePersonEntity p
WHERE :name is null WHERE :name is null
OR p.tradeName like concat(cast(:name as text), '%') OR p.tradeName like concat(:name, '%')
OR p.givenName like concat(cast(:name as text), '%') OR p.givenName like concat(:name, '%')
OR p.familyName like concat(cast(:name as text), '%') OR p.familyName like concat(:name, '%')
""") """)
List<HsOfficePersonEntity> findPersonByOptionalNameLike(String name); List<HsOfficePersonEntity> findPersonByOptionalNameLike(String name);

View File

@ -1,10 +1,12 @@
package net.hostsharing.hsadminng.hs.office.relationship; package net.hostsharing.hsadminng.hs.office.relationship;
import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType;
import lombok.*; import lombok.*;
import lombok.experimental.FieldNameConstants; import lombok.experimental.FieldNameConstants;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
import org.hibernate.annotations.Type;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.util.UUID; import java.util.UUID;
@ -45,6 +47,7 @@ public class HsOfficeRelationshipEntity {
@Column(name = "reltype") @Column(name = "reltype")
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
//@Type(PostgreSQLEnumType.class)
private HsOfficeRelationshipType relType; private HsOfficeRelationshipType relType;
@Override @Override

View File

@ -14,7 +14,7 @@ public interface HsOfficeSepaMandateRepository extends Repository<HsOfficeSepaMa
@Query(""" @Query("""
SELECT mandate FROM HsOfficeSepaMandateEntity mandate SELECT mandate FROM HsOfficeSepaMandateEntity mandate
WHERE :iban is null WHERE :iban is null
OR mandate.bankAccount.iban like concat(cast(:iban as text), '%') OR mandate.bankAccount.iban like concat(:iban, '%')
ORDER BY mandate.bankAccount.iban ORDER BY mandate.bankAccount.iban
""") """)
List<HsOfficeSepaMandateEntity> findSepaMandateByOptionalIban(String iban); List<HsOfficeSepaMandateEntity> findSepaMandateByOptionalIban(String iban);

View File

@ -1,10 +1,12 @@
package net.hostsharing.hsadminng.mapper; package net.hostsharing.hsadminng.mapper;
import com.vladmihalcea.hibernate.type.range.Range;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.postgresql.util.PGtokenizer; import org.postgresql.util.PGtokenizer;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.function.Function; import java.util.function.Function;
@UtilityClass @UtilityClass
@ -42,10 +44,7 @@ public class PostgresArray {
tokenizer.remove("\"", "\""); tokenizer.remove("\"", "\"");
final T[] array = newGenericArray(elementClass, tokenizer.getSize()); // Create a new array of the specified type and length final T[] array = newGenericArray(elementClass, tokenizer.getSize()); // Create a new array of the specified type and length
for ( int n = 0; n < tokenizer.getSize(); ++n ) { for ( int n = 0; n < tokenizer.getSize(); ++n ) {
final String token = tokenizer.getToken(n); array[n] = itemParser.apply(tokenizer.getToken(n).trim().replace("\\\"", "\""));
if ( !"NULL".equals(token) ) {
array[n] = itemParser.apply(token.trim().replace("\\\"", "\""));
}
} }
return array; return array;
} }

View File

@ -11,7 +11,7 @@ public interface RbacUserRepository extends Repository<RbacUserEntity, UUID> {
@Query(""" @Query("""
select u from RbacUserEntity u select u from RbacUserEntity u
where :userName is null or u.name like concat(cast(:userName as text), '%') where :userName is null or u.name like concat(:userName, '%')
order by u.name order by u.name
""") """)
List<RbacUserEntity> findByOptionalNameLike(String userName); List<RbacUserEntity> findByOptionalNameLike(String userName);

View File

@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import java.util.List; import java.util.List;
import java.util.UUID;
@RestController @RestController
public class TestCustomerController implements TestCustomersApi { public class TestCustomerController implements TestCustomersApi {

View File

@ -12,7 +12,7 @@ public interface TestCustomerRepository extends Repository<TestCustomerEntity, U
Optional<TestCustomerEntity> findByUuid(UUID id); Optional<TestCustomerEntity> findByUuid(UUID id);
@Query("SELECT c FROM TestCustomerEntity c WHERE :prefix is null or c.prefix like concat(cast(:prefix as text), '%')") @Query("SELECT c FROM TestCustomerEntity c WHERE :prefix is null or c.prefix like concat(:prefix, '%')")
List<TestCustomerEntity> findCustomerByOptionalPrefixLike(String prefix); List<TestCustomerEntity> findCustomerByOptionalPrefixLike(String prefix);
TestCustomerEntity save(final TestCustomerEntity entity); TestCustomerEntity save(final TestCustomerEntity entity);

View File

@ -8,7 +8,7 @@ import java.util.UUID;
public interface TestPackageRepository extends Repository<TestPackageEntity, UUID> { public interface TestPackageRepository extends Repository<TestPackageEntity, UUID> {
@Query("SELECT p FROM TestPackageEntity p WHERE :name is null or p.name like concat(cast(:name as text), '%')") @Query("SELECT p FROM TestPackageEntity p WHERE :name is null or p.name like concat(:name, '%')")
List<TestPackageEntity> findAllByOptionalNameLike(final String name); List<TestPackageEntity> findAllByOptionalNameLike(final String name);
TestPackageEntity findByUuid(UUID packageUuid); TestPackageEntity findByUuid(UUID packageUuid);

View File

@ -83,7 +83,7 @@ class HsOfficeBankAccountControllerRestTest {
enum InvalidBicTestCase { enum InvalidBicTestCase {
TOO_SHORT("BEVODEB", "Bic length must be 8 or 11"), TOO_SHORT("BEVODEB", "Bic length must be 8 or 11"),
TOO_LONG("BEVODEBBX", "Bic length must be 8 or 11"), TOO_LONG("BEVODEBBX", "Bic length must be 8 or 11"),
INVALID_CHARACTER("BEV-ODEB", "Bank code must contain only alphanumeric."); INVALID_CHARACTER("BEV-ODEB", "Bank code must contain only letters.");
private final String givenBic; private final String givenBic;
private final String expectedErrorMessage; private final String expectedErrorMessage;

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.bankaccount; package net.hostsharing.hsadminng.hs.office.bankaccount;
import java.util.UUID;
public class TestHsOfficeBankAccount { public class TestHsOfficeBankAccount {

View File

@ -28,6 +28,7 @@ import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.grantD
import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf; import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf;
import static net.hostsharing.test.JpaAttempt.attempt; import static net.hostsharing.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest @DataJpaTest
@Import( { Context.class, JpaAttempt.class }) @Import( { Context.class, JpaAttempt.class })
@ -236,6 +237,10 @@ class HsOfficeContactRepositoryIntegrationTest extends ContextBasedTest {
final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll()); final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll());
final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll()); final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll());
final var givenContact = givenSomeTemporaryContact("selfregistered-user-drew@hostsharing.org"); final var givenContact = givenSomeTemporaryContact("selfregistered-user-drew@hostsharing.org");
assumeThat(rawRoleRepo.findAll().size()).as("unexpected number of roles created")
.isEqualTo(initialRoleNames.size() + 3);
assumeThat(rawGrantRepo.findAll().size()).as("unexpected number of grants created")
.isEqualTo(initialGrantNames.size() + 7);
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.contact; package net.hostsharing.hsadminng.hs.office.contact;
import java.util.UUID;
public class TestHsOfficeContact { public class TestHsOfficeContact {

View File

@ -26,6 +26,7 @@ import java.util.UUID;
import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid; import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid;
import static net.hostsharing.test.JsonMatcher.lenientlyEquals; import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
@SpringBootTest( @SpringBootTest(
@ -480,7 +481,7 @@ class HsOfficeDebitorControllerAcceptanceTest {
void contactAdminUser_canNotDeleteRelatedDebitor() { void contactAdminUser_canNotDeleteRelatedDebitor() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenDebitor = givenSomeTemporaryDebitor(); final var givenDebitor = givenSomeTemporaryDebitor();
assertThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact"); assumeThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact");
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
@ -500,7 +501,7 @@ class HsOfficeDebitorControllerAcceptanceTest {
void normalUser_canNotDeleteUnrelatedDebitor() { void normalUser_canNotDeleteUnrelatedDebitor() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenDebitor = givenSomeTemporaryDebitor(); final var givenDebitor = givenSomeTemporaryDebitor();
assertThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact"); assumeThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact");
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()

View File

@ -2,6 +2,7 @@ package net.hostsharing.hsadminng.hs.office.debitor;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import java.util.UUID;
import static net.hostsharing.hsadminng.hs.office.contact.TestHsOfficeContact.TEST_CONTACT; import static net.hostsharing.hsadminng.hs.office.contact.TestHsOfficeContact.TEST_CONTACT;
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER; import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER;

View File

@ -32,6 +32,7 @@ import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.grantD
import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf; import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf;
import static net.hostsharing.test.JpaAttempt.attempt; import static net.hostsharing.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest @DataJpaTest
@Import( { Context.class, JpaAttempt.class }) @Import( { Context.class, JpaAttempt.class })
@ -326,7 +327,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTest {
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net", "hs_office_debitor#10003ThirdOHG-thirdcontact.admin"); context("superuser-alex@hostsharing.net", "hs_office_debitor#10003ThirdOHG-thirdcontact.admin");
assertThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent(); assumeThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent();
membershipRepo.deleteByUuid(givenMembership.getUuid()); membershipRepo.deleteByUuid(givenMembership.getUuid());
}); });

View File

@ -3,6 +3,7 @@ package net.hostsharing.hsadminng.hs.office.membership;
import com.vladmihalcea.hibernate.type.range.Range; import com.vladmihalcea.hibernate.type.range.Range;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.UUID;
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER; import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER;

View File

@ -24,6 +24,7 @@ import java.util.UUID;
import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid; import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid;
import static net.hostsharing.test.JsonMatcher.lenientlyEquals; import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.startsWith;
@ -407,7 +408,7 @@ class HsOfficePartnerControllerAcceptanceTest {
void contactAdminUser_canNotDeleteRelatedPartner() { void contactAdminUser_canNotDeleteRelatedPartner() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenPartner = givenSomeTemporaryPartnerBessler(); final var givenPartner = givenSomeTemporaryPartnerBessler();
assertThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact"); assumeThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact");
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
@ -427,7 +428,7 @@ class HsOfficePartnerControllerAcceptanceTest {
void normalUser_canNotDeleteUnrelatedPartner() { void normalUser_canNotDeleteUnrelatedPartner() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenPartner = givenSomeTemporaryPartnerBessler(); final var givenPartner = givenSomeTemporaryPartnerBessler();
assertThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact"); assumeThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact");
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()

View File

@ -29,6 +29,7 @@ import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.grantD
import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf; import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf;
import static net.hostsharing.test.JpaAttempt.attempt; import static net.hostsharing.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest @DataJpaTest
@Import( { Context.class, JpaAttempt.class }) @Import( { Context.class, JpaAttempt.class })
@ -329,7 +330,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
context("person-ErbenBesslerMelBessler@example.com"); context("person-ErbenBesslerMelBessler@example.com");
assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent(); assumeThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent();
partnerRepo.deleteByUuid(givenPartner.getUuid()); partnerRepo.deleteByUuid(givenPartner.getUuid());
}); });
@ -351,6 +352,10 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
final var initialRoleNames = Array.from(roleNamesOf(rawRoleRepo.findAll())); final var initialRoleNames = Array.from(roleNamesOf(rawRoleRepo.findAll()));
final var initialGrantNames = Array.from(grantDisplaysOf(rawGrantRepo.findAll())); final var initialGrantNames = Array.from(grantDisplaysOf(rawGrantRepo.findAll()));
final var givenPartner = givenSomeTemporaryPartnerBessler("twelfth"); final var givenPartner = givenSomeTemporaryPartnerBessler("twelfth");
assumeThat(rawRoleRepo.findAll().size()).as("unexpected number of roles created")
.isEqualTo(initialRoleNames.length + 3);
assumeThat(rawGrantRepo.findAll().size()).as("unexpected number of grants created")
.isEqualTo(initialGrantNames.length + 10);
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {

View File

@ -3,6 +3,7 @@ package net.hostsharing.hsadminng.hs.office.partner;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import java.util.UUID;
import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.LEGAL; import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.LEGAL;

View File

@ -27,6 +27,7 @@ import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.grantD
import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf; import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf;
import static net.hostsharing.test.JpaAttempt.attempt; import static net.hostsharing.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest @DataJpaTest
@Import( { Context.class, JpaAttempt.class }) @Import( { Context.class, JpaAttempt.class })
@ -243,6 +244,10 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTest {
final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll()); final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll());
final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll()); final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll());
final var givenPerson = givenSomeTemporaryPerson("selfregistered-user-drew@hostsharing.org"); final var givenPerson = givenSomeTemporaryPerson("selfregistered-user-drew@hostsharing.org");
assumeThat(rawRoleRepo.findAll().size()).as("unexpected number of roles created")
.isEqualTo(initialRoleNames.size() + 3);
assumeThat(rawGrantRepo.findAll().size()).as("unexpected number of grants created")
.isEqualTo(initialGrantNames.size() + 7);
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.person; package net.hostsharing.hsadminng.hs.office.person;
import java.util.UUID;
public class TestHsOfficePerson { public class TestHsOfficePerson {

View File

@ -25,6 +25,7 @@ import java.util.UUID;
import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid; import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid;
import static net.hostsharing.test.JsonMatcher.lenientlyEquals; import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.startsWith;

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.sepamandate; package net.hostsharing.hsadminng.hs.office.sepamandate;
import com.vladmihalcea.hibernate.type.range.Range;
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -31,6 +31,7 @@ import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.grantD
import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf; import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf;
import static net.hostsharing.test.JpaAttempt.attempt; import static net.hostsharing.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest @DataJpaTest
@Import({ Context.class, JpaAttempt.class }) @Import({ Context.class, JpaAttempt.class })
@ -345,7 +346,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest {
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
context("bankaccount-admin@ThirdOHG.example.com"); context("bankaccount-admin@ThirdOHG.example.com");
assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent(); assumeThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent();
sepaMandateRepo.deleteByUuid(givenSepaMandate.getUuid()); sepaMandateRepo.deleteByUuid(givenSepaMandate.getUuid());
}); });

View File

@ -1,88 +0,0 @@
package net.hostsharing.hsadminng.mapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import jakarta.persistence.EntityManager;
import java.util.UUID;
import java.util.function.Function;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
class PostgresArrayIntegrationTest {
@Autowired
EntityManager em;
@Test
void shouldCreateEmptyArray() {
em.createNativeQuery("""
create or replace function returnEmptyArray()
returns text[]
stable leakproof
language plpgsql as $$
declare
emptyArray text[] = '{}';
begin
return emptyArray;
end; $$;
""").executeUpdate();
final byte[] pgArray = (byte[]) em.createNativeQuery("SELECT returnEmptyArray()", String[].class).getSingleResult();
final String[] result = PostgresArray.fromPostgresArray(pgArray, String.class, Function.identity());
assertThat(result).isEmpty();
}
@Test
void shouldCreateStringArray() {
em.createNativeQuery("""
create or replace function returnStringArray()
returns varchar(63)[]
stable leakproof
language plpgsql as $$
declare
text1 text = 'one';
text2 text = 'two, three';
text3 text = 'four; five';
text4 text = 'say "Hello" to me';
begin
return array[text1, text2, text3, null, text4];
end; $$;
""").executeUpdate();
final byte[] pgArray = (byte[]) em.createNativeQuery("SELECT returnStringArray()", String[].class).getSingleResult();
final String[] result = PostgresArray.fromPostgresArray(pgArray, String.class, Function.identity());
assertThat(result).containsExactly("one", "two, three", "four; five", null, "say \"Hello\" to me");
}
@Test
void shouldCreateUUidArray() {
em.createNativeQuery("""
create or replace function returnUuidArray()
returns uuid[]
stable leakproof
language plpgsql as $$
declare
uuid1 UUID = 'f47ac10b-58cc-4372-a567-0e02b2c3d479';
uuid2 UUID = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
uuid3 UUID = '01234567-89ab-cdef-0123-456789abcdef';
begin
return ARRAY[uuid1, uuid2, null, uuid3];
end; $$;
""").executeUpdate();
final byte[] pgArray = (byte[]) em.createNativeQuery("SELECT returnUuidArray()", UUID[].class).getSingleResult();
final UUID[] result = PostgresArray.fromPostgresArray(pgArray, UUID.class, UUID::fromString);
assertThat(result).containsExactly(
UUID.fromString("f47ac10b-58cc-4372-a567-0e02b2c3d479"),
UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8"),
null,
UUID.fromString("01234567-89ab-cdef-0123-456789abcdef"));
}
}

View File

@ -26,6 +26,7 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
@ -342,7 +343,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
} }
private void assumeCreated(final ValidatableResponse response) { private void assumeCreated(final ValidatableResponse response) {
assertThat(response.extract().response().statusCode()).isEqualTo(201); assumeThat(response.extract().response().statusCode()).isEqualTo(201);
} }
class Subject { class Subject {
@ -478,7 +479,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
} }
private void assumeGrantExists(final Subject grantingSubject, final String expectedGrant) { private void assumeGrantExists(final Subject grantingSubject, final String expectedGrant) {
assertThat(findAllGrantsOf(grantingSubject)) assumeThat(findAllGrantsOf(grantingSubject))
.extracting(RbacGrantEntity::toDisplay) .extracting(RbacGrantEntity::toDisplay)
.contains(expectedGrant); .contains(expectedGrant);
} }

View File

@ -25,6 +25,7 @@ import java.util.UUID;
import static net.hostsharing.test.JpaAttempt.attempt; import static net.hostsharing.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest @DataJpaTest
@Import( { Context.class, JpaAttempt.class }) @Import( { Context.class, JpaAttempt.class })
@ -185,8 +186,9 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
// when // when
context("customer-admin@xxx.example.com", "test_customer#xxx.admin"); context("customer-admin@xxx.example.com", "test_customer#xxx.admin");
final var revokeAttempt = attempt(em, () -> final var revokeAttempt = attempt(em, () -> {
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId())); rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
});
// then // then
context("customer-admin@xxx.example.com", "test_customer#xxx.admin"); context("customer-admin@xxx.example.com", "test_customer#xxx.admin");
@ -206,8 +208,9 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
// when // when
context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00.admin"); context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00.admin");
final var revokeAttempt = attempt(em, () -> final var revokeAttempt = attempt(em, () -> {
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId())); rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
});
// then // then
assertThat(revokeAttempt.caughtExceptionsRootCause()).isNull(); assertThat(revokeAttempt.caughtExceptionsRootCause()).isNull();
@ -227,8 +230,9 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
// when // when
context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00.admin"); context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00.admin");
final var revokeAttempt = attempt(em, () -> final var revokeAttempt = attempt(em, () -> {
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId())); rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
});
// then // then
revokeAttempt.assertExceptionWithRootCauseMessage( revokeAttempt.assertExceptionWithRootCauseMessage(
@ -251,10 +255,10 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
rbacGrantRepository.save(grant) rbacGrantRepository.save(grant)
); );
assertThat(grantAttempt.caughtException()).isNull(); assumeThat(grantAttempt.caughtException()).isNull();
assertThat(rawRbacGrantRepository.findAll()) assumeThat(rawRbacGrantRepository.findAll())
.extracting(RawRbacGrantEntity::toDisplay) .extracting(RawRbacGrantEntity::toDisplay)
.contains("{ grant role %s to user %s by %s and assume }".formatted( .contains("{ grant role %s to user %s by role %s and assume }".formatted(
with.grantedRole, with.granteeUserName, with.assumedRole with.grantedRole, with.granteeUserName, with.assumedRole
)); ));

View File

@ -61,6 +61,11 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
assertThat(result.returnedValue()).isNotNull() assertThat(result.returnedValue()).isNotNull()
.extracting(RbacUserEntity::getUuid).isEqualTo(givenUuid); .extracting(RbacUserEntity::getUuid).isEqualTo(givenUuid);
assertThat(rbacUserRepository.findByName(result.returnedValue().getName())).isNotNull(); assertThat(rbacUserRepository.findByName(result.returnedValue().getName())).isNotNull();
// jpaAttempt.transacted(() -> {
// context(givenUser.getName());
// assertThat(em.find(RbacUserEntity.class, givenUser.getUuid()))
// .isNotNull().extracting(RbacUserEntity::getName).isEqualTo(givenUser.getName());
// }).assertSuccessful();
} }
} }
@ -82,6 +87,9 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
// then the user is deleted // then the user is deleted
result.assertSuccessful(); result.assertSuccessful();
assertThat(rbacUserRepository.findByName(givenUser.getName())).isNull(); assertThat(rbacUserRepository.findByName(givenUser.getName())).isNull();
// jpaAttempt.transacted(() -> {
// assertThat(rbacUserRepository.findByName(givenUser.getName())).isNull();
// }).assertSuccessful();
} }
} }

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.test.cust; package net.hostsharing.hsadminng.test.cust;
import static java.util.UUID.randomUUID;
public class TestCustomer { public class TestCustomer {

View File

@ -16,7 +16,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.UUID; import java.util.UUID;
import static java.lang.String.format; import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assumptions.assumeThat;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
@ -85,8 +85,7 @@ class TestPackageControllerAcceptanceTest {
@Test @Test
void withDescriptionUpdatesDescription() { void withDescriptionUpdatesDescription() {
assertThat(getDescriptionOfPackage("xxx00")) assumeThat(getDescriptionOfPackage("xxx00"))
.as("precondition failed")
.isEqualTo("Here you can add your own description of package xxx00."); .isEqualTo("Here you can add your own description of package xxx00.");
final var randomDescription = RandomStringUtils.randomAlphanumeric(80); final var randomDescription = RandomStringUtils.randomAlphanumeric(80);
@ -118,8 +117,7 @@ class TestPackageControllerAcceptanceTest {
@Test @Test
void withNullDescriptionUpdatesDescriptionToNull() { void withNullDescriptionUpdatesDescriptionToNull() {
assertThat(getDescriptionOfPackage("xxx01")) assumeThat(getDescriptionOfPackage("xxx01"))
.as("precondition failed")
.isEqualTo("Here you can add your own description of package xxx01."); .isEqualTo("Here you can add your own description of package xxx01.");
// @formatter:off // @formatter:off
@ -148,8 +146,7 @@ class TestPackageControllerAcceptanceTest {
@Test @Test
void withoutDescriptionDoesNothing() { void withoutDescriptionDoesNothing() {
assertThat(getDescriptionOfPackage("xxx02")) assumeThat(getDescriptionOfPackage("xxx02"))
.as("precondition failed")
.isEqualTo("Here you can add your own description of package xxx02."); .isEqualTo("Here you can add your own description of package xxx02.");
// @formatter:off // @formatter:off

View File

@ -12,6 +12,7 @@ import java.util.Optional;
import java.util.function.Supplier; import java.util.function.Supplier;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
/** /**
* Wraps the 'when' part of a DataJpaTest to improve readability of tests. * Wraps the 'when' part of a DataJpaTest to improve readability of tests.
@ -137,7 +138,7 @@ public class JpaAttempt {
} }
public JpaResult<T> assumeSuccessful() { public JpaResult<T> assumeSuccessful() {
assertThat(exception).as(firstRootCauseMessageLineOf(exception)).isNull(); assumeThat(exception).as(firstRootCauseMessageLineOf(exception)).isNull();
return this; return this;
} }