Skip to content
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
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ apply {
}

dependencies {
implementation(group: 'uk.gov.hmcts.cp', name: 'api-cp-crime-hearing-case-event-subscription', version: '0.1.0-724f10f')
implementation(group: 'uk.gov.hmcts.cp', name: 'api-cp-crime-hearing-case-event-subscription', version: '1.0.0')

// This is proving to be a real puzzle. This is actually included in the api published pom
// ( though with scope of "runtime" )
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package uk.gov.hmcts.cp.http;

import org.junit.jupiter.api.Test;
import org.springframework.http.*;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import uk.gov.hmcts.cp.openapi.model.ClientSubscriptionRequest;
import uk.gov.hmcts.cp.services.SubscriptionService;

import java.util.UUID;

@RestController
@RequiredArgsConstructor
@Slf4j
Expand All @@ -23,4 +25,12 @@ public ResponseEntity<ClientSubscription> createClientSubscription(final ClientS
log.info("createClientSubscription created subscription:{}", response.getClientSubscriptionId());
return ResponseEntity.ok(response);
}

@Override
public ResponseEntity<ClientSubscription> getClientSubscription(final UUID clientSubscriptionId) {
log.info("getClientSubscription clientId:{}", "TODO");
final ClientSubscription response = subscriptionService.getSubscription(clientSubscriptionId);
log.info("createClientSubscription returning subscription:{}", response.getClientSubscriptionId());
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package uk.gov.hmcts.cp.entities;

import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand All @@ -11,9 +9,7 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import uk.gov.hmcts.cp.model.EventType;
import uk.gov.hmcts.cp.model.EntityEventType;

import java.time.OffsetDateTime;
import java.util.List;
Expand All @@ -32,10 +28,7 @@ public class ClientSubscriptionEntity {
private UUID id;

private String notificationEndpoint;
@Enumerated(EnumType.STRING)
private List<EventType> eventTypes;
@CreationTimestamp
private List<EntityEventType> eventTypes;
private OffsetDateTime createdAt;
@UpdateTimestamp
private OffsetDateTime updatedAt;
}
17 changes: 16 additions & 1 deletion src/main/java/uk/gov/hmcts/cp/mappers/SubscriptionMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,36 @@

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.ReportingPolicy;
import uk.gov.hmcts.cp.entities.ClientSubscriptionEntity;
import uk.gov.hmcts.cp.model.EntityEventType;
import uk.gov.hmcts.cp.openapi.model.ClientSubscription;
import uk.gov.hmcts.cp.openapi.model.ClientSubscriptionRequest;
import uk.gov.hmcts.cp.openapi.model.EventType;
import uk.gov.hmcts.cp.openapi.model.NotificationEndpoint;

import java.net.URI;
import java.util.List;

import static java.util.stream.Collectors.toList;

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface SubscriptionMapper {

@Mapping(source = "request.eventTypes", target = "eventTypes", qualifiedByName = "sortedEventTypes")
@Mapping(target = "createdAt", expression = "java(java.time.OffsetDateTime.now())")
@Mapping(target = "updatedAt", expression = "java(java.time.OffsetDateTime.now())")
ClientSubscriptionEntity mapRequestToEntity(ClientSubscriptionRequest request);

@Mapping(source = "id", target = "clientSubscriptionId")
ClientSubscription mapEntityToResponse(ClientSubscriptionEntity subscription);
ClientSubscription mapEntityToResponse(ClientSubscriptionEntity entity);

@Named("sortedEventTypes")
static List<EntityEventType> sortedEventTypes(final List<EventType> events) {
final List<String> sorted = events.stream().map(e -> e.name()).sorted().collect(toList());
return sorted.stream().map(e -> EntityEventType.valueOf(e)).toList();
}

static String mapFromNotificationEndpoint(final NotificationEndpoint notificationEndpoint) {
return notificationEndpoint.getWebhookUrl().toString();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package uk.gov.hmcts.cp.model;

public enum EventType {
public enum EntityEventType {
PCR,
CUSTODIAL_RESULT
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import uk.gov.hmcts.cp.openapi.model.ClientSubscriptionRequest;
import uk.gov.hmcts.cp.repositories.SubscriptionRepository;

import java.util.UUID;

@Service
@RequiredArgsConstructor
@Slf4j
Expand All @@ -21,4 +23,9 @@ public ClientSubscription saveSubscription(final ClientSubscriptionRequest reque
final ClientSubscriptionEntity entity = mapper.mapRequestToEntity(request);
return mapper.mapEntityToResponse(subscriptionRepository.save(entity));
}

public ClientSubscription getSubscription(final UUID clientSubscriptionId) {
final ClientSubscriptionEntity entity = subscriptionRepository.getReferenceById(clientSubscriptionId);
return mapper.mapEntityToResponse(entity);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
create table client_subscription (
id uuid primary key not null,
event_types varchar(2048) not null,
notification_endpoint text not null,
event_types varchar(128) not null,
notification_endpoint varchar(2048) not null,
created_at timestamp not null,
updated_at timestamp
updated_at timestamp not null
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package uk.gov.hmcts.cp.controllers;

import jakarta.persistence.EntityNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

private static final String NOT_FOUND_MESSAGE = "No row with the given identifier exists";

@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<String> handleNotFoundException(final EntityNotFoundException exception) {
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body(NOT_FOUND_MESSAGE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.ResponseEntity;
import uk.gov.hmcts.cp.openapi.model.ClientSubscription;
import uk.gov.hmcts.cp.openapi.model.ClientSubscriptionRequest;
import uk.gov.hmcts.cp.services.SubscriptionService;

import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand All @@ -28,10 +30,19 @@ class SubscriptionControllerTest {

@Test
void create_controller_should_call_service() {
UUID id = UUID.randomUUID();
ClientSubscription response = ClientSubscription.builder().clientSubscriptionId(id).build();
UUID subscriptionId = UUID.randomUUID();
ClientSubscription response = ClientSubscription.builder().clientSubscriptionId(subscriptionId).build();
when(subscriptionService.saveSubscription(any())).thenReturn(response);
subscriptionController.createClientSubscription(request);
verify(subscriptionService).saveSubscription(request);
}

@Test
void get_controller_should_call_service() {
UUID subscriptionId = UUID.randomUUID();
ClientSubscription response = ClientSubscription.builder().clientSubscriptionId(subscriptionId).build();
when(subscriptionService.getSubscription(subscriptionId)).thenReturn(response);
ResponseEntity<ClientSubscription> result = subscriptionController.getClientSubscription(subscriptionId);
assertThat(result.getBody()).isEqualTo(response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import uk.gov.hmcts.cp.config.TestContainersInitialise;
import uk.gov.hmcts.cp.entities.ClientSubscriptionEntity;
import uk.gov.hmcts.cp.model.EntityEventType;
import uk.gov.hmcts.cp.repositories.SubscriptionRepository;

import java.time.OffsetDateTime;
import java.util.List;

@SpringBootTest
@ContextConfiguration(initializers = TestContainersInitialise.class)
Expand All @@ -16,4 +23,18 @@ public abstract class IntegrationTestBase {

@Resource
protected MockMvc mockMvc;

@Autowired
SubscriptionRepository subscriptionRepository;

protected ClientSubscriptionEntity insertSubscription(String notificationUri, List<EntityEventType> entityEventTypes) {
ClientSubscriptionEntity subscription = ClientSubscriptionEntity.builder()
.eventTypes(entityEventTypes)
.notificationEndpoint(notificationUri)
.createdAt(OffsetDateTime.now())
.build();
ClientSubscriptionEntity saved = subscriptionRepository.save(subscription);
log.info("Inserted subscription:{}", saved.getId());
return saved;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package uk.gov.hmcts.cp.integration;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import tools.jackson.databind.ObjectMapper;
import uk.gov.hmcts.cp.openapi.model.ClientSubscriptionRequest;
import uk.gov.hmcts.cp.openapi.model.NotificationEndpoint;
import uk.gov.hmcts.cp.repositories.SubscriptionRepository;

import java.net.URI;
import java.util.List;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static uk.gov.hmcts.cp.openapi.model.EventType.CUSTODIAL_RESULT;
import static uk.gov.hmcts.cp.openapi.model.EventType.PCR;

class SubscriptionControllerValidationTest extends IntegrationTestBase {

@Autowired
SubscriptionRepository subscriptionRepository;

NotificationEndpoint notificationEndpoint = NotificationEndpoint.builder()
.webhookUrl(URI.create("https://my-callback-url"))
.build();
ClientSubscriptionRequest request = ClientSubscriptionRequest.builder()
.notificationEndpoint(notificationEndpoint)
.eventTypes(List.of(PCR, CUSTODIAL_RESULT))
.build();

@Test
void bad_event_type_should_return_400() throws Exception {
String body = new ObjectMapper().writeValueAsString(request)
.replace("PCR", "BAD");
mockMvc.perform(post("/client-subscriptions")
.contentType(MediaType.APPLICATION_JSON)
.content(body))
.andExpect(status().isBadRequest())
.andExpect(content().string(""));
}

// TODO - decide how to best validate the incoming url and enable this test once done
@Test
@Disabled
void bad_url_should_return_400() throws Exception {
String body = new ObjectMapper().writeValueAsString(request)
.replace("https://my-callback-url", "not-a-url");
mockMvc.perform(post("/client-subscriptions")
.contentType(MediaType.APPLICATION_JSON)
.content(body))
.andExpect(status().isBadRequest())
.andExpect(content().string(""));
}
}
Loading
Loading