Skip to content

Commit

Permalink
Merge branch 'refs/heads/dev' into 320-openapispec-hinzufuegen
Browse files Browse the repository at this point in the history
  • Loading branch information
GerhardPx committed Jul 12, 2024
2 parents 374c04a + 5ef8110 commit be21ffc
Show file tree
Hide file tree
Showing 267 changed files with 9,529 additions and 825 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ See the [open issues](https://github.com/it-at-m/Wahllokalsystem/issues) for a f

## Documentation

*comming soon during the development*
We use [VitePress](https://vitepress.dev/) for our documentation. The sources for the documentation is also part of
this repository. After building the documentation is accessible via https://it-at-m.github.io/Wahllokalsystem/.

## Contributing

Expand Down
5 changes: 5 additions & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {withMermaid} from "vitepress-plugin-mermaid"

const PATH_TECHNIK = '/technik/';
const PATH_FEATURES = '/features/';
const PATH_GUIDES = '/guides/';

// https://vitepress.dev/reference/site-config
export default withMermaid({
Expand All @@ -16,6 +17,7 @@ export default withMermaid({
{text: 'Home', link: '/'},
{text: 'About', link: '/about/'},
{text: 'Features', link: '/features/'},
{text: 'Guides', link: PATH_GUIDES},
{text: 'Technik', link: PATH_TECHNIK}
],

Expand Down Expand Up @@ -53,6 +55,9 @@ export default withMermaid({
{text: 'Wahlvorstand-Service', link: `${PATH_FEATURES}wahlvorstand-service/`},
{text: 'Ergebnismeldung-Service', link: `${PATH_FEATURES}ergebnismeldung-service/`},
{text: 'Auth-Service', link: `${PATH_FEATURES}auth-service/`},
],
[PATH_GUIDES]: [
{text: 'API-Client generieren', link: `${PATH_GUIDES}how-to-create-client-from-open-api-json.md`}
]
},

Expand Down
9 changes: 8 additions & 1 deletion docs/src/features/basisdaten-service/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@ Service zur Bereitstellung folgender Basisdaten:
- Wahlbezirke
- Wahlvorschläge
- Kopfdaten
- Handbuch

Wahlen, Wahlbezirke und Kopfdaten können in der Service-Datenbank gespeichert werden.

## Abhängigkeiten

Folgende Services werden zum Betrieb benötigt:
- EAI-Service
- Infomanagement-Service
- Infomanagement-Service

## Handbuch

In dem Service werden Handbücher verwaltet. Je Wahl und Wahlbezirkart kann ein Handbuch hinterlegt werden.

Bei dem Handbuch soll es sich um ein PDF-Dokument handeln.
14 changes: 13 additions & 1 deletion docs/src/features/eai-service/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,16 @@ Wahlbeteiligungen der Wahllokale kann mitgeteilt werden.

### Wahllokalstatus

Der Zustand in dem sich die Wahllokale befinden kann mitgeteilt werden.
Der Zustand in dem sich die Wahllokale befinden kann mitgeteilt werden.

## Zugriffsbeschränkungen

Übersicht über die Endpunkte und die dafür benötigten Rechte:

| Endpunkt | erforderliche Rechte |
| --- | --- |
| GET /wahldaten/wahlbezirke/{wahlbezirkID}/wahlberechtigte | aoueai_BUSINESSACTION_LoadWahlberechtigte
| GET /wahldaten/wahltage?includingSince | aoueai_BUSINESSACTION_LoadWahltage
| GET /wahldaten/wahlbezirk?forDate&withNummer | aoueai_BUSINESSACTION_LoadWahlbezirke
| GET /wahldaten/wahlen?forDate&withNummer | aoueai_BUSINESSACTION_LoadWahlen
| GET /wahldaten/basisdaten?forDate&withNummer | aoueai_BUSINESSACTION_LoadBasisdaten
225 changes: 225 additions & 0 deletions docs/src/guides/how-to-create-client-from-open-api-json.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
# API-Client aus OpenAPI-Spec erstellen

## Einleitung

Alle Services stellen ihre API in Form einer OpenAPI Spezifikation zur Verfügung. Diese Dateien liegen den Assets
der jeweiligen Releases bei.

![Übersicht über Release von wls-eai-service Version 0.0.1-RC1](/screenshot-wls-eai-service-release-0.0.1-RC1.png)
*Übersicht über [Release](https://github.com/it-at-m/Wahllokalsystem/releases/tag/wls-eai-service%2F0.0.1-RC1) von
wls-eai-service Version 0.0.1-RC1*

Durch ein Maven-Plugin lassen sich aus der Datei `openapi.json` der Client generieren.

## Einfügen des Plugins

Um aus der Spezifikation die Java-Klassen zu erstellen, muss das Generator-Plugin eingebunden werden.

```xml

<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>7.5.0</version>
<executions>
</executions>
</plugin>
```

Für jeden zu erzeugenden Client mus ein `execution`-Element definiert werden.

## Konfigurieren der Ausführung

```xml

<execution>
<!-- wenn mehrere Clients erzeugt werden muss jede execution eine eindeutige ID haben -->
<id>generateEAI</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- Pfad zur JSON-Datei mit der OpenAPI-Beschreibung -->
<inputSpec>${project.basedir}/src/main/resources/openapis/openapi.eai.0.0.1-RC1.json</inputSpec>

<!-- Wir wollen Java-Klassen generieren-->
<generatorName>java</generatorName>
<!-- Als Client wird das Resttemplate verwendet-->
<library>resttemplate</library>

<!-- Package in dem die Clients der jeweiligen Controller erzeugt werden -->
<!-- Hier wird das Package für Zugriff auf den EAI-Service innerhalb des Basisdatenservices definiert -->
<apiPackage>${groupId}.basisdatenservice.eai.aou.client</apiPackage>
<!-- Package in das die Datenklassen erzeugt werden -->
<modelPackage>${groupId}.basisdatenservice.eai.aou.model</modelPackage>

<!-- Weitere Klassen als Grundlagen für zusätzliche Tests sind nicht erforderlich-->
<generateApiTests>false</generateApiTests>
<generateModelTests>false</generateModelTests>
<!-- Die zusätzliche Generierung der Dokumentation ist nicht erforderlich.
Das JavaDoc der Klassen enthält bereits die Dokumentation -->
<generateApiDocumentation>false</generateApiDocumentation>
<generateModelDocumentation>false</generateModelDocumentation>

<configOptions>
<!-- Fügt einen Zeitstempel mit dem Zeitpunkt der Generierung bei den Klassen ein -->
<hideGenerationTimestamp>false</hideGenerationTimestamp>
<!-- Empfohlen laut Doku -->
<legacyDiscriminatorBehavior>false</legacyDiscriminatorBehavior>
<!-- der Client wird mit @Component annotiert -->
<generateClientAsBean>true</generateClientAsBean>
<!-- damit da jakarta-Package verwendet wird -->
<useJakartaEe>true</useJakartaEe>
</configOptions>

<globalProperties>
<!-- zusätzliche Klassen, die notwendig sind damit die Clients korrekt arbeiten können -->
<supportingFiles>
BaseApi.java,ApiClient.java,JavaTimeFormatter.java,Authentication.java,OAuth.java,ApiKeyAuth.java,HttpBasicAuth.java,HttpBearerAuth.java,RFC3339DateFormat.java
</supportingFiles>
</globalProperties>
</configuration>
</execution>
```

Eine ausführliche Beschreibung alle Konfigurationsoptionen gibt es in der
[offiziellen Dokumentation](https://openapi-generator.tech/docs/generators/java/).

Bei der Konfiguration für die Packages soll folgendes Schema beachtet werden:
`<package von Microserviceapplication>.clients.<service>.(api|model)`

## Ergänzen von Dependencies

Damit die generierten Klassen compiliert werden können, muss folgende Dependency ergänzt werden:

```xml

<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.6</version>
</dependency>
```

Des Weiteren wird für die abschließende Konfiguration der Beans `wls-common:exception` benötigt:

```xml

<dependency>
<groupId>de.muenchen.oss.wahllokalsystem.wls-common</groupId>
<artifactId>exception</artifactId>
<version>1.1.0</version>
</dependency>
```

## Context um Beans erweitern

Damit der generierte Client verwendet werden kann, muss dem Spring-Context noch ein `RestTemplate` hinzugefügt werden:

```java

@Configuration
public class ClientConfiguration {

@Bean
public RestTemplate restTemplate(final WlsResponseErrorHandler wlsResponseErrorHandler) {
val restTemplate = new RestTemplate();

/* definieren des Errorhandlers für Antworten vom externen Service */
restTemplate.setErrorHandler(wlsResponseErrorHandler);
/* Ergänzen eines Interceptors um den Bearer-Token an den nächsten Service weiter zu geben */
restTemplate.getInterceptors().add((request, body, execution) -> {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
return execution.execute(request, body);
}

if (!(authentication.getCredentials() instanceof AbstractOAuth2Token)) {
return execution.execute(request, body);
}

val token = (AbstractOAuth2Token) authentication.getCredentials();
request.getHeaders().setBearerAuth(token.getTokenValue());
return execution.execute(request, body);
});

return restTemplate;
}

}
```

Wie zu erkennen ist, wird für das RestTemplate ein ErrorHandler benötigt, wobei wir hier den `WlsResponseErrorHandler`
aus `wls-common:exception` verwenden. Eine entsprechende Bean muss ebenfalls noch dem Spring-Context hinzugefügt werden:

```java
@Configuration
public class ClientConfiguration {

//other configurations like the restTemplate bean factory method

@Bean
public WlsResponseErrorHandler wlsResponseErrorHandler(final ObjectMapper objectMapper) {
return new WlsResponseErrorHandler(objectMapper);
}

}
```

## Target des Clients definieren

Nachdem jetzt alle Beans im Kontext sind, fehlt nur noch die Konfiguration unter welche Adresse der Service, für den wir
den Client generiert haben, erreichbar ist.

❗Diese Konfiguration darf nicht in derselben Konfigurationsklasse enthalten sein, in der das `RestTemplate` erstellt
wird, das sonst eine zirkulare Abhängigkeit vorliegt und die Anwendung nicht startet.

```java

@Configuration
@RequiredArgsConstructor
public class BasePathConfiguration {

/* Umgebungsvariable welche die Ziel-URL enthält, z.b. http//localhost:39146 */
@Value("${app.clients.eai.basePath}")
String eaiBasePath;

private final ApiClient eaiApiClient;

@PostConstruct
public void updateBasePaths() {
eaiApiClient.setBasePath(eaiBasePath);
}
}
```

In der `application.yml` wird der Defaultwert für die Ziel-URL hinterlegt:

```yml
app:
clients:
eai:
basePath: http://localhost:39146
```
## EAI-Client definieren und verwenden
Abschließend wird der EAI-Client, welche das Datenmodell des aufgerufenen externen Services auf das Datenmodell unseres
Services mappt, erstellt:
```java

@Component
@RequiredArgsConstructor
public class DemoClient {

private final WahlvorschlagControllerApi wahlvorschlagControllerApi;

public DemoDTO getDemo() {
val wahlvorschlaege = wahlvorschlagControllerApi.loadWahlvorschlaege("wahlID", "wahlbezirkID");

return new DemoDTO(wahlvorschlaege.getStimmzettelgebietID(), "" + wahlvorschlaege.getWahlvorschlaege().size());
}

}
```
Empty file added docs/src/guides/index.md
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion stack/.env
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@ WLS_INFOMANAGEMENT_SERVICE_KEYCLOAK_URL=http://kubernetes.docker.internal:8100/a

WLS_BRIEFWAHL_SERVICE_PROFILE=local,db-oracle
WLS_BRIEFWAHL_SERVICE_DB_URL=jdbc:oracle:thin:@//wls-db-oracle:1521/XEPDB1
WLS_BRIEFWAHL_SERVICE_KEYCLOAK_URL=http://kubernetes.docker.internal:8100/auth/realms/${SSO_REALM}/protocol/openid-connect
WLS_BRIEFWAHL_SERVICE_KEYCLOAK_URL=http://kubernetes.docker.internal:8100/auth/realms/${SSO_REALM}/protocol/openid-connect

WLS_WAHLVORBEREITUNG_SERVICE_PROFILE=local,db-oracle,dummy.nobezirkid.check
WLS_WAHLVORBEREITUNG_SERVICE_DB_URL=jdbc:oracle:thin:@//wls-db-oracle:1521/XEPDB1
WLS_WAHLVORBEREITUNG_SERVICE_KEYCLOAK_URL=http://kubernetes.docker.internal:8100/auth/realms/${SSO_REALM}/protocol/openid-connect

WLS_EAI_SERVICE_PROFILE=local,db-oracle,db-dummydata
WLS_EAI_SERVICE_DB_URL=jdbc:oracle:thin:@//wls-db-oracle:1521/XEPDB1
WLS_EAI_SERVICE_KEYCLOAK_URL=http://kubernetes.docker.internal:8100/auth/realms/${SSO_REALM}/protocol/openid-connect
47 changes: 44 additions & 3 deletions stack/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ services:
- SPRING_DATASOURCE_URL=${WLS_BROADCAST_SERVICE_DB_URL}
- SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK-SET-URI=${WLS_BROADCAST_SERVICE_KEYCLOAK_URL}/certs
- SECURITY_OAUTH2_RESOURCE_USER-INFO-URI=${WLS_BROADCAST_SERVICE_KEYCLOAK_URL}/userinfo
- SERVER_PORT=8080
ports:
- 8200:39146
- 8200:8080
networks:
- services
- keycloak
Expand All @@ -32,8 +33,9 @@ services:
- SPRING_DATASOURCE_URL=${WLS_INFOMANAGEMENT_SERVICE_DB_URL}
- SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK-SET-URI=${WLS_INFOMANAGEMENT_SERVICE_KEYCLOAK_URL}/certs
- SECURITY_OAUTH2_RESOURCE_USER-INFO-URI=${WLS_INFOMANAGEMENT_SERVICE_KEYCLOAK_URL}/userinfo
- SERVER_PORT=8080
ports:
- 8201:39146
- 8201:8080
networks:
- services
- keycloak
Expand All @@ -50,8 +52,47 @@ services:
- SPRING_DATASOURCE_URL=${WLS_BRIEFWAHL_SERVICE_DB_URL}
- SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK-SET-URI=${WLS_BRIEFWAHL_SERVICE_KEYCLOAK_URL}/certs
- SECURITY_OAUTH2_RESOURCE_USER-INFO-URI=${WLS_BRIEFWAHL_SERVICE_KEYCLOAK_URL}/userinfo
- SERVER_PORT=8080
ports:
- 8202:39146
- 8202:8080
networks:
- services
- keycloak

wls-wahlvorbereitung-service:
container_name: wls-wahlvorbereitung-service
image: ghcr.io/it-at-m/wahllokalsystem-wls-wahlvorbereitung-service:latest
depends_on:
- wls-db-oracle
env_file:
- .env
environment:
- SPRING_PROFILES_ACTIVE=${WLS_WAHLVORBEREITUNG_SERVICE_PROFILE}
- SPRING_DATASOURCE_URL=${WLS_WAHLVORBEREITUNG_SERVICE_DB_URL}
- SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK-SET-URI=${WLS_WAHLVORBEREITUNG_SERVICE_KEYCLOAK_URL}/certs
- SECURITY_OAUTH2_RESOURCE_USER-INFO-URI=${WLS_WAHLVORBEREITUNG_SERVICE_KEYCLOAK_URL}/userinfo
- SERVER_PORT=8080
ports:
- 8203:8080
networks:
- services
- keycloak

wls-eai-service:
container_name: wls-eai-service
image: ghcr.io/it-at-m/wahllokalsystem-wls-eai-service:latest
depends_on:
- wls-db-oracle
env_file:
- .env
environment:
- SPRING_PROFILES_ACTIVE=${WLS_EAI_SERVICE_PROFILE}
- SPRING_DATASOURCE_URL=${WLS_EAI_SERVICE_DB_URL}
- SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK-SET-URI=${WLS_EAI_SERVICE_KEYCLOAK_URL}/certs
- SECURITY_OAUTH2_RESOURCE_USER-INFO-URI=${WLS_EAI_SERVICE_KEYCLOAK_URL}/userinfo
- SERVER_PORT=8080
ports:
- 8300:8080
networks:
- services
- keycloak
Expand Down
Loading

0 comments on commit be21ffc

Please sign in to comment.