Compare commits
29 Commits
e5e9f26856
...
5c651891c3
Author | SHA1 | Date | |
---|---|---|---|
5c651891c3 | |||
|
727644736d | ||
|
1f49970e66 | ||
|
07dbc45c80 | ||
|
b15464bed5 | ||
|
650ae365e5 | ||
|
d97827c01e | ||
|
e9dde69c40 | ||
|
7f98bbde64 | ||
|
ea130581a3 | ||
|
f8de575b77 | ||
|
d2f9f0ae8f | ||
|
4c44f42b79 | ||
|
73f147c557 | ||
|
378e1ec584 | ||
|
ec53934f30 | ||
|
063fcf90a3 | ||
|
51aebc65b2 | ||
|
287c1ad9dc | ||
|
53ffe9e738 | ||
|
f1e977c905 | ||
|
95457980d8 | ||
|
70d73d8caa | ||
|
bdac905958 | ||
|
1c19afefa6 | ||
|
0edc2cca91 | ||
|
51c658cdc7 | ||
|
796d1a0991 | ||
|
5986ca26fe |
2
.aliases
2
.aliases
@ -44,7 +44,7 @@ alias podman-stop='systemctl --user disable --now podman.socket && systemctl --u
|
|||||||
alias podman-use='export DOCKER_HOST="unix:///run/user/$UID/podman/podman.sock"; export TESTCONTAINERS_RYUK_DISABLED=true'
|
alias podman-use='export DOCKER_HOST="unix:///run/user/$UID/podman/podman.sock"; export TESTCONTAINERS_RYUK_DISABLED=true'
|
||||||
|
|
||||||
alias gw=gradleWrapper
|
alias gw=gradleWrapper
|
||||||
alias pg-sql-run='docker run --name hsadmin-ng-postgres -e POSTGRES_PASSWORD=password -p 5432:5432 -d postgres:13.7-bullseye'
|
alias pg-sql-run='docker run --name hsadmin-ng-postgres -e POSTGRES_PASSWORD=password -p 5432:5432 -d postgres:15.5-bookworm'
|
||||||
alias pg-sql-stop='docker stop hsadmin-ng-postgres'
|
alias pg-sql-stop='docker stop hsadmin-ng-postgres'
|
||||||
alias pg-sql-start='docker container start hsadmin-ng-postgres'
|
alias pg-sql-start='docker container start hsadmin-ng-postgres'
|
||||||
alias pg-sql-remove='docker rm hsadmin-ng-postgres'
|
alias pg-sql-remove='docker rm hsadmin-ng-postgres'
|
||||||
|
40
README.md
40
README.md
@ -20,6 +20,7 @@ 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)
|
||||||
@ -39,6 +40,7 @@ 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. -->
|
||||||
|
|
||||||
@ -50,7 +52,7 @@ Everything is tested on _Ubuntu Linux 22.04_ and _MacOS Monterey (12.4)_.
|
|||||||
To be able to build and run the Java Spring Boot application, you need the following tools:
|
To be able to build and run the Java Spring Boot application, you need the following tools:
|
||||||
|
|
||||||
- Docker 20.x (on MacOS you also need *Docker Desktop* or similar)
|
- Docker 20.x (on MacOS you also need *Docker Desktop* or similar)
|
||||||
- PostgreSQL Server 13.7-bullseye
|
- PostgreSQL Server 15.5-bookworm
|
||||||
(see instructions below to install and run in Docker)
|
(see instructions below to install and run in Docker)
|
||||||
- Java JDK at least recent enough to run Gradle
|
- Java JDK at least recent enough to run Gradle
|
||||||
(JDK 17.x will be automatically installed by Gradle toolchain support)
|
(JDK 17.x will be automatically installed by Gradle toolchain support)
|
||||||
@ -133,14 +135,14 @@ But the easiest way to run PostgreSQL is via Docker.
|
|||||||
|
|
||||||
Initially, pull an image compatible to current PostgreSQL version of Hostsharing:
|
Initially, pull an image compatible to current PostgreSQL version of Hostsharing:
|
||||||
|
|
||||||
docker pull postgres:13.7-bullseye
|
docker pull postgres:15.5-bookworm
|
||||||
|
|
||||||
<big>**⚠**</big>
|
<big>**⚠**</big>
|
||||||
If we switch the version, please also amend the documentation as well as the aliases file. Thanks!
|
If we switch the version, please also amend the documentation as well as the aliases file. Thanks!
|
||||||
|
|
||||||
Create and run a container with the given PostgreSQL version:
|
Create and run a container with the given PostgreSQL version:
|
||||||
|
|
||||||
docker run --name hsadmin-ng-postgres -e POSTGRES_PASSWORD=password -p 5432:5432 -d postgres:13.7-bullseye
|
docker run --name hsadmin-ng-postgres -e POSTGRES_PASSWORD=password -p 5432:5432 -d postgres:15.5-bookworm
|
||||||
|
|
||||||
# or via alias:
|
# or via alias:
|
||||||
pg-sql-run
|
pg-sql-run
|
||||||
@ -199,7 +201,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 | sed -e 's/^ //g'
|
md-toc <README.md 2 4 | cut -c5-'
|
||||||
```
|
```
|
||||||
|
|
||||||
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:
|
||||||
@ -233,12 +235,19 @@ sudo apt install graphviz
|
|||||||
|
|
||||||
##### Ubuntu Linux command line
|
##### Ubuntu Linux command line
|
||||||
|
|
||||||
```sh
|
1. Install Pandoc with some extra libraries:
|
||||||
|
```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
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
2. Install mermaid-filter, e.g. this way:
|
||||||
pandoc --filter pandoc-plantuml rbac.md -o rbac.pdf
|
```shell
|
||||||
|
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
|
||||||
@ -247,7 +256,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 the main reason Mermaid ist used too.
|
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.
|
||||||
|
|
||||||
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.
|
||||||
@ -271,8 +280,11 @@ If not, you need to install some tooling.
|
|||||||
|
|
||||||
##### for IntelliJ IDEA (or derived products)
|
##### for IntelliJ IDEA (or derived products)
|
||||||
|
|
||||||
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).
|
1. Activate the bundled Jebrains Markdown PlantUML Extension via
|
||||||
|
[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
|
||||||
|
|
||||||
@ -282,13 +294,23 @@ 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.
|
||||||
|
81
build.gradle
81
build.gradle
@ -1,15 +1,15 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'org.springframework.boot' version '3.0.0'
|
id 'org.springframework.boot' version '3.1.7'
|
||||||
id 'io.spring.dependency-management' version '1.1.0'
|
id 'io.spring.dependency-management' version '1.1.4'
|
||||||
id 'io.openapiprocessor.openapi-processor' version '2022.2'
|
id 'io.openapiprocessor.openapi-processor' version '2023.2'
|
||||||
id 'com.github.jk1.dependency-license-report' version '2.1'
|
id 'com.github.jk1.dependency-license-report' version '2.5'
|
||||||
id "org.owasp.dependencycheck" version "7.3.0"
|
id "org.owasp.dependencycheck" version "9.0.7"
|
||||||
id "com.diffplug.spotless" version "6.11.0"
|
id "com.diffplug.spotless" version "6.23.3"
|
||||||
id 'jacoco'
|
id 'jacoco'
|
||||||
id 'info.solidsoft.pitest' version '1.9.0'
|
id 'info.solidsoft.pitest' version '1.15.0'
|
||||||
id 'se.patrikerdes.use-latest-versions' version '0.2.18'
|
id 'se.patrikerdes.use-latest-versions' version '0.2.18'
|
||||||
id 'com.github.ben-manes.versions' version '0.43.0'
|
id 'com.github.ben-manes.versions' version '0.50.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'net.hostsharing'
|
group = 'net.hostsharing'
|
||||||
@ -17,7 +17,7 @@ version = '0.0.1-SNAPSHOT'
|
|||||||
|
|
||||||
wrapper {
|
wrapper {
|
||||||
distributionType = Wrapper.DistributionType.BIN
|
distributionType = Wrapper.DistributionType.BIN
|
||||||
gradleVersion = '7.5'
|
gradleVersion = '8.5'
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
@ -42,7 +42,7 @@ repositories {
|
|||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
languageVersion = JavaLanguageVersion.of(21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,31 +50,41 @@ 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'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
|
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||||
implementation 'com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.8.1'
|
implementation 'com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.9.1'
|
||||||
implementation 'org.springdoc:springdoc-openapi:2.0.0-M7'
|
implementation 'org.springdoc:springdoc-openapi:2.3.0'
|
||||||
implementation 'org.liquibase:liquibase-core'
|
implementation 'org.postgresql:postgresql:42.7.1'
|
||||||
implementation 'com.vladmihalcea:hibernate-types-60:2.20.0'
|
implementation 'org.liquibase:liquibase-core:4.25.1'
|
||||||
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4'
|
implementation 'com.vladmihalcea:hibernate-types-60:2.21.1'
|
||||||
implementation 'org.openapitools:jackson-databind-nullable:0.2.4'
|
implementation 'io.hypersistence:hypersistence-utils-hibernate-62:3.7.0'
|
||||||
implementation 'org.apache.commons:commons-text:1.10.0'
|
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1'
|
||||||
implementation 'org.modelmapper:modelmapper:3.1.0'
|
implementation 'org.openapitools:jackson-databind-nullable:0.2.6'
|
||||||
implementation 'org.iban4j:iban4j:3.2.3-RELEASE'
|
implementation 'org.apache.commons:commons-text:1.11.0'
|
||||||
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
|
implementation 'org.modelmapper:modelmapper:3.2.0'
|
||||||
|
implementation 'org.iban4j:iban4j:3.2.7-RELEASE'
|
||||||
|
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'
|
||||||
|
|
||||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||||
|
|
||||||
runtimeOnly 'org.postgresql:postgresql'
|
|
||||||
|
|
||||||
annotationProcessor 'org.projectlombok:lombok'
|
annotationProcessor 'org.projectlombok:lombok'
|
||||||
testAnnotationProcessor 'org.projectlombok:lombok'
|
testAnnotationProcessor 'org.projectlombok:lombok'
|
||||||
@ -82,11 +92,12 @@ dependencies {
|
|||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
testImplementation 'org.testcontainers:testcontainers'
|
testImplementation 'org.testcontainers:testcontainers'
|
||||||
testImplementation 'org.testcontainers:junit-jupiter'
|
testImplementation 'org.testcontainers:junit-jupiter'
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
testImplementation 'org.testcontainers:postgresql'
|
testImplementation 'org.testcontainers:postgresql'
|
||||||
testImplementation 'com.tngtech.archunit:archunit-junit5:1.0.0'
|
testImplementation 'com.tngtech.archunit:archunit-junit5:1.2.1'
|
||||||
testImplementation 'io.rest-assured:spring-mock-mvc'
|
testImplementation 'io.rest-assured:spring-mock-mvc'
|
||||||
testImplementation 'org.hamcrest:hamcrest-core:2.2'
|
testImplementation 'org.hamcrest:hamcrest-core:2.2'
|
||||||
testImplementation 'org.pitest:pitest-junit5-plugin:1.1.0'
|
testImplementation 'org.pitest:pitest-junit5-plugin:1.2.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyManagement {
|
dependencyManagement {
|
||||||
@ -171,7 +182,7 @@ openApiGenerate.dependsOn processSpring
|
|||||||
// Spotless Code Formatting
|
// Spotless Code Formatting
|
||||||
spotless {
|
spotless {
|
||||||
java {
|
java {
|
||||||
// removeUnusedImports() TODO: reactivate once it can deal with multi-line-strings
|
removeUnusedImports()
|
||||||
indentWithSpaces(4)
|
indentWithSpaces(4)
|
||||||
endWithNewline()
|
endWithNewline()
|
||||||
toggleOffOn()
|
toggleOffOn()
|
||||||
@ -183,14 +194,24 @@ spotless {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 {
|
||||||
cveValidForHours=4
|
nvd {
|
||||||
|
apiKey = project.property('OWASP_API_KEY') // set it in ~/.gradle/gradle.properties
|
||||||
|
delay = 16000
|
||||||
|
}
|
||||||
format = 'ALL'
|
format = 'ALL'
|
||||||
suppressionFile = 'etc/owasp-dependency-check-suppression.xml'
|
suppressionFile = 'etc/owasp-dependency-check-suppression.xml'
|
||||||
failOnError = true
|
failOnError = true
|
||||||
failBuildOnCVSS = 7
|
failBuildOnCVSS = 5
|
||||||
}
|
}
|
||||||
project.tasks.check.dependsOn(dependencyCheckAnalyze)
|
project.tasks.check.dependsOn(dependencyCheckAnalyze)
|
||||||
project.tasks.dependencyCheckAnalyze.doFirst { // Why not doLast? See README.md!
|
project.tasks.dependencyCheckAnalyze.doFirst { // Why not doLast? See README.md!
|
||||||
@ -207,7 +228,7 @@ project.tasks.check.dependsOn(checkLicense)
|
|||||||
|
|
||||||
// JaCoCo Test Code Coverage
|
// JaCoCo Test Code Coverage
|
||||||
jacoco {
|
jacoco {
|
||||||
toolVersion = "0.8.8"
|
toolVersion = "0.8.10"
|
||||||
}
|
}
|
||||||
test {
|
test {
|
||||||
finalizedBy jacocoTestReport // generate report after tests
|
finalizedBy jacocoTestReport // generate report after tests
|
||||||
@ -286,7 +307,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.9.9'
|
pitestVersion = '1.15.3'
|
||||||
junit5PluginVersion = '1.1.0'
|
junit5PluginVersion = '1.1.0'
|
||||||
|
|
||||||
threads = 4
|
threads = 4
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
{ "moduleLicense": "BSD License" },
|
{ "moduleLicense": "BSD License" },
|
||||||
{ "moduleLicense": "BSD-2-Clause" },
|
{ "moduleLicense": "BSD-2-Clause" },
|
||||||
|
{ "moduleLicense": "BSD-3-Clause" },
|
||||||
{ "moduleLicense": "The BSD License" },
|
{ "moduleLicense": "The BSD License" },
|
||||||
|
|
||||||
{ "moduleLicense": "CDDL 1.1" },
|
{ "moduleLicense": "CDDL 1.1" },
|
||||||
|
@ -14,4 +14,52 @@
|
|||||||
<packageUrl regex="true">^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$</packageUrl>
|
<packageUrl regex="true">^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$</packageUrl>
|
||||||
<cve>CVE-2022-42003</cve>
|
<cve>CVE-2022-42003</cve>
|
||||||
</suppress>
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<notes><![CDATA[
|
||||||
|
We don't parse external XML.
|
||||||
|
]]></notes>
|
||||||
|
<packageUrl regex="true">^pkg:maven/org\.eclipse\.angus/angus\-activation@.*$</packageUrl>
|
||||||
|
<cpe>cpe:/a:eclipse:eclipse_ide</cpe>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<notes><![CDATA[
|
||||||
|
We don't parse external XML.
|
||||||
|
]]></notes>
|
||||||
|
<packageUrl regex="true">^pkg:maven/jakarta\.activation/jakarta\.activation\-api@.*$</packageUrl>
|
||||||
|
<cpe>cpe:/a:eclipse:eclipse_ide</cpe>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<notes><![CDATA[
|
||||||
|
Cyclic references are not possible if file comes in JSON text format.
|
||||||
|
]]></notes>
|
||||||
|
<packageUrl regex="true">^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$</packageUrl>
|
||||||
|
<cpe>cpe:/a:fasterxml:jackson-databind</cpe>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<notes><![CDATA[
|
||||||
|
As far as I see Criteria.parse(...) cannot be reached with external data.
|
||||||
|
]]></notes>
|
||||||
|
<packageUrl regex="true">^pkg:maven/com\.jayway\.jsonpath/json\-path@.*$</packageUrl>
|
||||||
|
<vulnerabilityName>CVE-2023-51074</vulnerabilityName>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<notes><![CDATA[
|
||||||
|
Internal tooling, not exposed to the Internet.
|
||||||
|
]]></notes>
|
||||||
|
<packageUrl regex="true">^pkg:maven/org\.pitest/pitest\-command\-line@.*$</packageUrl>
|
||||||
|
<cpe>cpe:/a:line:line</cpe>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<notes><![CDATA[
|
||||||
|
Spring Boot 3.1.x has a transient dependency to snakeyaml 1.3
|
||||||
|
which contains this vulnerability.
|
||||||
|
|
||||||
|
We've explicitly bumped to 2.2, but the vulnerability 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>
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
41
gradlew
vendored
41
gradlew
vendored
@ -55,7 +55,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@ -80,13 +80,11 @@ do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@ -133,22 +131,29 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
# double quotes to make sure that they get re-expanded; and
|
|
||||||
# * put everything else in single quotes, so that it's not re-expanded.
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
@ -205,6 +214,12 @@ set -- \
|
|||||||
org.gradle.wrapper.GradleWrapperMain \
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
# Use "xargs" to parse quoted args.
|
||||||
#
|
#
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
11
gradlew.bat
vendored
11
gradlew.bat
vendored
@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
|
|||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%"=="" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
exit /b 1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
@ -7,4 +7,28 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
components {
|
||||||
|
all {
|
||||||
|
allVariants {
|
||||||
|
withDependencies {
|
||||||
|
removeAll {
|
||||||
|
// Spring Boot 3.1.x has a transient dependency to snakeyaml 1.3
|
||||||
|
// which contains a severe vulnerability.
|
||||||
|
// Here we remove this transient dependency and in build.gradle
|
||||||
|
// we add an explicit dependency to snakeyaml 2.2,
|
||||||
|
// which does not have this vulnerability anymore.
|
||||||
|
//
|
||||||
|
// TODO: Check Once we are on SpringBoot 3.2.x, check if this exclude
|
||||||
|
// is still neccessary. If not:
|
||||||
|
// Remove it // 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'
|
||||||
|
@ -8,7 +8,7 @@ import static org.hibernate.dialect.DatabaseVersion.make;
|
|||||||
public class PostgresCustomDialect extends PostgreSQLDialect {
|
public class PostgresCustomDialect extends PostgreSQLDialect {
|
||||||
|
|
||||||
public PostgresCustomDialect() {
|
public PostgresCustomDialect() {
|
||||||
super(make(13, 7));
|
super(make(15, 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,11 @@ import java.util.Collections;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static java.util.function.Predicate.not;
|
import static java.util.function.Predicate.not;
|
||||||
|
import static net.hostsharing.hsadminng.mapper.PostgresArray.fromPostgresArray;
|
||||||
import static org.springframework.transaction.annotation.Propagation.MANDATORY;
|
import static org.springframework.transaction.annotation.Propagation.MANDATORY;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -81,11 +83,14 @@ public class Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String[] getAssumedRoles() {
|
public String[] getAssumedRoles() {
|
||||||
return (String[]) em.createNativeQuery("select assumedRoles() as roles", String[].class).getSingleResult();
|
final byte[] result = (byte[]) em.createNativeQuery("select assumedRoles() as roles", String[].class).getSingleResult();
|
||||||
|
return fromPostgresArray(result, String.class, Function.identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID[] currentSubjectsUuids() {
|
public UUID[] currentSubjectsUuids() {
|
||||||
return (UUID[]) em.createNativeQuery("select currentSubjectsUuids() as uuids", UUID[].class).getSingleResult();
|
final byte[] result = (byte[]) em.createNativeQuery("select currentSubjectsUuids() as uuids", UUID[].class)
|
||||||
|
.getSingleResult();
|
||||||
|
return fromPostgresArray(result, UUID.class, UUID::fromString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getCallerMethodNameFromStackFrame(final int skipFrames) {
|
public static String getCallerMethodNameFromStackFrame(final int skipFrames) {
|
||||||
|
@ -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(:label, '%')
|
OR c.label like concat(cast(:label as text), '%')
|
||||||
""")
|
""")
|
||||||
List<HsOfficeContactEntity> findContactByOptionalLabelLike(String label);
|
List<HsOfficeContactEntity> findContactByOptionalLabelLike(String label);
|
||||||
|
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
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;
|
||||||
@ -47,7 +45,6 @@ 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")
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
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;
|
||||||
|
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
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;
|
||||||
@ -43,7 +41,6 @@ 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")
|
||||||
|
@ -19,15 +19,15 @@ public interface HsOfficeDebitorRepository extends Repository<HsOfficeDebitorEnt
|
|||||||
|
|
||||||
@Query("""
|
@Query("""
|
||||||
SELECT debitor FROM HsOfficeDebitorEntity debitor
|
SELECT debitor FROM HsOfficeDebitorEntity debitor
|
||||||
JOIN HsOfficePartnerEntity partner ON partner.uuid = debitor.partner
|
JOIN HsOfficePartnerEntity partner ON partner.uuid = debitor.partner.uuid
|
||||||
JOIN HsOfficePersonEntity person ON person.uuid = partner.person
|
JOIN HsOfficePersonEntity person ON person.uuid = partner.person.uuid
|
||||||
JOIN HsOfficeContactEntity contact ON contact.uuid = debitor.billingContact
|
JOIN HsOfficeContactEntity contact ON contact.uuid = debitor.billingContact.uuid
|
||||||
WHERE :name is null
|
WHERE :name is null
|
||||||
OR partner.details.birthName like concat(:name, '%')
|
OR partner.details.birthName like concat(cast(:name as text), '%')
|
||||||
OR person.tradeName like concat(:name, '%')
|
OR person.tradeName like concat(cast(:name as text), '%')
|
||||||
OR person.familyName like concat(:name, '%')
|
OR person.familyName like concat(cast(:name as text), '%')
|
||||||
OR person.givenName like concat(:name, '%')
|
OR person.givenName like concat(cast(:name as text), '%')
|
||||||
OR contact.label like concat(:name, '%')
|
OR contact.label like concat(cast(:name as text), '%')
|
||||||
""")
|
""")
|
||||||
List<HsOfficeDebitorEntity> findDebitorByOptionalNameLike(String name);
|
List<HsOfficeDebitorEntity> findDebitorByOptionalNameLike(String name);
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
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.*;
|
||||||
@ -61,7 +60,6 @@ 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) {
|
||||||
|
@ -13,14 +13,14 @@ public interface HsOfficePartnerRepository extends Repository<HsOfficePartnerEnt
|
|||||||
|
|
||||||
@Query("""
|
@Query("""
|
||||||
SELECT partner FROM HsOfficePartnerEntity partner
|
SELECT partner FROM HsOfficePartnerEntity partner
|
||||||
JOIN HsOfficeContactEntity contact ON contact.uuid = partner.contact
|
JOIN HsOfficeContactEntity contact ON contact.uuid = partner.contact.uuid
|
||||||
JOIN HsOfficePersonEntity person ON person.uuid = partner.person
|
JOIN HsOfficePersonEntity person ON person.uuid = partner.person.uuid
|
||||||
WHERE :name is null
|
WHERE :name is null
|
||||||
OR partner.details.birthName like concat(:name, '%')
|
OR partner.details.birthName like concat(cast(:name as text), '%')
|
||||||
OR contact.label like concat(:name, '%')
|
OR contact.label like concat(cast(:name as text), '%')
|
||||||
OR person.tradeName like concat(:name, '%')
|
OR person.tradeName like concat(cast(:name as text), '%')
|
||||||
OR person.givenName like concat(:name, '%')
|
OR person.givenName like concat(cast(:name as text), '%')
|
||||||
OR person.familyName like concat(:name, '%')
|
OR person.familyName like concat(cast(:name as text), '%')
|
||||||
""")
|
""")
|
||||||
List<HsOfficePartnerEntity> findPartnerByOptionalNameLike(String name);
|
List<HsOfficePartnerEntity> findPartnerByOptionalNameLike(String name);
|
||||||
|
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
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;
|
||||||
@ -37,7 +35,6 @@ 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")
|
||||||
|
@ -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(:name, '%')
|
OR p.tradeName like concat(cast(:name as text), '%')
|
||||||
OR p.givenName like concat(:name, '%')
|
OR p.givenName like concat(cast(:name as text), '%')
|
||||||
OR p.familyName like concat(:name, '%')
|
OR p.familyName like concat(cast(:name as text), '%')
|
||||||
""")
|
""")
|
||||||
List<HsOfficePersonEntity> findPersonByOptionalNameLike(String name);
|
List<HsOfficePersonEntity> findPersonByOptionalNameLike(String name);
|
||||||
|
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
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;
|
||||||
@ -47,7 +45,6 @@ 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
|
||||||
|
@ -54,6 +54,7 @@ public class HsOfficeSepaMandateEntity implements Stringifyable {
|
|||||||
|
|
||||||
@Column(name = "validity", columnDefinition = "daterange")
|
@Column(name = "validity", columnDefinition = "daterange")
|
||||||
@Type(PostgreSQLRangeType.class)
|
@Type(PostgreSQLRangeType.class)
|
||||||
|
@Builder.Default
|
||||||
private Range<LocalDate> validity = Range.infinite(LocalDate.class);
|
private Range<LocalDate> validity = Range.infinite(LocalDate.class);
|
||||||
|
|
||||||
public void setValidFrom(final LocalDate validFrom) {
|
public void setValidFrom(final LocalDate validFrom) {
|
||||||
|
@ -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(:iban, '%')
|
OR mandate.bankAccount.iban like concat(cast(:iban as text), '%')
|
||||||
ORDER BY mandate.bankAccount.iban
|
ORDER BY mandate.bankAccount.iban
|
||||||
""")
|
""")
|
||||||
List<HsOfficeSepaMandateEntity> findSepaMandateByOptionalIban(String iban);
|
List<HsOfficeSepaMandateEntity> findSepaMandateByOptionalIban(String iban);
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
package net.hostsharing.hsadminng.mapper;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import org.postgresql.util.PGtokenizer;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class PostgresArray {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a byte[], as returned for a Postgres-array by native queries, to a Java array.
|
||||||
|
*
|
||||||
|
* <p>This example code worked with Hibernate 5 (Spring Boot 3.0.x):
|
||||||
|
* <pre><code>
|
||||||
|
* return (UUID[]) em.createNativeQuery("select currentSubjectsUuids() as uuids", UUID[].class).getSingleResult();
|
||||||
|
* </code></pre>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>With Hibernate 6 (Spring Boot 3.1.x), this utility method can be used like such:
|
||||||
|
* <pre><code>
|
||||||
|
* final byte[] result = (byte[]) em.createNativeQuery("select * from currentSubjectsUuids() as uuids", UUID[].class)
|
||||||
|
* .getSingleResult();
|
||||||
|
* return fromPostgresArray(result, UUID.class, UUID::fromString);
|
||||||
|
* </code></pre>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param pgArray the byte[] returned by a native query containing as rendered for a Postgres array
|
||||||
|
* @param elementClass the class of a single element of the Java array to be returned
|
||||||
|
* @param itemParser converts a string element to the specified elementClass
|
||||||
|
* @return a Java array containing the data from pgArray
|
||||||
|
* @param <T> type of a single element of the Java array
|
||||||
|
*/
|
||||||
|
public static <T> T[] fromPostgresArray(final byte[] pgArray, final Class<T> elementClass, final Function<String, T> itemParser) {
|
||||||
|
final var pgArrayLiteral = new String(pgArray, StandardCharsets.UTF_8);
|
||||||
|
if (pgArrayLiteral.length() == 2) {
|
||||||
|
return newGenericArray(elementClass, 0);
|
||||||
|
}
|
||||||
|
final PGtokenizer tokenizer = new PGtokenizer(pgArrayLiteral.substring(1, pgArrayLiteral.length()-1), ',');
|
||||||
|
tokenizer.remove("\"", "\"");
|
||||||
|
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 ) {
|
||||||
|
final String token = tokenizer.getToken(n);
|
||||||
|
if ( !"NULL".equals(token) ) {
|
||||||
|
array[n] = itemParser.apply(token.trim().replace("\\\"", "\""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static <T> T[] newGenericArray(final Class<T> elementClass, final int length) {
|
||||||
|
return (T[]) Array.newInstance(elementClass, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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(:userName, '%')
|
where :userName is null or u.name like concat(cast(:userName as text), '%')
|
||||||
order by u.name
|
order by u.name
|
||||||
""")
|
""")
|
||||||
List<RbacUserEntity> findByOptionalNameLike(String userName);
|
List<RbacUserEntity> findByOptionalNameLike(String userName);
|
||||||
|
@ -11,7 +11,6 @@ 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 {
|
||||||
|
@ -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(:prefix, '%')")
|
@Query("SELECT c FROM TestCustomerEntity c WHERE :prefix is null or c.prefix like concat(cast(:prefix as text), '%')")
|
||||||
List<TestCustomerEntity> findCustomerByOptionalPrefixLike(String prefix);
|
List<TestCustomerEntity> findCustomerByOptionalPrefixLike(String prefix);
|
||||||
|
|
||||||
TestCustomerEntity save(final TestCustomerEntity entity);
|
TestCustomerEntity save(final TestCustomerEntity entity);
|
||||||
|
@ -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(:name, '%')")
|
@Query("SELECT p FROM TestPackageEntity p WHERE :name is null or p.name like concat(cast(:name as text), '%')")
|
||||||
List<TestPackageEntity> findAllByOptionalNameLike(final String name);
|
List<TestPackageEntity> findAllByOptionalNameLike(final String name);
|
||||||
|
|
||||||
TestPackageEntity findByUuid(UUID packageUuid);
|
TestPackageEntity findByUuid(UUID packageUuid);
|
||||||
|
@ -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 letters.");
|
INVALID_CHARACTER("BEV-ODEB", "Bank code must contain only alphanumeric.");
|
||||||
|
|
||||||
private final String givenBic;
|
private final String givenBic;
|
||||||
private final String expectedErrorMessage;
|
private final String expectedErrorMessage;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.bankaccount;
|
package net.hostsharing.hsadminng.hs.office.bankaccount;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class TestHsOfficeBankAccount {
|
public class TestHsOfficeBankAccount {
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ 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 })
|
||||||
@ -237,10 +236,6 @@ 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(() -> {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.contact;
|
package net.hostsharing.hsadminng.hs.office.contact;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class TestHsOfficeContact {
|
public class TestHsOfficeContact {
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ 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(
|
||||||
@ -481,7 +480,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();
|
||||||
assumeThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact");
|
assertThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact");
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
@ -501,7 +500,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();
|
||||||
assumeThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact");
|
assertThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact");
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
|
@ -2,7 +2,6 @@ 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;
|
||||||
|
@ -32,7 +32,6 @@ 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 })
|
||||||
@ -327,7 +326,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");
|
||||||
assumeThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent();
|
assertThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent();
|
||||||
|
|
||||||
membershipRepo.deleteByUuid(givenMembership.getUuid());
|
membershipRepo.deleteByUuid(givenMembership.getUuid());
|
||||||
});
|
});
|
||||||
|
@ -3,7 +3,6 @@ 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;
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ 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;
|
||||||
|
|
||||||
@ -408,7 +407,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();
|
||||||
assumeThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact");
|
assertThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact");
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
@ -428,7 +427,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();
|
||||||
assumeThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact");
|
assertThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact");
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
|
@ -29,7 +29,6 @@ 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 })
|
||||||
@ -330,7 +329,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");
|
||||||
assumeThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent();
|
assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent();
|
||||||
|
|
||||||
partnerRepo.deleteByUuid(givenPartner.getUuid());
|
partnerRepo.deleteByUuid(givenPartner.getUuid());
|
||||||
});
|
});
|
||||||
@ -352,10 +351,6 @@ 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(() -> {
|
||||||
|
@ -3,7 +3,6 @@ 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;
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ 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 })
|
||||||
@ -244,10 +243,6 @@ 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(() -> {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.person;
|
package net.hostsharing.hsadminng.hs.office.person;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class TestHsOfficePerson {
|
public class TestHsOfficePerson {
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ 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;
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
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;
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@ 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 })
|
||||||
@ -346,7 +345,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");
|
||||||
assumeThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent();
|
assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent();
|
||||||
|
|
||||||
sepaMandateRepo.deleteByUuid(givenSepaMandate.getUuid());
|
sepaMandateRepo.deleteByUuid(givenSepaMandate.getUuid());
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
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"));
|
||||||
|
}
|
||||||
|
}
|
@ -26,7 +26,6 @@ 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.*;
|
||||||
@ -343,7 +342,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assumeCreated(final ValidatableResponse response) {
|
private void assumeCreated(final ValidatableResponse response) {
|
||||||
assumeThat(response.extract().response().statusCode()).isEqualTo(201);
|
assertThat(response.extract().response().statusCode()).isEqualTo(201);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Subject {
|
class Subject {
|
||||||
@ -479,7 +478,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assumeGrantExists(final Subject grantingSubject, final String expectedGrant) {
|
private void assumeGrantExists(final Subject grantingSubject, final String expectedGrant) {
|
||||||
assumeThat(findAllGrantsOf(grantingSubject))
|
assertThat(findAllGrantsOf(grantingSubject))
|
||||||
.extracting(RbacGrantEntity::toDisplay)
|
.extracting(RbacGrantEntity::toDisplay)
|
||||||
.contains(expectedGrant);
|
.contains(expectedGrant);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ 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 })
|
||||||
@ -186,9 +185,8 @@ 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");
|
||||||
@ -208,9 +206,8 @@ 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();
|
||||||
@ -230,9 +227,8 @@ 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(
|
||||||
@ -255,10 +251,10 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
|||||||
rbacGrantRepository.save(grant)
|
rbacGrantRepository.save(grant)
|
||||||
);
|
);
|
||||||
|
|
||||||
assumeThat(grantAttempt.caughtException()).isNull();
|
assertThat(grantAttempt.caughtException()).isNull();
|
||||||
assumeThat(rawRbacGrantRepository.findAll())
|
assertThat(rawRbacGrantRepository.findAll())
|
||||||
.extracting(RawRbacGrantEntity::toDisplay)
|
.extracting(RawRbacGrantEntity::toDisplay)
|
||||||
.contains("{ grant role %s to user %s by role %s and assume }".formatted(
|
.contains("{ grant role %s to user %s by %s and assume }".formatted(
|
||||||
with.grantedRole, with.granteeUserName, with.assumedRole
|
with.grantedRole, with.granteeUserName, with.assumedRole
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -61,11 +61,6 @@ 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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,9 +82,6 @@ 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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.hostsharing.hsadminng.test.cust;
|
package net.hostsharing.hsadminng.test.cust;
|
||||||
|
|
||||||
import static java.util.UUID.randomUUID;
|
|
||||||
|
|
||||||
public class TestCustomer {
|
public class TestCustomer {
|
||||||
|
|
||||||
|
@ -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.Assumptions.assumeThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
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,7 +85,8 @@ class TestPackageControllerAcceptanceTest {
|
|||||||
@Test
|
@Test
|
||||||
void withDescriptionUpdatesDescription() {
|
void withDescriptionUpdatesDescription() {
|
||||||
|
|
||||||
assumeThat(getDescriptionOfPackage("xxx00"))
|
assertThat(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);
|
||||||
@ -117,7 +118,8 @@ class TestPackageControllerAcceptanceTest {
|
|||||||
@Test
|
@Test
|
||||||
void withNullDescriptionUpdatesDescriptionToNull() {
|
void withNullDescriptionUpdatesDescriptionToNull() {
|
||||||
|
|
||||||
assumeThat(getDescriptionOfPackage("xxx01"))
|
assertThat(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
|
||||||
@ -146,7 +148,8 @@ class TestPackageControllerAcceptanceTest {
|
|||||||
@Test
|
@Test
|
||||||
void withoutDescriptionDoesNothing() {
|
void withoutDescriptionDoesNothing() {
|
||||||
|
|
||||||
assumeThat(getDescriptionOfPackage("xxx02"))
|
assertThat(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
|
||||||
|
@ -12,7 +12,6 @@ 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.
|
||||||
@ -138,7 +137,7 @@ public class JpaAttempt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JpaResult<T> assumeSuccessful() {
|
public JpaResult<T> assumeSuccessful() {
|
||||||
assumeThat(exception).as(firstRootCauseMessageLineOf(exception)).isNull();
|
assertThat(exception).as(firstRootCauseMessageLineOf(exception)).isNull();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user