Skip to content

Commit 4963ab3

Browse files
committed
feat(eventing-service): init
1 parent 77b873d commit 4963ab3

File tree

9 files changed

+100
-20
lines changed

9 files changed

+100
-20
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
@SpringBootApplication
1111
@ConfigurationPropertiesScan
1212
@SuppressWarnings("PMD.UseUtilityClass")
13-
public class MicroServiceApplication {
13+
public class DbsTicketingEventingService {
1414
public static void main(final String[] args) {
15-
SpringApplication.run(MicroServiceApplication.class, args);
15+
SpringApplication.run(DbsTicketingEventingService.class, args);
1616
}
1717
}

ticketing-eventing/eventing-service/src/main/java/de/muenchen/oss/dbs/ticketing/eventing/service/adapter/in/rest/EventMapper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import de.muenchen.oss.dbs.ticketing.eventing.service.domain.model.Event;
44
import org.mapstruct.Mapper;
5+
import org.springframework.stereotype.Component;
56

7+
@Component
68
@Mapper
79
interface EventMapper {
810
Event fromDto(String action, EventDTO dto);

ticketing-eventing/eventing-service/src/main/java/de/muenchen/oss/dbs/ticketing/eventing/service/adapter/in/rest/RestAdapter.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import de.muenchen.oss.dbs.ticketing.eventing.service.configuration.DbsEventingProperties;
44
import de.muenchen.oss.dbs.ticketing.eventing.service.core.port.in.HandleEventInPort;
55
import de.muenchen.oss.dbs.ticketing.eventing.service.domain.model.Event;
6+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
7+
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
68
import lombok.RequiredArgsConstructor;
79
import lombok.extern.slf4j.Slf4j;
810
import org.springframework.http.HttpStatus;
@@ -13,31 +15,42 @@
1315
import org.springframework.web.bind.annotation.RestController;
1416
import org.springframework.web.server.ResponseStatusException;
1517

18+
import static de.muenchen.oss.dbs.ticketing.eventing.service.configuration.OpenAPIDocumentationConfiguration.BASIC_SCHEME_NAME;
19+
1620
@Service
17-
@RestController("/api/")
21+
@RestController
1822
@RequiredArgsConstructor
1923
@Slf4j
2024
public class RestAdapter {
21-
private static final String TRIGGER_HEADER = "X-Zammad-Trigger";
22-
private static final String ID_HEADER = "X-Zammad-Delivery";
25+
private static final String HEADER_TRIGGER_NAME = "X-Zammad-Trigger";
26+
private static final String HEADER_DELIVERY_ID = "X-Zammad-Delivery";
2327

2428
private final DbsEventingProperties dbsEventingProperties;
2529
private final HandleEventInPort handleEventInPort;
2630
private final EventMapper eventMapper;
2731

28-
@PostMapping("event")
32+
/**
33+
* Endpoint for receiving Zammad webhook events.
34+
*
35+
* @param triggerName Name of the trigger of the event
36+
* @param deliveryId Random unique identifier of event
37+
* @param eventDto Event payload
38+
*/
39+
@PostMapping("/api/event")
40+
@SecurityRequirement(name = BASIC_SCHEME_NAME)
41+
@ApiResponse(responseCode = "200", description = "Successfully processed event")
2942
public void event(
30-
@RequestHeader(TRIGGER_HEADER) final String trigger,
31-
@RequestHeader(ID_HEADER) final String deliveryId,
43+
@RequestHeader(HEADER_TRIGGER_NAME) final String triggerName,
44+
@RequestHeader(HEADER_DELIVERY_ID) final String deliveryId,
3245
@RequestBody final EventDTO eventDto) {
33-
log.info("Received event {} from trigger {}: {}", deliveryId, trigger, eventDto);
34-
final String action = dbsEventingProperties.getTriggerMapping().get(trigger);
46+
log.info("Received event '{}' from trigger '{}': {}", deliveryId, triggerName, eventDto);
47+
final String action = dbsEventingProperties.mapTriggerToAction(triggerName);
3548
if (action == null) {
36-
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "No mapping for trigger %s".formatted(trigger));
49+
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "No mapping for trigger '%s'".formatted(triggerName));
3750
}
3851
final Event event = eventMapper.fromDto(action, eventDto);
39-
log.debug("Mapped trigger {} and payload to event {}", trigger, event);
52+
log.debug("Mapped trigger '{}' and payload to event {}", triggerName, event);
4053
handleEventInPort.handleEvent(event);
41-
log.debug("Handled event successfully");
54+
log.debug("Handled event '{}' successfully", deliveryId);
4255
}
4356
}
Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,54 @@
11
package de.muenchen.oss.dbs.ticketing.eventing.service.configuration;
22

3+
import jakarta.validation.Valid;
4+
import jakarta.validation.constraints.NotBlank;
35
import jakarta.validation.constraints.NotNull;
4-
import java.util.Map;
6+
7+
import java.util.List;
8+
59
import lombok.Getter;
610
import lombok.Setter;
711
import org.springframework.boot.context.properties.ConfigurationProperties;
12+
import org.springframework.boot.context.properties.NestedConfigurationProperty;
813
import org.springframework.context.annotation.Configuration;
14+
import org.springframework.validation.annotation.Validated;
915

1016
@Configuration
1117
@ConfigurationProperties("dbs.eventing")
1218
@Getter
1319
@Setter
20+
@Validated
1421
public class DbsEventingProperties {
15-
@NotNull private Map<String, String> triggerMapping;
22+
/**
23+
* Map for transforming trigger name into action.
24+
* Decouples trigger name from event action.
25+
*/
26+
@NestedConfigurationProperty @Valid
27+
@NotNull private List<TriggerMatching> triggerMapping;
28+
29+
/**
30+
* Maps a trigger name to the according action.
31+
* See {@link #triggerMapping}
32+
*
33+
* @param triggerName Name of the trigger
34+
* @return According action
35+
*/
36+
public String mapTriggerToAction(final String triggerName) {
37+
return triggerMapping.stream()
38+
// TODO case insensitive?
39+
.filter(i -> i.triggerName.equals(triggerName))
40+
.findFirst()
41+
.map(TriggerMatching::action).orElse(null);
42+
}
43+
44+
/**
45+
* Mapping from trigger name to action.
46+
*
47+
* @param triggerName The name of the trigger.
48+
* @param action The action to map to.
49+
*/
50+
public record TriggerMatching(
51+
@NotBlank String triggerName,
52+
@NotBlank String action
53+
) {}
1654
}
Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package de.muenchen.oss.dbs.ticketing.eventing.service.configuration;
22

3+
import io.swagger.v3.oas.models.Components;
34
import io.swagger.v3.oas.models.OpenAPI;
45
import io.swagger.v3.oas.models.info.Info;
6+
import io.swagger.v3.oas.models.security.SecurityRequirement;
7+
import io.swagger.v3.oas.models.security.SecurityScheme;
58
import lombok.RequiredArgsConstructor;
69
import org.springframework.context.annotation.Bean;
710
import org.springframework.context.annotation.Configuration;
@@ -10,11 +13,23 @@
1013
@RequiredArgsConstructor
1114
public class OpenAPIDocumentationConfiguration {
1215

16+
public static final String BASIC_SCHEME_NAME = "basicScheme";
17+
private static final String BASIC_SCHEME = "basic";
18+
1319
private final OpenAPIProperties openAPIProperties;
1420

1521
@Bean
1622
public OpenAPI customOpenAPI() {
1723
return new OpenAPI()
18-
.info(new Info().title(openAPIProperties.getName()).description(openAPIProperties.getDescription()).version(openAPIProperties.getVersion()));
24+
.info(new Info()
25+
.title(openAPIProperties.getName())
26+
.description(openAPIProperties.getDescription())
27+
.version(openAPIProperties.getVersion()))
28+
.components(new Components()
29+
.addSecuritySchemes(BASIC_SCHEME_NAME,
30+
new SecurityScheme()
31+
.type(SecurityScheme.Type.HTTP)
32+
.scheme(BASIC_SCHEME)))
33+
.addSecurityItem(new SecurityRequirement().addList(BASIC_SCHEME));
1934
}
2035
}

ticketing-eventing/eventing-service/src/main/java/de/muenchen/oss/dbs/ticketing/eventing/service/configuration/security/SecurityConfiguration.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
1313
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
1414
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
15+
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
1516
import org.springframework.security.web.SecurityFilterChain;
1617
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
1718

@@ -58,6 +59,8 @@ public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception
5859
.authorizeHttpRequests((requests) -> requests
5960
.anyRequest()
6061
.authenticated())
62+
// disable CSRF as server only api without preflight requests
63+
.csrf(AbstractHttpConfigurer::disable)
6164
.httpBasic(Customizer.withDefaults());
6265

6366
return http.build();

ticketing-eventing/eventing-service/src/main/java/de/muenchen/oss/dbs/ticketing/eventing/service/domain/model/Event.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package de.muenchen.oss.dbs.ticketing.eventing.service.domain.model;
22

3+
import jakarta.validation.constraints.NotBlank;
4+
35
public record Event(
4-
String action,
5-
String ticket,
6+
@NotBlank String action,
7+
@NotBlank String ticket,
68
String status,
79
String status_id,
810
String anliegenart,

ticketing-eventing/eventing-service/src/main/resources/application-local.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,11 @@ logging:
3131
level:
3232
root: INFO
3333
de.muenchen.oss.dbs.ticketing.eventing: DEBUG
34-
org.springframework.cache: TRACE
3534
org.springframework.web: DEBUG
35+
org.springframework.security: DEBUG
36+
37+
dbs:
38+
eventing:
39+
trigger-mapping:
40+
- trigger-name: "Trigger Name"
41+
action: "ticket_create"

ticketing-eventing/eventing-service/src/main/resources/application.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ server:
2525
error:
2626
whitelabel:
2727
enabled: false
28+
include-message: always
2829

2930
# Config for spring actuator endpoints
3031
management:
@@ -61,7 +62,6 @@ management:
6162
enabled: true
6263

6364
springdoc:
64-
show-actuator: true
6565
# Disable swagger-ui as default
6666
swagger-ui:
6767
enabled: false
@@ -72,6 +72,7 @@ springdoc:
7272
logging:
7373
level:
7474
root: info
75+
org.apache.kafka: warn
7576
structured:
7677
format:
7778
console: logstash

0 commit comments

Comments
 (0)