Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RISDEV-6627 Add PUT endpoint #188

Merged
merged 2 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
indent_style = space
indent_style = space
andreas-deazevedo marked this conversation as resolved.
Show resolved Hide resolved
indent_size = 2
280 changes: 140 additions & 140 deletions backend/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,190 +2,190 @@ import com.diffplug.spotless.LineEnding
import com.github.jk1.license.filter.LicenseBundleNormalizer

plugins {
java
id("org.springframework.boot") version "3.4.2"
id("io.spring.dependency-management") version "1.1.7"
id("jacoco")
id("org.sonarqube") version "6.0.1.5171"
id("com.github.jk1.dependency-license-report") version "2.9"
id("com.diffplug.spotless") version "7.0.2"
java
id("org.springframework.boot") version "3.4.2"
id("io.spring.dependency-management") version "1.1.7"
id("jacoco")
id("org.sonarqube") version "6.0.1.5171"
id("com.github.jk1.dependency-license-report") version "2.9"
id("com.diffplug.spotless") version "7.0.2"
}

group = "de.bund.digitalservice"
version = "0.0.1-SNAPSHOT"

java {
toolchain {
languageVersion = JavaLanguageVersion.of(23)
}
toolchain {
languageVersion = JavaLanguageVersion.of(23)
}
}

configurations {
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
}

repositories {
mavenCentral()
mavenCentral()
}

val kubernetesConfigVersion = "3.2.0"
val protobufVersion = "3.25.6"
val joseVersion = "0.9.4"
val okioVersion = "3.4.0"
dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.cloud:spring-cloud-starter-kubernetes-client-config:$kubernetesConfigVersion") {
exclude("com.google.protobuf", "protobuf-java")

// https://github.com/digitalservicebund/ris-adm-vwv/security/code-scanning/12
exclude("org.bitbucket.b_c", "jose4j")

// https://github.com/digitalservicebund/ris-adm-vwv/security/code-scanning/11
exclude("com.squareup.okio", "okio-jvm")
}
implementation("com.google.protobuf:protobuf-java:$protobufVersion")
implementation("org.bitbucket.b_c:jose4j:$joseVersion")
implementation("com.squareup.okio:okio-jvm:$okioVersion")
implementation("org.flywaydb:flyway-core")
implementation("org.flywaydb:flyway-database-postgresql")
implementation("org.springframework.session:spring-session-core")
compileOnly("org.projectlombok:lombok")
developmentOnly("org.springframework.boot:spring-boot-docker-compose")
runtimeOnly("org.postgresql:postgresql")
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.boot:spring-boot-testcontainers")
testImplementation("org.springframework.security:spring-security-test")
testImplementation("org.testcontainers:junit-jupiter")
testImplementation("org.testcontainers:postgresql")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.cloud:spring-cloud-starter-kubernetes-client-config:$kubernetesConfigVersion") {
exclude("com.google.protobuf", "protobuf-java")

// https://github.com/digitalservicebund/ris-adm-vwv/security/code-scanning/12
exclude("org.bitbucket.b_c", "jose4j")

// https://github.com/digitalservicebund/ris-adm-vwv/security/code-scanning/11
exclude("com.squareup.okio", "okio-jvm")
}
implementation("com.google.protobuf:protobuf-java:$protobufVersion")
implementation("org.bitbucket.b_c:jose4j:$joseVersion")
implementation("com.squareup.okio:okio-jvm:$okioVersion")
implementation("org.flywaydb:flyway-core")
implementation("org.flywaydb:flyway-database-postgresql")
implementation("org.springframework.session:spring-session-core")
compileOnly("org.projectlombok:lombok")
developmentOnly("org.springframework.boot:spring-boot-docker-compose")
runtimeOnly("org.postgresql:postgresql")
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.boot:spring-boot-testcontainers")
testImplementation("org.springframework.security:spring-security-test")
testImplementation("org.testcontainers:junit-jupiter")
testImplementation("org.testcontainers:postgresql")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

tasks.withType<Test> {
useJUnitPlatform()
useJUnitPlatform()
}

jacoco {
toolVersion = "0.8.12"
toolVersion = "0.8.12"
}

tasks.jacocoTestReport {
// dependsOn(tasks.test)

// Jacoco hooks into all tasks of type: Test automatically, but results for each of these
// tasks are kept separately and are not combined out of the box. we want to gather
// coverage of our unit and integration tests as a single report!
executionData.setFrom(
files(
fileTree(project.layout.buildDirectory) {
include("jacoco/*.exec")
},
),
)
reports {
xml.required = true
html.required = true
}
dependsOn("test") // All tests are required to run before generating a report.
// dependsOn(tasks.test)

// Jacoco hooks into all tasks of type: Test automatically, but results for each of these
// tasks are kept separately and are not combined out of the box. we want to gather
// coverage of our unit and integration tests as a single report!
executionData.setFrom(
files(
fileTree(project.layout.buildDirectory) {
include("jacoco/*.exec")
},
),
)
reports {
xml.required = true
html.required = true
}
dependsOn("test") // All tests are required to run before generating a report.
}

tasks.getByName("sonar") {
dependsOn("jacocoTestReport")
dependsOn("jacocoTestReport")
}

sonar {
// NOTE: sonarqube picks up combined coverage correctly without further configuration from:
// build/reports/jacoco/test/jacocoTestReport.xml
properties {
// we don't use "sonar-project.properties", but define the properties here
property("sonar.projectKey", "ris-adm-vwv-backend")
property("sonar.organization", "digitalservicebund")
property("sonar.host.url", "https://sonarcloud.io")
property("sonar.token", System.getenv("SONAR_TOKEN"))
property("sonar.coverage.exclusions", "**/Application.java")
}
// NOTE: sonarqube picks up combined coverage correctly without further configuration from:
// build/reports/jacoco/test/jacocoTestReport.xml
properties {
// we don't use "sonar-project.properties", but define the properties here
property("sonar.projectKey", "ris-adm-vwv-backend")
property("sonar.organization", "digitalservicebund")
property("sonar.host.url", "https://sonarcloud.io")
property("sonar.token", System.getenv("SONAR_TOKEN"))
property("sonar.coverage.exclusions", "**/Application.java")
}
}

tasks.bootBuildImage {
val containerImageRef = System.getenv("IMAGE_REF") ?: "ghcr.io/digitalservicebund/${rootProject.name}:latest"
val containerRegistry = System.getenv("CONTAINER_REGISTRY") ?: "ghcr.io"

imageName.set(containerImageRef)
builder.set("paketobuildpacks/builder-noble-java-tiny:latest")
publish.set(false)
runImage.set("cgr.dev/chainguard/jre@sha256:6207f817070fae80779cdcf5ab3d24880e8c4fe19a31af24b3b5e850eda3d80e")

docker {
publishRegistry {
username.set(System.getenv("CONTAINER_REGISTRY_USER") ?: "")
password.set(System.getenv("CONTAINER_REGISTRY_PASSWORD") ?: "")
url.set("https://$containerRegistry")
}
val containerImageRef = System.getenv("IMAGE_REF") ?: "ghcr.io/digitalservicebund/${rootProject.name}:latest"
val containerRegistry = System.getenv("CONTAINER_REGISTRY") ?: "ghcr.io"

imageName.set(containerImageRef)
builder.set("paketobuildpacks/builder-noble-java-tiny:latest")
publish.set(false)
runImage.set("cgr.dev/chainguard/jre@sha256:6207f817070fae80779cdcf5ab3d24880e8c4fe19a31af24b3b5e850eda3d80e")

docker {
publishRegistry {
username.set(System.getenv("CONTAINER_REGISTRY_USER") ?: "")
password.set(System.getenv("CONTAINER_REGISTRY_PASSWORD") ?: "")
url.set("https://$containerRegistry")
}
}
}

licenseReport {
// If there's a new dependency with a yet unknown license causing this task to fail
// the license(s) will be listed in build/reports/dependency-license/dependencies-without-allowed-license.json
allowedLicensesFile = File("$projectDir/../allowed-licenses.json")
filters =
arrayOf(
// With second arg true we get the default transformations:
// https://github.com/jk1/Gradle-License-Report/blob/7cf695c38126b63ef9e907345adab84dfa92ea0e/src/main/resources/default-license-normalizer-bundle.json
LicenseBundleNormalizer(null as String?, true),
)
allowedLicensesFile = File("$projectDir/../allowed-licenses.json")
filters =
arrayOf(
// With second arg true we get the default transformations:
// https://github.com/jk1/Gradle-License-Report/blob/7cf695c38126b63ef9e907345adab84dfa92ea0e/src/main/resources/default-license-normalizer-bundle.json
LicenseBundleNormalizer(null as String?, true),
)
}

spotless {
kotlin {
// Note that changes to the ktlint() default settings are done in .editorconfig
ktlint("1.4.1")
}

kotlinGradle {
ktlint("1.4.1")
}

java {
removeUnusedImports()
prettier(
mapOf(
"prettier" to "3.0.3",
"prettier-plugin-java" to "2.3.0",
),
).config(
mapOf(
"parser" to "java",
"printWidth" to 100,
"plugins" to listOf("prettier-plugin-java"),
),
)
}

format("misc") {
target(
"**/*.js",
"**/*.json",
"**/*.md",
"**/*.properties",
"**/*.sh",
"**/*.yml",
)
prettier(
mapOf(
"prettier" to "2.6.1",
"prettier-plugin-sh" to "0.7.1",
"prettier-plugin-properties" to "0.1.0",
),
).config(mapOf("keySeparator" to "="))
}
if (System.getProperty("os.name", "undefined").contains("Windows")) {
lineEndings = LineEnding.UNIX
}
kotlin {
// Note that changes to the ktlint() default settings are done in .editorconfig
ktlint("1.4.1")
}

kotlinGradle {
ktlint("1.4.1")
}

java {
removeUnusedImports()
prettier(
mapOf(
"prettier" to "3.0.3",
"prettier-plugin-java" to "2.3.0",
),
).config(
mapOf(
"parser" to "java",
"printWidth" to 100,
"plugins" to listOf("prettier-plugin-java"),
),
)
}

format("misc") {
target(
"**/*.js",
"**/*.json",
"**/*.md",
"**/*.properties",
"**/*.sh",
"**/*.yml",
)
prettier(
mapOf(
"prettier" to "2.6.1",
"prettier-plugin-sh" to "0.7.1",
"prettier-plugin-properties" to "0.1.0",
),
).config(mapOf("keySeparator" to "="))
}
if (System.getProperty("os.name", "undefined").contains("Windows")) {
lineEndings = LineEnding.UNIX
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package de.bund.digitalservice.ris.adm_vwv.adapter.api;

import com.fasterxml.jackson.databind.JsonNode;
import de.bund.digitalservice.ris.adm_vwv.application.CreateDocumentationUnitPort;
import de.bund.digitalservice.ris.adm_vwv.application.DocumentationUnit;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
Expand All @@ -24,4 +24,15 @@ public class DocumentationUnitController {
public DocumentationUnit create() {
return createDocumentationUnitPort.create();
}

@PutMapping("api/documentation-units/{documentNumber}")
public ResponseEntity<DocumentationUnit> update(
andreas-deazevedo marked this conversation as resolved.
Show resolved Hide resolved
@PathVariable String documentNumber,
@RequestBody JsonNode documentationUnit
) {
return createDocumentationUnitPort
.update(documentNumber, documentationUnit.toString())
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import de.bund.digitalservice.ris.adm_vwv.application.DocumentationUnit;
import de.bund.digitalservice.ris.adm_vwv.application.DocumentationUnitPersistencePort;
import jakarta.annotation.Nonnull;
import java.security.SecureRandom;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
Expand All @@ -25,6 +26,18 @@ public DocumentationUnit create() {
new SecureRandom().nextInt(1000)
);
DocumentationUnitEntity saved = documentationUnitRepository.save(documentationUnitEntity);
return new DocumentationUnit(saved.getDocumentNumber(), saved.getId());
return new DocumentationUnit(saved.getDocumentNumber(), saved.getId(), null);
}

@Override
@Transactional
public DocumentationUnit update(@Nonnull String documentNumber, @Nonnull String json) {
return documentationUnitRepository
.findByDocumentNumber(documentNumber)
.map(due -> {
andreas-deazevedo marked this conversation as resolved.
Show resolved Hide resolved
due.setJson(json);
return new DocumentationUnit(documentNumber, due.getId(), json);
})
.orElse(null);
}
}
Loading
Loading