Merge branch 'master' into readme-podman-storage
This commit is contained in:
commit
fef9fba073
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 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-start='docker container start hsadmin-ng-postgres'
|
||||
alias pg-sql-remove='docker rm hsadmin-ng-postgres'
|
||||
|
74
README.md
74
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)
|
||||
- [General Directory Structure](#general-directory-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)
|
||||
- [JaCoCo Test Code Coverage Check](#jacoco-test-code-coverage-check)
|
||||
- [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 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 Generate Database Table Diagrams?](#how-to-generate-database-table-diagrams?)
|
||||
- [Further Documentation](#further-documentation)
|
||||
<!-- generated TOC end. -->
|
||||
|
||||
@ -49,25 +51,28 @@ 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:
|
||||
|
||||
- Docker 20.x (on MacOS you also need *Docker Desktop* or similar)
|
||||
- PostgreSQL Server 13.7-bullseye
|
||||
- Docker 20.x (on MacOS you also need *Docker Desktop* or similar) or Podman
|
||||
- PostgreSQL Server 15.5-bookworm
|
||||
(see instructions below to install and run in Docker)
|
||||
- Java JDK at least recent enough to run Gradle
|
||||
(JDK 17.x will be automatically installed by Gradle toolchain support)
|
||||
- Gradle in some not too outdated version (7.4 will be installed via wrapper)
|
||||
|
||||
You also might need an IDE (e.g. *IntelliJ IDEA* or *Eclipse* or *VS Code* with *[STS](https://spring.io/tools)* and a GUI Frontend for *PostgreSQL* like *Postbird*.
|
||||
We recommend to use an IDE (e.g. *IntelliJ IDEA* or *Eclipse* or *VS Code* with *[STS](https://spring.io/tools)* and optionally a GUI Frontend for *PostgreSQL* like *Postbird*.
|
||||
|
||||
If you have at least Docker, the Java JDK and Gradle installed in appropriate versions and in your `PATH`, then you can start like this:
|
||||
If you have at least Docker and the Java JDK installed in appropriate versions and in your `PATH`, then you can start like this:
|
||||
|
||||
cd your-hsadmin-ng-directory
|
||||
|
||||
gradle wrapper # downloads the configured Gradle version into the project
|
||||
source .aliases # creates some comforable bash aliases, e.g. 'gw'='./gradlew'
|
||||
source .aliases # creates some comfortable bash aliases, e.g. 'gw'='./gradlew'
|
||||
gw # initially downloads the configured Gradle version into the project
|
||||
|
||||
gw test # compiles and runs unit- and integration-tests
|
||||
|
||||
# if the container has not been built yet, run this:
|
||||
pg-sql-run # downloads + runs PostgreSQL in a Docker container on localhost:5432
|
||||
# if the container has been built already, run this:
|
||||
pg-sql-start
|
||||
|
||||
gw bootRun # compiles and runs the application on localhost:8080
|
||||
|
||||
# the following command should reply with "pong":
|
||||
@ -130,14 +135,14 @@ But the easiest way to run PostgreSQL is via Docker.
|
||||
|
||||
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>
|
||||
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:
|
||||
|
||||
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:
|
||||
pg-sql-run
|
||||
@ -196,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:
|
||||
|
||||
```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:
|
||||
@ -230,12 +235,19 @@ sudo apt install graphviz
|
||||
|
||||
##### Ubuntu Linux command line
|
||||
|
||||
```sh
|
||||
sudo apt-get install pandoc texlive-latex-base texlive-fonts-recommended texlive-extra-utils texlive-latex-extra pandoc-plantuml-filter
|
||||
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
|
||||
```
|
||||
|
||||
```sh
|
||||
pandoc --filter pandoc-plantuml rbac.md -o rbac.pdf
|
||||
2. Install mermaid-filter, e.g. this way:
|
||||
```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
|
||||
@ -244,7 +256,7 @@ If you have figured out how it works, please add instructions above this section
|
||||
|
||||
#### 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?
|
||||
I mean a real graphic diagram, not just some markup code.
|
||||
@ -268,8 +280,11 @@ If not, you need to install some tooling.
|
||||
|
||||
##### 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
|
||||
|
||||
@ -279,13 +294,23 @@ If you have figured out how it works, please add instructions above this section
|
||||
|
||||
#### 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".
|
||||
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.
|
||||
Otherwise, *IntelliJ IDEA* can't see *Lombok* generated classes
|
||||
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
|
||||
|
||||
**jq**: a JSON formatter.
|
||||
@ -418,6 +443,21 @@ Underneath of rbac and hs, the structure is business oriented, NOT technical / l
|
||||
Some of these rules are checked with *ArchUnit* unit tests.
|
||||
|
||||
|
||||
### Run Tests from Command Line
|
||||
|
||||
Run all tests which have not yet been passed with the current source code:
|
||||
|
||||
```shell
|
||||
gw test
|
||||
```
|
||||
|
||||
Force running all tests:
|
||||
|
||||
```shell
|
||||
gw cleanTest test
|
||||
```
|
||||
|
||||
|
||||
### Spotless Code Formatting
|
||||
|
||||
Code formatting for Java is checked via *spotless*.
|
||||
@ -616,7 +656,7 @@ we need to register a shutdown-hook in the test source code.
|
||||
2. Now You Can Run the Tests
|
||||
|
||||
```shell
|
||||
gw clean test # gw is from the .aliases file
|
||||
gw test # gw is from the .aliases file
|
||||
```
|
||||
|
||||
#### Use IntelliJ IDEA Run the Tests Against the Podman Daemon
|
||||
|
82
build.gradle
82
build.gradle
@ -1,15 +1,15 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '3.0.0'
|
||||
id 'io.spring.dependency-management' version '1.1.0'
|
||||
id 'io.openapiprocessor.openapi-processor' version '2022.2'
|
||||
id 'com.github.jk1.dependency-license-report' version '2.1'
|
||||
id "org.owasp.dependencycheck" version "7.3.0"
|
||||
id "com.diffplug.spotless" version "6.11.0"
|
||||
id 'org.springframework.boot' version '3.1.7'
|
||||
id 'io.spring.dependency-management' version '1.1.4'
|
||||
id 'io.openapiprocessor.openapi-processor' version '2023.2'
|
||||
id 'com.github.jk1.dependency-license-report' version '2.5'
|
||||
id "org.owasp.dependencycheck" version "9.0.7"
|
||||
id "com.diffplug.spotless" version "6.23.3"
|
||||
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 'com.github.ben-manes.versions' version '0.43.0'
|
||||
id 'com.github.ben-manes.versions' version '0.50.0'
|
||||
}
|
||||
|
||||
group = 'net.hostsharing'
|
||||
@ -17,7 +17,7 @@ version = '0.0.1-SNAPSHOT'
|
||||
|
||||
wrapper {
|
||||
distributionType = Wrapper.DistributionType.BIN
|
||||
gradleVersion = '7.5'
|
||||
gradleVersion = '8.5'
|
||||
}
|
||||
|
||||
configurations {
|
||||
@ -42,7 +42,9 @@ repositories {
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(17)
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
vendor = JvmVendorSpec.ADOPTIUM
|
||||
implementation = JvmImplementation.VENDOR_SPECIFIC
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,30 +52,41 @@ ext {
|
||||
set('testcontainersVersion', "1.17.3")
|
||||
}
|
||||
|
||||
// wrapper
|
||||
|
||||
dependencies {
|
||||
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-jdbc'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
implementation 'com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.8.1'
|
||||
implementation 'org.springdoc:springdoc-openapi:2.0.0-M7'
|
||||
implementation 'org.liquibase:liquibase-core'
|
||||
implementation 'com.vladmihalcea:hibernate-types-60:2.20.0'
|
||||
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4'
|
||||
implementation 'org.openapitools:jackson-databind-nullable:0.2.4'
|
||||
implementation 'org.apache.commons:commons-text:1.10.0'
|
||||
implementation 'org.modelmapper:modelmapper:3.1.0'
|
||||
implementation 'org.iban4j:iban4j:3.2.3-RELEASE'
|
||||
implementation 'com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.9.1'
|
||||
implementation 'org.springdoc:springdoc-openapi:2.3.0'
|
||||
implementation 'org.postgresql:postgresql:42.7.1'
|
||||
implementation 'org.liquibase:liquibase-core:4.25.1'
|
||||
implementation 'com.vladmihalcea:hibernate-types-60:2.21.1'
|
||||
implementation 'io.hypersistence:hypersistence-utils-hibernate-62:3.7.0'
|
||||
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1'
|
||||
implementation 'org.openapitools:jackson-databind-nullable:0.2.6'
|
||||
implementation 'org.apache.commons:commons-text:1.11.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'
|
||||
testCompileOnly 'org.projectlombok:lombok'
|
||||
|
||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||
|
||||
runtimeOnly 'org.postgresql:postgresql'
|
||||
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
testAnnotationProcessor 'org.projectlombok:lombok'
|
||||
@ -81,11 +94,12 @@ dependencies {
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
testImplementation 'org.testcontainers:testcontainers'
|
||||
testImplementation 'org.testcontainers:junit-jupiter'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||
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 '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 {
|
||||
@ -170,7 +184,7 @@ openApiGenerate.dependsOn processSpring
|
||||
// Spotless Code Formatting
|
||||
spotless {
|
||||
java {
|
||||
// removeUnusedImports() TODO: reactivate once it can deal with multi-line-strings
|
||||
removeUnusedImports()
|
||||
indentWithSpaces(4)
|
||||
endWithNewline()
|
||||
toggleOffOn()
|
||||
@ -182,14 +196,24 @@ spotless {
|
||||
}
|
||||
}
|
||||
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
|
||||
dependencyCheck {
|
||||
cveValidForHours=4
|
||||
nvd {
|
||||
apiKey = project.property('OWASP_API_KEY') // set it in ~/.gradle/gradle.properties
|
||||
delay = 16000
|
||||
}
|
||||
format = 'ALL'
|
||||
suppressionFile = 'etc/owasp-dependency-check-suppression.xml'
|
||||
failOnError = true
|
||||
failBuildOnCVSS = 7
|
||||
failBuildOnCVSS = 5
|
||||
}
|
||||
project.tasks.check.dependsOn(dependencyCheckAnalyze)
|
||||
project.tasks.dependencyCheckAnalyze.doFirst { // Why not doLast? See README.md!
|
||||
@ -206,7 +230,7 @@ project.tasks.check.dependsOn(checkLicense)
|
||||
|
||||
// JaCoCo Test Code Coverage
|
||||
jacoco {
|
||||
toolVersion = "0.8.8"
|
||||
toolVersion = "0.8.10"
|
||||
}
|
||||
test {
|
||||
finalizedBy jacocoTestReport // generate report after tests
|
||||
@ -285,7 +309,7 @@ pitest {
|
||||
targetTests = ['net.hostsharing.hsadminng.**.*UnitTest', 'net.hostsharing.hsadminng.**.*RestTest']
|
||||
excludedTestClasses = ['**AcceptanceTest*', '**IntegrationTest*']
|
||||
|
||||
pitestVersion = '1.9.9'
|
||||
pitestVersion = '1.15.3'
|
||||
junit5PluginVersion = '1.1.0'
|
||||
|
||||
threads = 4
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
{ "moduleLicense": "BSD License" },
|
||||
{ "moduleLicense": "BSD-2-Clause" },
|
||||
{ "moduleLicense": "BSD-3-Clause" },
|
||||
{ "moduleLicense": "The BSD License" },
|
||||
|
||||
{ "moduleLicense": "CDDL 1.1" },
|
||||
|
@ -14,4 +14,52 @@
|
||||
<packageUrl regex="true">^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$</packageUrl>
|
||||
<cve>CVE-2022-42003</cve>
|
||||
</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>
|
||||
|
@ -1,3 +1,8 @@
|
||||
# Gradle Java Toolchain-support
|
||||
org.gradle.java.installations.auto-detect=true
|
||||
org.gradle.java.installations.auto-download=true
|
||||
# org.gradle.jvm.toolchain.install.adoptopenjdk.baseUri
|
||||
# org.gradle.java.installations.paths -- uncomment and set if needed
|
||||
|
||||
# Spring BOM overrides
|
||||
# currently none necessary
|
||||
|
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
|
||||
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
|
||||
zipStorePath=wrapper/dists
|
||||
|
41
gradlew
vendored
41
gradlew
vendored
@ -55,7 +55,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@ -80,13 +80,11 @@ do
|
||||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@ -133,22 +131,29 @@ location of your Java installation."
|
||||
fi
|
||||
else
|
||||
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
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
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 ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | 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" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# 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 -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
@ -205,6 +214,12 @@ set -- \
|
||||
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.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
|
15
gradlew.bat
vendored
15
gradlew.bat
vendored
@ -14,7 +14,7 @@
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@ -25,7 +25,8 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
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
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
@ -7,4 +7,32 @@ pluginManagement {
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
|
||||
}
|
||||
|
||||
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'
|
||||
|
@ -8,7 +8,7 @@ import static org.hibernate.dialect.DatabaseVersion.make;
|
||||
public class PostgresCustomDialect extends PostgreSQLDialect {
|
||||
|
||||
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.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.function.Predicate.not;
|
||||
import static net.hostsharing.hsadminng.mapper.PostgresArray.fromPostgresArray;
|
||||
import static org.springframework.transaction.annotation.Propagation.MANDATORY;
|
||||
|
||||
@Service
|
||||
@ -81,11 +83,14 @@ public class Context {
|
||||
}
|
||||
|
||||
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() {
|
||||
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) {
|
||||
|
@ -14,7 +14,7 @@ public interface HsOfficeContactRepository extends Repository<HsOfficeContactEnt
|
||||
@Query("""
|
||||
SELECT c FROM HsOfficeContactEntity c
|
||||
WHERE :label is null
|
||||
OR c.label like concat(:label, '%')
|
||||
OR c.label like concat(cast(:label as text), '%')
|
||||
""")
|
||||
List<HsOfficeContactEntity> findContactByOptionalLabelLike(String label);
|
||||
|
||||
|
@ -1,13 +1,11 @@
|
||||
package net.hostsharing.hsadminng.hs.office.coopassets;
|
||||
|
||||
import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType;
|
||||
import lombok.*;
|
||||
import net.hostsharing.hsadminng.errors.DisplayName;
|
||||
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
|
||||
import net.hostsharing.hsadminng.stringify.Stringify;
|
||||
import net.hostsharing.hsadminng.stringify.Stringifyable;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.math.BigDecimal;
|
||||
@ -47,7 +45,6 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable {
|
||||
|
||||
@Column(name = "transactiontype")
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Type(PostgreSQLEnumType.class)
|
||||
private HsOfficeCoopAssetsTransactionType transactionType;
|
||||
|
||||
@Column(name = "valuedate")
|
||||
|
@ -1,6 +1,5 @@
|
||||
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.repository.Repository;
|
||||
|
||||
|
@ -1,12 +1,10 @@
|
||||
package net.hostsharing.hsadminng.hs.office.coopshares;
|
||||
|
||||
import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType;
|
||||
import lombok.*;
|
||||
import net.hostsharing.hsadminng.errors.DisplayName;
|
||||
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
|
||||
import net.hostsharing.hsadminng.stringify.Stringify;
|
||||
import net.hostsharing.hsadminng.stringify.Stringifyable;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDate;
|
||||
@ -43,7 +41,6 @@ public class HsOfficeCoopSharesTransactionEntity implements Stringifyable {
|
||||
|
||||
@Column(name = "transactiontype")
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Type(PostgreSQLEnumType.class)
|
||||
private HsOfficeCoopSharesTransactionType transactionType;
|
||||
|
||||
@Column(name = "valuedate")
|
||||
|
@ -19,15 +19,15 @@ public interface HsOfficeDebitorRepository extends Repository<HsOfficeDebitorEnt
|
||||
|
||||
@Query("""
|
||||
SELECT debitor FROM HsOfficeDebitorEntity debitor
|
||||
JOIN HsOfficePartnerEntity partner ON partner.uuid = debitor.partner
|
||||
JOIN HsOfficePersonEntity person ON person.uuid = partner.person
|
||||
JOIN HsOfficeContactEntity contact ON contact.uuid = debitor.billingContact
|
||||
JOIN HsOfficePartnerEntity partner ON partner.uuid = debitor.partner.uuid
|
||||
JOIN HsOfficePersonEntity person ON person.uuid = partner.person.uuid
|
||||
JOIN HsOfficeContactEntity contact ON contact.uuid = debitor.billingContact.uuid
|
||||
WHERE :name is null
|
||||
OR partner.details.birthName like concat(:name, '%')
|
||||
OR person.tradeName like concat(:name, '%')
|
||||
OR person.familyName like concat(:name, '%')
|
||||
OR person.givenName like concat(:name, '%')
|
||||
OR contact.label like concat(:name, '%')
|
||||
OR partner.details.birthName like concat(cast(:name as text), '%')
|
||||
OR person.tradeName like concat(cast(:name as text), '%')
|
||||
OR person.familyName like concat(cast(:name as text), '%')
|
||||
OR person.givenName like concat(cast(:name as text), '%')
|
||||
OR contact.label like concat(cast(:name as text), '%')
|
||||
""")
|
||||
List<HsOfficeDebitorEntity> findDebitorByOptionalNameLike(String name);
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
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.Range;
|
||||
import lombok.*;
|
||||
@ -61,7 +60,6 @@ public class HsOfficeMembershipEntity implements Stringifyable {
|
||||
|
||||
@Column(name = "reasonfortermination")
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Type(PostgreSQLEnumType.class)
|
||||
private HsOfficeReasonForTermination reasonForTermination;
|
||||
|
||||
public void setValidFrom(final LocalDate validFrom) {
|
||||
|
@ -13,14 +13,14 @@ public interface HsOfficePartnerRepository extends Repository<HsOfficePartnerEnt
|
||||
|
||||
@Query("""
|
||||
SELECT partner FROM HsOfficePartnerEntity partner
|
||||
JOIN HsOfficeContactEntity contact ON contact.uuid = partner.contact
|
||||
JOIN HsOfficePersonEntity person ON person.uuid = partner.person
|
||||
JOIN HsOfficeContactEntity contact ON contact.uuid = partner.contact.uuid
|
||||
JOIN HsOfficePersonEntity person ON person.uuid = partner.person.uuid
|
||||
WHERE :name is null
|
||||
OR partner.details.birthName like concat(:name, '%')
|
||||
OR contact.label like concat(:name, '%')
|
||||
OR person.tradeName like concat(:name, '%')
|
||||
OR person.givenName like concat(:name, '%')
|
||||
OR person.familyName like concat(:name, '%')
|
||||
OR partner.details.birthName like concat(cast(:name as text), '%')
|
||||
OR contact.label like concat(cast(:name as text), '%')
|
||||
OR person.tradeName like concat(cast(:name as text), '%')
|
||||
OR person.givenName like concat(cast(:name as text), '%')
|
||||
OR person.familyName like concat(cast(:name as text), '%')
|
||||
""")
|
||||
List<HsOfficePartnerEntity> findPartnerByOptionalNameLike(String name);
|
||||
|
||||
|
@ -1,13 +1,11 @@
|
||||
package net.hostsharing.hsadminng.hs.office.person;
|
||||
|
||||
import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType;
|
||||
import lombok.*;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import net.hostsharing.hsadminng.errors.DisplayName;
|
||||
import net.hostsharing.hsadminng.stringify.Stringify;
|
||||
import net.hostsharing.hsadminng.stringify.Stringifyable;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.util.UUID;
|
||||
@ -37,7 +35,6 @@ public class HsOfficePersonEntity implements Stringifyable {
|
||||
|
||||
@Column(name = "persontype")
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Type(PostgreSQLEnumType.class)
|
||||
private HsOfficePersonType personType;
|
||||
|
||||
@Column(name = "tradename")
|
||||
|
@ -14,9 +14,9 @@ public interface HsOfficePersonRepository extends Repository<HsOfficePersonEntit
|
||||
@Query("""
|
||||
SELECT p FROM HsOfficePersonEntity p
|
||||
WHERE :name is null
|
||||
OR p.tradeName like concat(:name, '%')
|
||||
OR p.givenName like concat(:name, '%')
|
||||
OR p.familyName like concat(:name, '%')
|
||||
OR p.tradeName like concat(cast(:name as text), '%')
|
||||
OR p.givenName like concat(cast(:name as text), '%')
|
||||
OR p.familyName like concat(cast(:name as text), '%')
|
||||
""")
|
||||
List<HsOfficePersonEntity> findPersonByOptionalNameLike(String name);
|
||||
|
||||
|
@ -51,7 +51,7 @@ public class HsOfficeRelationshipController implements HsOfficeRelationshipsApi
|
||||
final HsOfficeRelationshipTypeResource relationshipType) {
|
||||
context.define(currentUser, assumedRoles);
|
||||
|
||||
final var entities = relationshipRepo.findRelationshipRelatedToPersonUuid(personUuid,
|
||||
final var entities = relationshipRepo.findRelationshipRelatedToPersonUuidAndRelationshipType(personUuid,
|
||||
mapper.map(relationshipType, HsOfficeRelationshipType.class));
|
||||
|
||||
final var resources = mapper.mapList(entities, HsOfficeRelationshipResource.class,
|
||||
|
@ -1,12 +1,10 @@
|
||||
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||
|
||||
import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType;
|
||||
import lombok.*;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||
import net.hostsharing.hsadminng.stringify.Stringify;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.util.UUID;
|
||||
@ -47,7 +45,6 @@ public class HsOfficeRelationshipEntity {
|
||||
|
||||
@Column(name = "reltype")
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Type(PostgreSQLEnumType.class)
|
||||
private HsOfficeRelationshipType relType;
|
||||
|
||||
@Override
|
||||
|
@ -12,8 +12,8 @@ public interface HsOfficeRelationshipRepository extends Repository<HsOfficeRelat
|
||||
|
||||
Optional<HsOfficeRelationshipEntity> findByUuid(UUID id);
|
||||
|
||||
default List<HsOfficeRelationshipEntity> findRelationshipRelatedToPersonUuid(@NotNull UUID personUuid, HsOfficeRelationshipType relationshipType) {
|
||||
return findRelationshipRelatedToPersonUuid(personUuid, relationshipType.toString());
|
||||
default List<HsOfficeRelationshipEntity> findRelationshipRelatedToPersonUuidAndRelationshipType(@NotNull UUID personUuid, HsOfficeRelationshipType relationshipType) {
|
||||
return findRelationshipRelatedToPersonUuidAndRelationshipTypeString(personUuid, relationshipType.toString());
|
||||
}
|
||||
|
||||
@Query(value = """
|
||||
@ -27,7 +27,7 @@ public interface HsOfficeRelationshipRepository extends Repository<HsOfficeRelat
|
||||
WHERE (:relationshipType IS NULL OR p.relType = cast(:relationshipType AS HsOfficeRelationshipType))
|
||||
AND ( p.relAnchorUuid = :personUuid OR p.relHolderUuid = :personUuid)
|
||||
""", nativeQuery = true)
|
||||
List<HsOfficeRelationshipEntity> findRelationshipRelatedToPersonUuid(@NotNull UUID personUuid, String relationshipType);
|
||||
List<HsOfficeRelationshipEntity> findRelationshipRelatedToPersonUuidAndRelationshipTypeString(@NotNull UUID personUuid, String relationshipType);
|
||||
|
||||
HsOfficeRelationshipEntity save(final HsOfficeRelationshipEntity entity);
|
||||
|
||||
|
@ -54,6 +54,7 @@ public class HsOfficeSepaMandateEntity implements Stringifyable {
|
||||
|
||||
@Column(name = "validity", columnDefinition = "daterange")
|
||||
@Type(PostgreSQLRangeType.class)
|
||||
@Builder.Default
|
||||
private Range<LocalDate> validity = Range.infinite(LocalDate.class);
|
||||
|
||||
public void setValidFrom(final LocalDate validFrom) {
|
||||
|
@ -14,7 +14,7 @@ public interface HsOfficeSepaMandateRepository extends Repository<HsOfficeSepaMa
|
||||
@Query("""
|
||||
SELECT mandate FROM HsOfficeSepaMandateEntity mandate
|
||||
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
|
||||
""")
|
||||
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("""
|
||||
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
|
||||
""")
|
||||
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 java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
public class TestCustomerController implements TestCustomersApi {
|
||||
|
@ -12,7 +12,7 @@ public interface TestCustomerRepository extends Repository<TestCustomerEntity, U
|
||||
|
||||
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);
|
||||
|
||||
TestCustomerEntity save(final TestCustomerEntity entity);
|
||||
|
@ -8,7 +8,7 @@ import java.util.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);
|
||||
|
||||
TestPackageEntity findByUuid(UUID packageUuid);
|
||||
|
@ -0,0 +1,96 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- TODO: These changesets are just for the external remote views to simulate the legacy tables.
|
||||
-- Once we don't need the external remote views anymore, create revert changesets.
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-mapping:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE hs_office_contact_legacy_id
|
||||
(
|
||||
uuid uuid NOT NULL REFERENCES hs_office_contact(uuid),
|
||||
contact_id integer NOT NULL
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-sequence:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS hs_office_contact_legacy_id_seq
|
||||
AS integer
|
||||
START 1000000000
|
||||
OWNED BY hs_office_contact_legacy_id.contact_id;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-default:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
ALTER TABLE hs_office_contact_legacy_id
|
||||
ALTER COLUMN contact_id
|
||||
SET DEFAULT nextVal('hs_office_contact_legacy_id_seq');
|
||||
|
||||
--/
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-insert:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CALL defineContext('schema-migration');
|
||||
INSERT INTO hs_office_contact_legacy_id(uuid, contact_id)
|
||||
SELECT uuid, nextVal('hs_office_contact_legacy_id_seq') FROM hs_office_contact;
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function insertContactLegacyIdMapping()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of trigger';
|
||||
end if;
|
||||
|
||||
INSERT INTO hs_office_contact_legacy_id VALUES
|
||||
(NEW.uuid, nextVal('hs_office_contact_legacy_id_seq'));
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger createContactLegacyIdMapping
|
||||
after insert on hs_office_contact
|
||||
for each row
|
||||
execute procedure insertContactLegacyIdMapping();
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-delete-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function deleteContactLegacyIdMapping()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'DELETE' then
|
||||
raise exception 'invalid usage of trigger';
|
||||
end if;
|
||||
|
||||
DELETE FROM hs_office_contact_legacy_id
|
||||
WHERE uuid = OLD.uuid;
|
||||
|
||||
return OLD;
|
||||
end; $$;
|
||||
|
||||
create trigger removeContactLegacyIdMapping
|
||||
before delete on hs_office_contact
|
||||
for each row
|
||||
execute procedure deleteContactLegacyIdMapping();
|
||||
--/
|
@ -0,0 +1,95 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- TODO: These changesets are just for the external remote views to simulate the legacy tables.
|
||||
-- Once we don't need the external remote views anymore, create revert changesets.
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-MIGRATION-mapping:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE hs_office_partner_legacy_id
|
||||
(
|
||||
uuid uuid NOT NULL REFERENCES hs_office_partner(uuid),
|
||||
bp_id integer NOT NULL
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-MIGRATION-sequence:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS hs_office_partner_legacy_id_seq
|
||||
AS integer
|
||||
START 1000000000
|
||||
OWNED BY hs_office_partner_legacy_id.bp_id;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-MIGRATION-default:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
ALTER TABLE hs_office_partner_legacy_id
|
||||
ALTER COLUMN bp_id
|
||||
SET DEFAULT nextVal('hs_office_partner_legacy_id_seq');
|
||||
--/
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-MIGRATION-insert:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CALL defineContext('schema-migration');
|
||||
INSERT INTO hs_office_partner_legacy_id(uuid, bp_id)
|
||||
SELECT uuid, nextVal('hs_office_partner_legacy_id_seq') FROM hs_office_partner;
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-MIGRATION-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function insertPartnerLegacyIdMapping()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of trigger';
|
||||
end if;
|
||||
|
||||
INSERT INTO hs_office_partner_legacy_id VALUES
|
||||
(NEW.uuid, nextVal('hs_office_partner_legacy_id_seq'));
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger createPartnerLegacyIdMapping
|
||||
after insert on hs_office_partner
|
||||
for each row
|
||||
execute procedure insertPartnerLegacyIdMapping();
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-MIGRATION-delete-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function deletePartnerLegacyIdMapping()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'DELETE' then
|
||||
raise exception 'invalid usage of trigger';
|
||||
end if;
|
||||
|
||||
DELETE FROM hs_office_partner_legacy_id
|
||||
WHERE uuid = OLD.uuid;
|
||||
|
||||
return OLD;
|
||||
end; $$;
|
||||
|
||||
create trigger removePartnerLegacyIdMapping
|
||||
before delete on hs_office_partner
|
||||
for each row
|
||||
execute procedure deletePartnerLegacyIdMapping();
|
||||
--/
|
@ -0,0 +1,97 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- TODO: These changesets are just for the external remote views to simulate the legacy tables.
|
||||
-- Once we don't need the external remote views anymore, create revert changesets.
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-MIGRATION-mapping:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE hs_office_sepamandate_legacy_id
|
||||
(
|
||||
uuid uuid NOT NULL REFERENCES hs_office_sepamandate(uuid),
|
||||
sepa_mandat_id integer NOT NULL
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-MIGRATION-sequence:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS hs_office_sepamandate_legacy_id_seq
|
||||
AS integer
|
||||
START 1000000000
|
||||
OWNED BY hs_office_sepamandate_legacy_id.sepa_mandat_id;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-MIGRATION-default:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
ALTER TABLE hs_office_sepamandate_legacy_id
|
||||
ALTER COLUMN sepa_mandat_id
|
||||
SET DEFAULT nextVal('hs_office_sepamandate_legacy_id_seq');
|
||||
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-MIGRATION-insert:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CALL defineContext('schema-migration');
|
||||
INSERT INTO hs_office_sepamandate_legacy_id(uuid, sepa_mandat_id)
|
||||
SELECT uuid, nextVal('hs_office_sepamandate_legacy_id_seq') FROM hs_office_sepamandate;
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-MIGRATION-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function insertSepaMandateLegacyIdMapping()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of trigger';
|
||||
end if;
|
||||
|
||||
INSERT INTO hs_office_sepamandate_legacy_id VALUES
|
||||
(NEW.uuid, nextVal('hs_office_sepamandate_legacy_id_seq'));
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger createSepaMandateLegacyIdMapping
|
||||
after insert on hs_office_sepamandate
|
||||
for each row
|
||||
execute procedure insertSepaMandateLegacyIdMapping();
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-MIGRATION-delete-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function deleteSepaMandateLegacyIdMapping()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'DELETE' then
|
||||
raise exception 'invalid usage of trigger';
|
||||
end if;
|
||||
|
||||
DELETE FROM hs_office_sepamandate_legacy_id
|
||||
WHERE uuid = OLD.uuid;
|
||||
|
||||
return OLD;
|
||||
end; $$;
|
||||
|
||||
create trigger removeSepaMandateLegacyIdMapping
|
||||
before delete on hs_office_sepamandate
|
||||
for each row
|
||||
execute procedure deleteSepaMandateLegacyIdMapping();
|
||||
--/
|
@ -0,0 +1,96 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- TODO: These changesets are just for the external remote views to simulate the legacy tables.
|
||||
-- Once we don't need the external remote views anymore, create revert changesets.
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopshares-MIGRATION-mapping:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE hs_office_coopsharestransaction_legacy_id
|
||||
(
|
||||
uuid uuid NOT NULL REFERENCES hs_office_coopsharestransaction(uuid),
|
||||
member_share_id integer NOT NULL
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopshares-MIGRATION-sequence:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS hs_office_coopsharestransaction_legacy_id_seq
|
||||
AS integer
|
||||
START 1000000000
|
||||
OWNED BY hs_office_coopsharestransaction_legacy_id.member_share_id;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopshares-MIGRATION-default:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
ALTER TABLE hs_office_coopsharestransaction_legacy_id
|
||||
ALTER COLUMN member_share_id
|
||||
SET DEFAULT nextVal('hs_office_coopsharestransaction_legacy_id_seq');
|
||||
|
||||
--/
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopshares-MIGRATION-insert:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CALL defineContext('schema-migration');
|
||||
INSERT INTO hs_office_coopsharestransaction_legacy_id(uuid, member_share_id)
|
||||
SELECT uuid, nextVal('hs_office_coopsharestransaction_legacy_id_seq') FROM hs_office_coopsharestransaction;
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopShares-MIGRATION-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function insertCoopSharesLegacyIdMapping()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of trigger';
|
||||
end if;
|
||||
|
||||
INSERT INTO hs_office_coopsharestransaction_legacy_id VALUES
|
||||
(NEW.uuid, nextVal('hs_office_coopsharestransaction_legacy_id_seq'));
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger createCoopSharesLegacyIdMapping
|
||||
after insert on hs_office_coopsharestransaction
|
||||
for each row
|
||||
execute procedure insertCoopSharesLegacyIdMapping();
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopShares-MIGRATION-delete-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function deleteCoopSharesLegacyIdMapping()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'DELETE' then
|
||||
raise exception 'invalid usage of trigger';
|
||||
end if;
|
||||
|
||||
DELETE FROM hs_office_coopsharestransaction_legacy_id
|
||||
WHERE uuid = OLD.uuid;
|
||||
|
||||
return OLD;
|
||||
end; $$;
|
||||
|
||||
create trigger removeCoopSharesLegacyIdMapping
|
||||
before delete on hs_office_coopsharestransaction
|
||||
for each row
|
||||
execute procedure deleteCoopSharesLegacyIdMapping();
|
||||
--/
|
@ -0,0 +1,96 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- TODO: These changesets are just for the external remote views to simulate the legacy tables.
|
||||
-- Once we don't need the external remote views anymore, create revert changesets.
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopassets-MIGRATION-mapping:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE hs_office_coopassetstransaction_legacy_id
|
||||
(
|
||||
uuid uuid NOT NULL REFERENCES hs_office_coopassetstransaction(uuid),
|
||||
member_asset_id integer NOT NULL
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopassets-MIGRATION-sequence:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS hs_office_coopassetstransaction_legacy_id_seq
|
||||
AS integer
|
||||
START 1000000000
|
||||
OWNED BY hs_office_coopassetstransaction_legacy_id.member_asset_id;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopassets-MIGRATION-default:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
ALTER TABLE hs_office_coopassetstransaction_legacy_id
|
||||
ALTER COLUMN member_asset_id
|
||||
SET DEFAULT nextVal('hs_office_coopassetstransaction_legacy_id_seq');
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopassets-MIGRATION-insert:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CALL defineContext('schema-migration');
|
||||
INSERT INTO hs_office_coopassetstransaction_legacy_id(uuid, member_asset_id)
|
||||
SELECT uuid, nextVal('hs_office_coopassetstransaction_legacy_id_seq') FROM hs_office_coopassetstransaction;
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopAssets-MIGRATION-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function insertCoopAssetsLegacyIdMapping()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of trigger';
|
||||
end if;
|
||||
|
||||
INSERT INTO hs_office_coopassetstransaction_legacy_id VALUES
|
||||
(NEW.uuid, nextVal('hs_office_coopassetstransaction_legacy_id_seq'));
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger createCoopAssetsLegacyIdMapping
|
||||
after insert on hs_office_coopassetstransaction
|
||||
for each row
|
||||
execute procedure insertCoopAssetsLegacyIdMapping();
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopAssets-MIGRATION-delete-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function deleteCoopAssetsLegacyIdMapping()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'DELETE' then
|
||||
raise exception 'invalid usage of trigger';
|
||||
end if;
|
||||
|
||||
DELETE FROM hs_office_coopassetstransaction_legacy_id
|
||||
WHERE uuid = OLD.uuid;
|
||||
|
||||
return OLD;
|
||||
end; $$;
|
||||
|
||||
create trigger removeCoopAssetsLegacyIdMapping
|
||||
before delete on hs_office_coopassetstransaction
|
||||
for each row
|
||||
execute procedure deleteCoopAssetsLegacyIdMapping();
|
||||
--/
|
@ -53,6 +53,8 @@ databaseChangeLog:
|
||||
file: db/changelog/200-hs-office-contact.sql
|
||||
- include:
|
||||
file: db/changelog/203-hs-office-contact-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/206-hs-office-contact-migration.sql
|
||||
- include:
|
||||
file: db/changelog/208-hs-office-contact-test-data.sql
|
||||
- include:
|
||||
@ -67,6 +69,8 @@ databaseChangeLog:
|
||||
file: db/changelog/223-hs-office-partner-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/224-hs-office-partner-details-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/226-hs-office-partner-migration.sql
|
||||
- include:
|
||||
file: db/changelog/228-hs-office-partner-test-data.sql
|
||||
- include:
|
||||
@ -80,7 +84,7 @@ databaseChangeLog:
|
||||
- include:
|
||||
file: db/changelog/243-hs-office-bankaccount-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/248-hs-office-bankaccount-test-data.sql
|
||||
file: db/changelog/248-hs-office-bankaccount-test-data.sql
|
||||
- include:
|
||||
file: db/changelog/270-hs-office-debitor.sql
|
||||
- include:
|
||||
@ -91,6 +95,8 @@ databaseChangeLog:
|
||||
file: db/changelog/250-hs-office-sepamandate.sql
|
||||
- include:
|
||||
file: db/changelog/253-hs-office-sepamandate-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/256-hs-office-sepamandate-migration.sql
|
||||
- include:
|
||||
file: db/changelog/258-hs-office-sepamandate-test-data.sql
|
||||
- include:
|
||||
@ -103,11 +109,15 @@ databaseChangeLog:
|
||||
file: db/changelog/310-hs-office-coopshares.sql
|
||||
- include:
|
||||
file: db/changelog/313-hs-office-coopshares-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/316-hs-office-coopshares-migration.sql
|
||||
- include:
|
||||
file: db/changelog/318-hs-office-coopshares-test-data.sql
|
||||
- include:
|
||||
file: db/changelog/320-hs-office-coopassets.sql
|
||||
- include:
|
||||
file: db/changelog/323-hs-office-coopassets-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/326-hs-office-coopassets-migration.sql
|
||||
- include:
|
||||
file: db/changelog/328-hs-office-coopassets-test-data.sql
|
||||
|
@ -83,7 +83,7 @@ class HsOfficeBankAccountControllerRestTest {
|
||||
enum InvalidBicTestCase {
|
||||
TOO_SHORT("BEVODEB", "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 expectedErrorMessage;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.hostsharing.hsadminng.hs.office.bankaccount;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
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.test.JpaAttempt.attempt;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
|
||||
@DataJpaTest
|
||||
@Import( { Context.class, JpaAttempt.class })
|
||||
@ -237,10 +236,6 @@ class HsOfficeContactRepositoryIntegrationTest extends ContextBasedTest {
|
||||
final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll());
|
||||
final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll());
|
||||
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
|
||||
final var result = jpaAttempt.transacted(() -> {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.hostsharing.hsadminng.hs.office.contact;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TestHsOfficeContact {
|
||||
|
||||
|
@ -26,7 +26,6 @@ import java.util.UUID;
|
||||
import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid;
|
||||
import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
@SpringBootTest(
|
||||
@ -481,7 +480,7 @@ class HsOfficeDebitorControllerAcceptanceTest {
|
||||
void contactAdminUser_canNotDeleteRelatedDebitor() {
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenDebitor = givenSomeTemporaryDebitor();
|
||||
assumeThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact");
|
||||
assertThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact");
|
||||
|
||||
RestAssured // @formatter:off
|
||||
.given()
|
||||
@ -501,7 +500,7 @@ class HsOfficeDebitorControllerAcceptanceTest {
|
||||
void normalUser_canNotDeleteUnrelatedDebitor() {
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenDebitor = givenSomeTemporaryDebitor();
|
||||
assumeThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact");
|
||||
assertThat(givenDebitor.getBillingContact().getLabel()).isEqualTo("forth contact");
|
||||
|
||||
RestAssured // @formatter:off
|
||||
.given()
|
||||
|
@ -2,7 +2,6 @@ package net.hostsharing.hsadminng.hs.office.debitor;
|
||||
|
||||
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.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.test.JpaAttempt.attempt;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
|
||||
@DataJpaTest
|
||||
@Import( { Context.class, JpaAttempt.class })
|
||||
@ -327,7 +326,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTest {
|
||||
// when
|
||||
final var result = jpaAttempt.transacted(() -> {
|
||||
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());
|
||||
});
|
||||
|
@ -3,7 +3,6 @@ package net.hostsharing.hsadminng.hs.office.membership;
|
||||
import com.vladmihalcea.hibernate.type.range.Range;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
|
||||
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.JsonMatcher.lenientlyEquals;
|
||||
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.startsWith;
|
||||
|
||||
@ -408,7 +407,7 @@ class HsOfficePartnerControllerAcceptanceTest {
|
||||
void contactAdminUser_canNotDeleteRelatedPartner() {
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenPartner = givenSomeTemporaryPartnerBessler();
|
||||
assumeThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact");
|
||||
assertThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact");
|
||||
|
||||
RestAssured // @formatter:off
|
||||
.given()
|
||||
@ -428,7 +427,7 @@ class HsOfficePartnerControllerAcceptanceTest {
|
||||
void normalUser_canNotDeleteUnrelatedPartner() {
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenPartner = givenSomeTemporaryPartnerBessler();
|
||||
assumeThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact");
|
||||
assertThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact");
|
||||
|
||||
RestAssured // @formatter:off
|
||||
.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.test.JpaAttempt.attempt;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
|
||||
@DataJpaTest
|
||||
@Import( { Context.class, JpaAttempt.class })
|
||||
@ -330,7 +329,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
|
||||
// when
|
||||
final var result = jpaAttempt.transacted(() -> {
|
||||
context("person-ErbenBesslerMelBessler@example.com");
|
||||
assumeThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent();
|
||||
assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent();
|
||||
|
||||
partnerRepo.deleteByUuid(givenPartner.getUuid());
|
||||
});
|
||||
@ -352,10 +351,6 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
|
||||
final var initialRoleNames = Array.from(roleNamesOf(rawRoleRepo.findAll()));
|
||||
final var initialGrantNames = Array.from(grantDisplaysOf(rawGrantRepo.findAll()));
|
||||
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
|
||||
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.person.HsOfficePersonEntity;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
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.test.JpaAttempt.attempt;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
|
||||
@DataJpaTest
|
||||
@Import( { Context.class, JpaAttempt.class })
|
||||
@ -244,10 +243,6 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTest {
|
||||
final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll());
|
||||
final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll());
|
||||
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
|
||||
final var result = jpaAttempt.transacted(() -> {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.hostsharing.hsadminng.hs.office.person;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TestHsOfficePerson {
|
||||
|
||||
|
@ -25,7 +25,6 @@ import java.util.UUID;
|
||||
import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid;
|
||||
import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
|
||||
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.startsWith;
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.hostsharing.hsadminng.hs.office.sepamandate;
|
||||
|
||||
import com.vladmihalcea.hibernate.type.range.Range;
|
||||
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||
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.test.JpaAttempt.attempt;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
|
||||
@DataJpaTest
|
||||
@Import({ Context.class, JpaAttempt.class })
|
||||
@ -346,7 +345,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest {
|
||||
// when
|
||||
final var result = jpaAttempt.transacted(() -> {
|
||||
context("bankaccount-admin@ThirdOHG.example.com");
|
||||
assumeThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent();
|
||||
assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent();
|
||||
|
||||
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 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.is;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
@ -343,7 +342,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
}
|
||||
|
||||
private void assumeCreated(final ValidatableResponse response) {
|
||||
assumeThat(response.extract().response().statusCode()).isEqualTo(201);
|
||||
assertThat(response.extract().response().statusCode()).isEqualTo(201);
|
||||
}
|
||||
|
||||
class Subject {
|
||||
@ -479,7 +478,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
}
|
||||
|
||||
private void assumeGrantExists(final Subject grantingSubject, final String expectedGrant) {
|
||||
assumeThat(findAllGrantsOf(grantingSubject))
|
||||
assertThat(findAllGrantsOf(grantingSubject))
|
||||
.extracting(RbacGrantEntity::toDisplay)
|
||||
.contains(expectedGrant);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import java.util.UUID;
|
||||
|
||||
import static net.hostsharing.test.JpaAttempt.attempt;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
|
||||
@DataJpaTest
|
||||
@Import( { Context.class, JpaAttempt.class })
|
||||
@ -186,9 +185,8 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
|
||||
// when
|
||||
context("customer-admin@xxx.example.com", "test_customer#xxx.admin");
|
||||
final var revokeAttempt = attempt(em, () -> {
|
||||
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
|
||||
});
|
||||
final var revokeAttempt = attempt(em, () ->
|
||||
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId()));
|
||||
|
||||
// then
|
||||
context("customer-admin@xxx.example.com", "test_customer#xxx.admin");
|
||||
@ -208,9 +206,8 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
|
||||
// when
|
||||
context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00.admin");
|
||||
final var revokeAttempt = attempt(em, () -> {
|
||||
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
|
||||
});
|
||||
final var revokeAttempt = attempt(em, () ->
|
||||
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId()));
|
||||
|
||||
// then
|
||||
assertThat(revokeAttempt.caughtExceptionsRootCause()).isNull();
|
||||
@ -230,9 +227,8 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
|
||||
// when
|
||||
context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00.admin");
|
||||
final var revokeAttempt = attempt(em, () -> {
|
||||
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
|
||||
});
|
||||
final var revokeAttempt = attempt(em, () ->
|
||||
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId()));
|
||||
|
||||
// then
|
||||
revokeAttempt.assertExceptionWithRootCauseMessage(
|
||||
@ -255,10 +251,10 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
rbacGrantRepository.save(grant)
|
||||
);
|
||||
|
||||
assumeThat(grantAttempt.caughtException()).isNull();
|
||||
assumeThat(rawRbacGrantRepository.findAll())
|
||||
assertThat(grantAttempt.caughtException()).isNull();
|
||||
assertThat(rawRbacGrantRepository.findAll())
|
||||
.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
|
||||
));
|
||||
|
||||
|
@ -61,11 +61,6 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
assertThat(result.returnedValue()).isNotNull()
|
||||
.extracting(RbacUserEntity::getUuid).isEqualTo(givenUuid);
|
||||
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
|
||||
result.assertSuccessful();
|
||||
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;
|
||||
|
||||
import static java.util.UUID.randomUUID;
|
||||
|
||||
public class TestCustomer {
|
||||
|
||||
|
@ -16,7 +16,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.UUID;
|
||||
|
||||
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.is;
|
||||
|
||||
@ -85,7 +85,8 @@ class TestPackageControllerAcceptanceTest {
|
||||
@Test
|
||||
void withDescriptionUpdatesDescription() {
|
||||
|
||||
assumeThat(getDescriptionOfPackage("xxx00"))
|
||||
assertThat(getDescriptionOfPackage("xxx00"))
|
||||
.as("precondition failed")
|
||||
.isEqualTo("Here you can add your own description of package xxx00.");
|
||||
|
||||
final var randomDescription = RandomStringUtils.randomAlphanumeric(80);
|
||||
@ -117,7 +118,8 @@ class TestPackageControllerAcceptanceTest {
|
||||
@Test
|
||||
void withNullDescriptionUpdatesDescriptionToNull() {
|
||||
|
||||
assumeThat(getDescriptionOfPackage("xxx01"))
|
||||
assertThat(getDescriptionOfPackage("xxx01"))
|
||||
.as("precondition failed")
|
||||
.isEqualTo("Here you can add your own description of package xxx01.");
|
||||
|
||||
// @formatter:off
|
||||
@ -146,7 +148,8 @@ class TestPackageControllerAcceptanceTest {
|
||||
@Test
|
||||
void withoutDescriptionDoesNothing() {
|
||||
|
||||
assumeThat(getDescriptionOfPackage("xxx02"))
|
||||
assertThat(getDescriptionOfPackage("xxx02"))
|
||||
.as("precondition failed")
|
||||
.isEqualTo("Here you can add your own description of package xxx02.");
|
||||
|
||||
// @formatter:off
|
||||
|
@ -12,7 +12,6 @@ import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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.
|
||||
@ -138,7 +137,7 @@ public class JpaAttempt {
|
||||
}
|
||||
|
||||
public JpaResult<T> assumeSuccessful() {
|
||||
assumeThat(exception).as(firstRootCauseMessageLineOf(exception)).isNull();
|
||||
assertThat(exception).as(firstRootCauseMessageLineOf(exception)).isNull();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ spring:
|
||||
platform: postgres
|
||||
|
||||
datasource:
|
||||
url: jdbc:tc:postgresql:13.7-bullseye:///spring_boot_testcontainers
|
||||
url: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers
|
||||
url-local: jdbc:postgresql://localhost:5432/postgres
|
||||
username: postgres
|
||||
password: password
|
||||
|
Loading…
Reference in New Issue
Block a user