Skip to content

Commit 191cb2e

Browse files
authored
Merge pull request #95 from it-at-m/feat/eai-client
feat(ticketing-eai/client-internal): init
2 parents 4f238cc + 0e190c0 commit 191cb2e

File tree

10 files changed

+3942
-1
lines changed

10 files changed

+3942
-1
lines changed

.github/labeler.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
"Template: personalization-service":
66
- changed-files:
77
- any-glob-to-any-file: [ 'personalization-service/**' ]
8+
"Component: ticketing-eai":
9+
- changed-files:
10+
- any-glob-to-any-file: [ 'ticketing-eai/**' ]
811
"Component: ticketing-eventing":
912
- changed-files:
1013
- any-glob-to-any-file: [ 'ticketing-eventing/**' ]

.github/workflows/maven-node-build.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ jobs:
1717
include:
1818
- app-path: personalization-service
1919
- app-path: personalization-webcomponents
20+
- app-path: ticketing-eai/api-client-internal
21+
build-image: false
2022
- app-path: ticketing-eventing/eventing-service
2123

2224
steps:
@@ -31,7 +33,7 @@ jobs:
3133
uses: it-at-m/lhm_actions/action-templates/actions/action-maven-build@9767179088fd2e344d1a24c17404ab809a60f1b6 # v1.0.20
3234
with:
3335
app-path: ${{ matrix.app-path }}
34-
- if: github.ref == 'refs/heads/main'
36+
- if: github.ref == 'refs/heads/main' && matrix.build-image != 'false'
3537
uses: it-at-m/lhm_actions/action-templates/actions/action-build-image@9767179088fd2e344d1a24c17404ab809a60f1b6 # v1.0.20
3638
with:
3739
path: ${{ matrix.app-path }}

.github/workflows/maven-release.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ on:
1717
required: true
1818
options:
1919
- personalization-service
20+
- ticketing-eai/api-client-internal
2021
- ticketing-eventing/eventing-service
2122

2223
jobs:
@@ -41,6 +42,7 @@ jobs:
4142
GPG_PRIVATE_KEY: ${{ secrets.gpg_private_key }}
4243

4344
build-image:
45+
if: inputs.app-path != 'ticketing-eai/api-client-internal'
4446
runs-on: ubuntu-latest
4547
needs: release-maven
4648
steps:

ticketing-eai/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# ticketing-eai
2+
3+
EAI (enterprise application integration) for Zammad API with different endpoints for internal and external clients.
4+
5+
```mermaid
6+
flowchart LR
7+
EAI -->|REST| Zammad
8+
ic[Internal Clients] -->|Internal REST API| EAI
9+
ec[External Clients] -->|External REST API| EAI
10+
```
11+
12+
## components
13+
14+
- eai-service: TBD
15+
- [api-client](./api-client): Spring Java Client for making request against EAI based on eai OpenAPI spec
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>org.springframework.boot</groupId>
6+
<artifactId>spring-boot-starter-parent</artifactId>
7+
<version>3.5.4</version>
8+
<relativePath/>
9+
</parent>
10+
11+
<groupId>de.muenchen.oss.dbs.ticketing.eai</groupId>
12+
<artifactId>api-client-internal</artifactId>
13+
<name>api-client-internal</name>
14+
<description>API client for dbs-ticketing-eai internal endpoints</description>
15+
<version>0.1.0-SNAPSHOT</version>
16+
<url>https://github.com/it-at-m/dbs</url>
17+
<licenses>
18+
<license>
19+
<name>MIT</name>
20+
<url>https://opensource.org/licenses/MIT</url>
21+
<distribution>repo</distribution>
22+
</license>
23+
</licenses>
24+
<scm>
25+
<url>https://github.com/it-at-m/dbs.git</url>
26+
<connection>scm:git:https://github.com/it-at-m/dbs.git</connection>
27+
<developerConnection>scm:git:https://github.com/it-at-m/dbs.git</developerConnection>
28+
<tag>HEAD</tag>
29+
</scm>
30+
<developers>
31+
<developer>
32+
<organization>it@M</organization>
33+
<email>[email protected]</email>
34+
<url>https://github.com/it-at-m</url>
35+
</developer>
36+
</developers>
37+
38+
<properties>
39+
<openapi-generator-maven-plugin.version>7.14.0</openapi-generator-maven-plugin.version>
40+
<jackson-databind-nullable.version>0.2.6</jackson-databind-nullable.version>
41+
42+
<!-- Release -->
43+
<central-publishing-maven-plugin.version>0.8.0</central-publishing-maven-plugin.version>
44+
<maven-release-plugin.version>3.1.1</maven-release-plugin.version>
45+
<maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version>
46+
</properties>
47+
48+
<dependencies>
49+
<!-- Spring -->
50+
<dependency>
51+
<groupId>org.springframework</groupId>
52+
<artifactId>spring-webflux</artifactId>
53+
</dependency>
54+
<dependency>
55+
<groupId>org.springframework.boot</groupId>
56+
<artifactId>spring-boot-starter-logging</artifactId>
57+
</dependency>
58+
<dependency>
59+
<groupId>org.springframework.boot</groupId>
60+
<artifactId>spring-boot-starter-validation</artifactId>
61+
</dependency>
62+
<dependency>
63+
<groupId>org.springframework.security</groupId>
64+
<artifactId>spring-security-oauth2-client</artifactId>
65+
</dependency>
66+
<dependency>
67+
<groupId>org.springframework.boot</groupId>
68+
<artifactId>spring-boot-configuration-processor</artifactId>
69+
<optional>true</optional>
70+
</dependency>
71+
72+
<!-- openApi -->
73+
<dependency>
74+
<groupId>org.openapitools</groupId>
75+
<artifactId>jackson-databind-nullable</artifactId>
76+
<version>${jackson-databind-nullable.version}</version>
77+
</dependency>
78+
<dependency>
79+
<groupId>com.fasterxml.jackson.datatype</groupId>
80+
<artifactId>jackson-datatype-jsr310</artifactId>
81+
</dependency>
82+
</dependencies>
83+
84+
<build>
85+
<plugins>
86+
<!-- OpenAPI -->
87+
<plugin>
88+
<groupId>org.openapitools</groupId>
89+
<artifactId>openapi-generator-maven-plugin</artifactId>
90+
<version>${openapi-generator-maven-plugin.version}</version>
91+
<executions>
92+
<execution>
93+
<goals>
94+
<goal>generate</goal>
95+
</goals>
96+
<configuration>
97+
<inputSpec>${project.basedir}/src/main/resources/api-spec-internal-without-security.json</inputSpec>
98+
<library>webclient</library>
99+
<generatorName>java</generatorName>
100+
101+
<apiPackage>de.muenchen.oss.dbs.ticketing.eai.client.api</apiPackage>
102+
<modelPackage>de.muenchen.oss.dbs.ticketing.eai.client.model</modelPackage>
103+
<invokerPackage>de.muenchen.oss.dbs.ticketing.eai.client</invokerPackage>
104+
105+
<serverVariableOverrides />
106+
<configOptions>
107+
<useJakartaEe>true</useJakartaEe>
108+
<useAbstractionForFiles>true</useAbstractionForFiles>
109+
</configOptions>
110+
</configuration>
111+
</execution>
112+
</executions>
113+
</plugin>
114+
<plugin>
115+
<groupId>org.apache.maven.plugins</groupId>
116+
<artifactId>maven-source-plugin</artifactId>
117+
<executions>
118+
<execution>
119+
<id>attach-sources</id>
120+
<goals>
121+
<goal>jar-no-fork</goal>
122+
</goals>
123+
</execution>
124+
</executions>
125+
</plugin>
126+
<plugin>
127+
<groupId>org.apache.maven.plugins</groupId>
128+
<artifactId>maven-javadoc-plugin</artifactId>
129+
<configuration>
130+
<doclint>accessibility,html,reference,syntax</doclint>
131+
</configuration>
132+
<executions>
133+
<execution>
134+
<id>attach-javadocs</id>
135+
<goals>
136+
<goal>jar</goal>
137+
</goals>
138+
</execution>
139+
</executions>
140+
</plugin>
141+
<!-- Release -->
142+
<plugin>
143+
<groupId>org.apache.maven.plugins</groupId>
144+
<artifactId>maven-release-plugin</artifactId>
145+
<version>${maven-release-plugin.version}</version>
146+
<configuration>
147+
<autoVersionSubmodules>true</autoVersionSubmodules>
148+
<useReleaseProfile>false</useReleaseProfile>
149+
<releaseProfiles>release</releaseProfiles>
150+
<goals>deploy</goals>
151+
</configuration>
152+
</plugin>
153+
</plugins>
154+
</build>
155+
156+
<profiles>
157+
<profile>
158+
<id>release</id>
159+
<build>
160+
<plugins>
161+
<!-- Central Portal Publishing Plugin -->
162+
<plugin>
163+
<groupId>org.sonatype.central</groupId>
164+
<artifactId>central-publishing-maven-plugin</artifactId>
165+
<version>${central-publishing-maven-plugin.version}</version>
166+
<extensions>true</extensions>
167+
<configuration>
168+
<autoPublish>true</autoPublish>
169+
<deploymentName>${project.groupId}:${project.artifactId}:${project.version}</deploymentName>
170+
</configuration>
171+
</plugin>
172+
<!-- GPG plugin -->
173+
<plugin>
174+
<groupId>org.apache.maven.plugins</groupId>
175+
<artifactId>maven-gpg-plugin</artifactId>
176+
<version>${maven-gpg-plugin.version}</version>
177+
<executions>
178+
<execution>
179+
<id>sign-artifacts</id>
180+
<phase>verify</phase>
181+
<goals>
182+
<goal>sign</goal>
183+
</goals>
184+
<configuration>
185+
<!-- Prevent `gpg` from using pinentry programs -->
186+
<gpgArguments>
187+
<arg>--pinentry-mode</arg>
188+
<arg>loopback</arg>
189+
</gpgArguments>
190+
</configuration>
191+
</execution>
192+
</executions>
193+
</plugin>
194+
</plugins>
195+
</build>
196+
</profile>
197+
</profiles>
198+
</project>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package de.muenchen.oss.dbs.ticketing.eai.client;
2+
3+
import de.muenchen.oss.dbs.ticketing.eai.client.api.ArticlesApi;
4+
import de.muenchen.oss.dbs.ticketing.eai.client.api.OrganizationsApi;
5+
import de.muenchen.oss.dbs.ticketing.eai.client.api.TicketsApi;
6+
import de.muenchen.oss.dbs.ticketing.eai.client.api.UsersApi;
7+
import org.springframework.boot.autoconfigure.AutoConfiguration;
8+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
9+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
10+
import org.springframework.context.annotation.Bean;
11+
import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
12+
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
13+
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
14+
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction;
15+
import org.springframework.web.reactive.function.client.WebClient;
16+
17+
@AutoConfiguration
18+
@EnableConfigurationProperties({ApiClientProperties.class})
19+
public class ApiClientAutoConfiguration {
20+
@Bean
21+
@ConditionalOnMissingBean
22+
public ApiClient apiClient(final ApiClientProperties apiClientProperties,
23+
final ClientRegistrationRepository clientRegistrationRepository,
24+
final OAuth2AuthorizedClientService authorizedClientService) {
25+
final ServletOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
26+
new AuthorizedClientServiceOAuth2AuthorizedClientManager(
27+
clientRegistrationRepository, authorizedClientService));
28+
oauth.setDefaultClientRegistrationId(apiClientProperties.getOauthClientRegistration());
29+
final WebClient webClient = ApiClient.buildWebClientBuilder()
30+
.apply(oauth.oauth2Configuration())
31+
.build();
32+
final ApiClient apiClient = new ApiClient(webClient);
33+
apiClient.setBasePath(apiClientProperties.getEaiBaseUrl());
34+
return apiClient;
35+
}
36+
37+
@Bean
38+
@ConditionalOnMissingBean
39+
public TicketsApi ticketsApi(final ApiClient apiClient) {
40+
return new TicketsApi(apiClient);
41+
}
42+
43+
@Bean
44+
@ConditionalOnMissingBean
45+
public ArticlesApi articlesApi(final ApiClient apiClient) {
46+
return new ArticlesApi(apiClient);
47+
}
48+
49+
@Bean
50+
@ConditionalOnMissingBean
51+
public OrganizationsApi organizationsApi(final ApiClient apiClient) {
52+
return new OrganizationsApi(apiClient);
53+
}
54+
55+
@Bean
56+
@ConditionalOnMissingBean
57+
public UsersApi usersApi(final ApiClient apiClient) {
58+
return new UsersApi(apiClient);
59+
}
60+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package de.muenchen.oss.dbs.ticketing.eai.client;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import org.springframework.boot.context.properties.ConfigurationProperties;
5+
import org.springframework.validation.annotation.Validated;
6+
7+
@ConfigurationProperties("dbs.eai.client")
8+
@Validated
9+
public class ApiClientProperties {
10+
/**
11+
* Base URL of the ticket-eai-service to make API calls against.
12+
*/
13+
@NotBlank
14+
private String eaiBaseUrl;
15+
/**
16+
* Name of the client registration configured via Spring oAuth client to use for authenticating API requests.
17+
*/
18+
@NotBlank
19+
private String oauthClientRegistration = "zammad";
20+
21+
public String getEaiBaseUrl() {
22+
return eaiBaseUrl;
23+
}
24+
25+
public void setEaiBaseUrl(String eaiBaseUrl) {
26+
this.eaiBaseUrl = eaiBaseUrl;
27+
}
28+
29+
public String getOauthClientRegistration() {
30+
return oauthClientRegistration;
31+
}
32+
33+
public void setOauthClientRegistration(String oauthClientRegistration) {
34+
this.oauthClientRegistration = oauthClientRegistration;
35+
}
36+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
de.muenchen.oss.dbs.ticketing.eai.client.ApiClientAutoConfiguration

0 commit comments

Comments
 (0)