diff --git a/src/functionalTest/java/uk/gov/hmcts/opal/steps/draftaccount/DraftAccountPostSteps.java b/src/functionalTest/java/uk/gov/hmcts/opal/steps/draftaccount/DraftAccountPostSteps.java index 85bc0612..1a196fb6 100644 --- a/src/functionalTest/java/uk/gov/hmcts/opal/steps/draftaccount/DraftAccountPostSteps.java +++ b/src/functionalTest/java/uk/gov/hmcts/opal/steps/draftaccount/DraftAccountPostSteps.java @@ -102,7 +102,7 @@ public void postDraftAccountWithInvalidToken() throws JSONException { JSONObject postBody = new JSONObject(); postBody.put("business_unit_id", "77"); - postBody.put("account", "{\"accountCreateRequest\":{\"Defendant\":{},\"Account\":{}}}"); + postBody.put("account", "{\"account_create_request\":{\"defendant\":{},\"account\":{}}}"); postBody.put("account_type", "Fine"); postBody.put("account_status", ""); postBody.put("submitted_by", "BUUID"); diff --git a/src/functionalTest/resources/features/opalMode/manualAccountCreation/draftAccounts/accountJson/account.json b/src/functionalTest/resources/features/opalMode/manualAccountCreation/draftAccounts/accountJson/account.json index 4ac932df..932d9c90 100644 --- a/src/functionalTest/resources/features/opalMode/manualAccountCreation/draftAccounts/accountJson/account.json +++ b/src/functionalTest/resources/features/opalMode/manualAccountCreation/draftAccounts/accountJson/account.json @@ -1,6 +1,6 @@ { - "accountCreateRequest": { - "Defendant": {}, - "Account": {} + "account_create_request": { + "defendant": {}, + "account": {} } } diff --git a/src/functionalTest/resources/features/opalMode/manualAccountCreation/draftAccounts/accountJson/adultAccount.json b/src/functionalTest/resources/features/opalMode/manualAccountCreation/draftAccounts/accountJson/adultAccount.json index 825c937f..8c457c43 100644 --- a/src/functionalTest/resources/features/opalMode/manualAccountCreation/draftAccounts/accountJson/adultAccount.json +++ b/src/functionalTest/resources/features/opalMode/manualAccountCreation/draftAccounts/accountJson/adultAccount.json @@ -1,12 +1,12 @@ { - "accountCreateRequest": { - "Defendant": { - "Surname": "LNAME", - "Forenames": "FNAME", - "DOB": "01/01/2000" + "account_create_request": { + "defendant": { + "surname": "LNAME", + "forenames": "FNAME", + "dob": "01/01/2000" }, - "Account": { - "AccountType": "Fine" + "account": { + "account_type": "Fine" } } } diff --git a/src/integrationTest/java/uk/gov/hmcts/opal/controllers/DraftAccountControllerIntegrationTest.java b/src/integrationTest/java/uk/gov/hmcts/opal/controllers/DraftAccountControllerIntegrationTest.java index ec6d84f7..4f159c84 100644 --- a/src/integrationTest/java/uk/gov/hmcts/opal/controllers/DraftAccountControllerIntegrationTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/opal/controllers/DraftAccountControllerIntegrationTest.java @@ -22,7 +22,7 @@ import uk.gov.hmcts.opal.authorisation.model.Permissions; import uk.gov.hmcts.opal.authorisation.model.UserState; import uk.gov.hmcts.opal.controllers.advice.GlobalExceptionHandler; -import uk.gov.hmcts.opal.controllers.util.UserStateUtil; +import uk.gov.hmcts.opal.dto.AddDraftAccountRequestDto; import uk.gov.hmcts.opal.dto.ReplaceDraftAccountRequestDto; import uk.gov.hmcts.opal.dto.ToJsonString; import uk.gov.hmcts.opal.dto.UpdateDraftAccountRequestDto; @@ -37,7 +37,6 @@ import java.net.ConnectException; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.HashSet; import java.util.logging.Logger; import static java.util.Collections.singletonList; @@ -56,13 +55,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static uk.gov.hmcts.opal.controllers.util.UserStateUtil.allPermissionsUser; +import static uk.gov.hmcts.opal.controllers.util.UserStateUtil.noPermissionsUser; +import static uk.gov.hmcts.opal.controllers.util.UserStateUtil.permissionUser; @WebMvcTest @ContextConfiguration(classes = {DraftAccountController.class, GlobalExceptionHandler.class}) @ActiveProfiles({"integration"}) class DraftAccountControllerIntegrationTest { - private static final Logger logger = Logger.getLogger(DraftAccountControllerIntegrationTest.class.getSimpleName()); private static final String URL_BASE = "/draft-accounts"; private static final String GET_DRAFT_ACCOUNT_RESPONSE = "getDraftAccountResponse.json"; @@ -124,7 +125,7 @@ void testGetDraftAccountById_WhenDraftAccountDoesNotExist() throws Exception { void testGetDraftAccountsSummaries_noParams() throws Exception { DraftAccountEntity draftAccountEntity = createDraftAccountEntity(); - when(userStateService.checkForAuthorisedUser(any())).thenReturn(new UserState.DeveloperUserState()); + when(userStateService.checkForAuthorisedUser(any())).thenReturn(allPermissionsUser()); when(draftAccountService.getDraftAccounts(any(),any(), any())) .thenReturn(singletonList(draftAccountEntity)); @@ -143,7 +144,7 @@ void testGetDraftAccountsSummaries_permission() throws Exception { DraftAccountEntity draftAccountEntity = createDraftAccountEntity(); final Short businessId = (short)1; - UserState user = UserStateUtil.permissionUser(businessId, Permissions.CREATE_MANAGE_DRAFT_ACCOUNTS); + UserState user = permissionUser(businessId, Permissions.CREATE_MANAGE_DRAFT_ACCOUNTS); when(userStateService.checkForAuthorisedUser(any())).thenReturn(user); when(draftAccountService.getDraftAccounts(any(), any(), any())) @@ -164,7 +165,7 @@ void testGetDraftAccountsSummaries_noPermission() throws Exception { DraftAccountEntity draftAccountEntity = createDraftAccountEntity(); final Short businessId = (short)1; - UserState user = UserStateUtil.permissionUser(businessId, Permissions.COLLECTION_ORDER); + UserState user = permissionUser(businessId, Permissions.COLLECTION_ORDER); when(userStateService.checkForAuthorisedUser(any())).thenReturn(user); when(draftAccountService.getDraftAccounts(any(), any(), any())) @@ -191,7 +192,7 @@ private String checkStandardSummaryExpectations(ResultActions actions) throws Ex } @Test - void testPostDraftAccountsSearch() throws Exception { + void testSearchDraftAccountsPost() throws Exception { DraftAccountEntity draftAccountEntity = createDraftAccountEntity(); when(draftAccountService.searchDraftAccounts(any(DraftAccountSearchDto.class))) @@ -211,7 +212,7 @@ void testPostDraftAccountsSearch() throws Exception { } @Test - void testPostDraftAccountsSearch_WhenDraftAccountDoesNotExist() throws Exception { + void testSearchDraftAccountsPost_WhenDraftAccountDoesNotExist() throws Exception { mockMvc.perform(post(URL_BASE + "/search") .header("authorization", "Bearer some_value") .contentType(MediaType.APPLICATION_JSON) @@ -301,32 +302,6 @@ void testDeleteDraftAccountById() throws Exception { @Test void testReplaceDraftAccount() throws Exception { Long draftAccountId = 241L; - String requestBody = """ - { - "account": { - "accountCreateRequest": { - "Defendant": { - "CompanyName": "Company ABC", - "Surname": "LNAME", - "Fornames": "FNAME", - "DOB": "2000-01-01" - }, - "Account": { - "AccountType": "Fine" - } - } - }, - "account_status": "", - "account_summary_data": "", - "account_type": "Fines", - "business_unit_id": 5, - "submitted_by": "BUUID1", - "timeline_data": { - "stuff": "yes" - }, - "court": "test" - } - """; LocalDateTime testDateTime = LocalDateTime.of(2024, 9, 26, 15, 0, 0); @@ -336,9 +311,9 @@ void testReplaceDraftAccount() throws Exception { .businessUnitName("Cambridgeshire").build()) .createdDate(testDateTime) .submittedBy("BUUID1") - .account("{\"accountCreateRequest\":{\"Defendant\":{\"CompanyName\":\"Company ABC\",\"Surname\"" - + ":\"LNAME\",\"Fornames\":\"FNAME\",\"DOB\":\"2000-01-01\"},\"Account\"" - + ":{\"AccountType\":\"Fine\"}}}") + .account("{\"account_create_request\":{\"defendant\":{\"company_name\":\"Company ABC\",\"surname\"" + + ":\"LNAME\",\"fornames\":\"FNAME\",\"dob\":\"2000-01-01\"},\"account\"" + + ":{\"account_type\":\"Fine\"}}}") .accountSnapshot("{\"defendant_name\":\"Company ABC\",\"created_date\":\"2024-09-26T15:00:00Z\"," + "\"account_type\":\"Fine\",\"submitted_by\":\"BUUID1\"," + "\"business_unit_name\":\"Cambridgeshire\"}") @@ -347,7 +322,7 @@ void testReplaceDraftAccount() throws Exception { .timelineData("{\"stuff\":\"yes\"}") .build(); - when(userStateService.checkForAuthorisedUser(any())).thenReturn(new UserState.DeveloperUserState()); + when(userStateService.checkForAuthorisedUser(any())).thenReturn(allPermissionsUser()); when(draftAccountService.replaceDraftAccount(eq(draftAccountId), any(ReplaceDraftAccountRequestDto.class))) .thenReturn(updatedEntity); @@ -355,14 +330,14 @@ void testReplaceDraftAccount() throws Exception { MvcResult result = mockMvc.perform(put(URL_BASE + "/" + draftAccountId) .header("authorization", "Bearer some_value") .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) + .content(validCreateRequestBody())) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.draft_account_id").value(draftAccountId)) .andExpect(jsonPath("$.business_unit_id").value(5)) .andExpect(jsonPath("$.created_at").value("2024-09-26T15:00:00Z")) .andExpect(jsonPath("$.submitted_by").value("BUUID1")) - .andExpect(jsonPath("$.account.accountCreateRequest.Defendant.CompanyName") + .andExpect(jsonPath("$.account.account_create_request.defendant.company_name") .value("Company ABC")) .andExpect(jsonPath("$.account_snapshot.defendant_name").value("Company ABC")) .andExpect(jsonPath("$.account_type").value("Fines")) @@ -381,43 +356,13 @@ void testReplaceDraftAccount() throws Exception { @Test void testReplaceDraftAccount_no_permission() throws Exception { Long draftAccountId = 241L; - String requestBody = """ - { - "account": { - "accountCreateRequest": { - "Defendant": { - "CompanyName": "Company ABC", - "Surname": "LNAME", - "Fornames": "FNAME", - "DOB": "2000-01-01" - }, - "Account": { - "AccountType": "Fine" - } - } - }, - "account_status": "", - "account_summary_data": "", - "account_type": "Fines", - "business_unit_id": 5, - "submitted_by": "BUUID1", - "timeline_data": { - "stuff": "yes" - }, - "court": "test" - } - """; - - when(userStateService.checkForAuthorisedUser(any())).thenReturn(new UserState(1L, - "test", - new HashSet<>() - )); + when(userStateService.checkForAuthorisedUser(any())).thenReturn(noPermissionsUser()); mockMvc.perform(put(URL_BASE + "/" + draftAccountId) .header("authorization", "Bearer some_value") .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) + .content(validCreateRequestBody())) .andExpect(status().isForbidden()) .andReturn(); @@ -435,10 +380,7 @@ void testUpdateDraftAccount_no_permission() throws Exception { } """; - when(userStateService.checkForAuthorisedUser(any())).thenReturn(new UserState(1L, - "test", - new HashSet<>() - )); + when(userStateService.checkForAuthorisedUser(any())).thenReturn(noPermissionsUser()); mockMvc.perform(patch(URL_BASE + "/" + draftAccountId) .header("authorization", "Bearer some_value") @@ -452,14 +394,6 @@ void testUpdateDraftAccount_no_permission() throws Exception { @Test void testUpdateDraftAccount() throws Exception { Long draftAccountId = 241L; - String requestBody = """ - { - "account_status": "PENDING", - "validated_by": "BUUID1", - "business_unit_id": 5, - "timeline_data": {"test":"yes"} - } - """; LocalDateTime testDateTime = LocalDateTime.of(2024, 10, 3, 14, 30, 0); @@ -471,8 +405,9 @@ void testUpdateDraftAccount() throws Exception { .submittedBy("BUUID1") .validatedDate(testDateTime) .validatedBy("BUUID1") - .account("{\"accountCreateRequest\":{\"Defendant\":{\"CompanyName\":\"Company ABC\",\"Surname\":\"LNAME\"," - + "\"Fornames\":\"FNAME\",\"DOB\":\"2000-01-01\"},\"Account\":{\"AccountType\":\"Fine\"}}}") + .account("{\"account_create_request\":{\"defendant\":{\"company_name\":\"Company ABC\"," + + "\"surname\":\"LNAME\",\"fornames\":\"FNAME\",\"dob\":\"2000-01-01\"}," + + "\"account\":{\"account_type\":\"Fine\"}}}") .accountSnapshot("{\"defendant_name\":\"Company ABC\",\"created_date\":\"2024-10-02T14:30:00Z\"," + "\"account_type\":\"Fine\",\"submitted_by\":\"BUUID1\"," + "\"business_unit_name\":\"Cambridgeshire\"," @@ -485,12 +420,12 @@ void testUpdateDraftAccount() throws Exception { when(draftAccountService.updateDraftAccount(eq(draftAccountId), any(UpdateDraftAccountRequestDto.class))) .thenReturn(updatedEntity); - when(userStateService.checkForAuthorisedUser(any())).thenReturn(new UserState.DeveloperUserState()); + when(userStateService.checkForAuthorisedUser(any())).thenReturn(allPermissionsUser()); MvcResult result = mockMvc.perform(patch(URL_BASE + "/" + draftAccountId) .header("authorization", "Bearer some_value") .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) + .content(validUpdateRequestBody())) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.draft_account_id").value(draftAccountId)) @@ -499,7 +434,7 @@ void testUpdateDraftAccount() throws Exception { .andExpect(jsonPath("$.submitted_by").value("BUUID1")) .andExpect(jsonPath("$.validated_at").value("2024-10-03T14:30:00Z")) .andExpect(jsonPath("$.validated_by").value("BUUID1")) - .andExpect(jsonPath("$.account.accountCreateRequest.Defendant.CompanyName") + .andExpect(jsonPath("$.account.account_create_request.defendant.company_name") .value("Company ABC")) .andExpect(jsonPath("$.account_snapshot.defendant_name").value("Company ABC")) .andExpect(jsonPath("$.account_snapshot.approved_date") @@ -519,34 +454,17 @@ void testUpdateDraftAccount() throws Exception { @Test void testPostDraftAccount_JsonSchemaValidationException() throws Exception { - String invalidRequestBody = """ - { - "invalid_field": "This field shouldn't be here", - "account": { - "accountCreateRequest": { - "Defendant": { - "CompanyName": "Company ABC", - "Surname": "LNAME", - "Fornames": "FNAME", - "DOB": "2000-01-01" - }, - "Account": { - "AccountType": "Invalid" - } - } - }, - "business_unit_id": 1 - } - """; String expectedErrorMessageStart = "JSON Schema Validation Error: Validating against JSON schema 'addDraftAccountRequest.json'," + " found 3 validation errors:"; + when(userStateService.checkForAuthorisedUser(any())).thenReturn(allPermissionsUser()); + mockMvc.perform(post(URL_BASE) .header("authorization", "Bearer some_value") .contentType(MediaType.APPLICATION_JSON) - .content(invalidRequestBody)) + .content(invalidCreateRequestBody())) .andExpect(status().isBadRequest()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.error").value("Bad Request")) @@ -556,4 +474,160 @@ void testPostDraftAccount_JsonSchemaValidationException() throws Exception { .andExpect(jsonPath("$.message").value(containsString("required property 'timeline_data' not found"))); } + + @Test + void testPostDraftAccount_permission() throws Exception { + + String validRequestBody = validCreateRequestBody(); + AddDraftAccountRequestDto dto = ToJsonString.toClassInstance(validRequestBody, AddDraftAccountRequestDto.class); + LocalDateTime created = LocalDateTime.now(); + DraftAccountEntity entity = toEntity(dto, created); + + when(userStateService.checkForAuthorisedUser(any())).thenReturn(allPermissionsUser()); + when(draftAccountService.submitDraftAccount(any())).thenReturn(entity); + + MvcResult result = mockMvc.perform(post(URL_BASE) + .header("authorization", "Bearer some_value") + .contentType(MediaType.APPLICATION_JSON) + .content(validCreateRequestBody())) + .andExpect(status().isCreated()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$.submitted_by").value("BUUID1")) + .andExpect(jsonPath("$.account_type").value("Fines")) + .andExpect(jsonPath("$.account_status").value("Submitted")) + .andExpect(jsonPath("$.account.accountCreateRequest.Account.AccountType") + .value("Fine")) + .andExpect(jsonPath("$.account.accountCreateRequest.Defendant.Surname") + .value("LNAME")) + .andReturn(); + + String body = result.getResponse().getContentAsString(); + + logger.info(":testPostDraftAccount_permission: Response body:\n" + ToJsonString.toPrettyJson(body)); + } + + @Test + void testPostDraftAccount_noPermission() throws Exception { + + String validRequestBody = validCreateRequestBody(); + AddDraftAccountRequestDto dto = ToJsonString.toClassInstance(validRequestBody, AddDraftAccountRequestDto.class); + LocalDateTime created = LocalDateTime.now(); + DraftAccountEntity entity = toEntity(dto, created); + + when(userStateService.checkForAuthorisedUser(any())).thenReturn(noPermissionsUser()); + when(draftAccountService.submitDraftAccount(any())).thenReturn(entity); + + MvcResult result = mockMvc.perform(post(URL_BASE) + .header("authorization", "Bearer some_value") + .contentType(MediaType.APPLICATION_JSON) + .content(validCreateRequestBody())) + .andExpect(status().isForbidden()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$.error").value("Forbidden")) + .andExpect(jsonPath("$.message").value( + "For user null, [CREATE_MANAGE_DRAFT_ACCOUNTS] permission(s) are not allowed for the user.")) + .andReturn(); + + String body = result.getResponse().getContentAsString(); + + logger.info(":testPostDraftAccount_permission: Response body:\n" + ToJsonString.toPrettyJson(body)); + } + + @Test + void testPostDraftAccount_wrongPermission() throws Exception { + + String validRequestBody = validCreateRequestBody(); + AddDraftAccountRequestDto dto = ToJsonString.toClassInstance(validRequestBody, AddDraftAccountRequestDto.class); + LocalDateTime created = LocalDateTime.now(); + DraftAccountEntity entity = toEntity(dto, created); + + when(userStateService.checkForAuthorisedUser(any())).thenReturn( + permissionUser((short)5, Permissions.CHECK_VALIDATE_DRAFT_ACCOUNTS, Permissions.ACCOUNT_ENQUIRY)); + when(draftAccountService.submitDraftAccount(any())).thenReturn(entity); + + MvcResult result = mockMvc.perform(post(URL_BASE) + .header("authorization", "Bearer some_value") + .contentType(MediaType.APPLICATION_JSON) + .content(validCreateRequestBody())) + .andExpect(status().isForbidden()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$.error").value("Forbidden")) + .andExpect(jsonPath("$.message").value( + "For user null, [CREATE_MANAGE_DRAFT_ACCOUNTS] permission(s) are not allowed for the user.")) + .andReturn(); + + String body = result.getResponse().getContentAsString(); + + logger.info(":testPostDraftAccount_permission: Response body:\n" + ToJsonString.toPrettyJson(body)); + } + + private String validCreateRequestBody() { + return """ +{ + "account": { + "accountCreateRequest": { + "Defendant": { + "CompanyName": "Company ABC", + "Surname": "LNAME", + "Fornames": "FNAME", + "DOB": "2000-01-01" + }, + "Account": { + "AccountType": "Fine" + } + } + }, + "account_type": "Fines", + "business_unit_id": 5, + "submitted_by": "BUUID1", + "timeline_data": { + "stuff": "yes" + } +}"""; + } + + private String invalidCreateRequestBody() { + return """ +{ + "invalid_field": "This field shouldn't be here", + "account": { + "account_create_request": { + "defendant": { + "company_name": "Company ABC", + "surname": "LNAME", + "fornames": "FNAME", + "dob": "2000-01-01" + }, + "account": { + "account_type": "Invalid" + } + } + }, + "business_unit_id": 1 +}"""; + } + + private String validUpdateRequestBody() { + return """ +{ + "account_status": "PENDING", + "validated_by": "BUUID1", + "business_unit_id": 5, + "timeline_data": {"test":"yes"} +}"""; + } + + private DraftAccountEntity toEntity(AddDraftAccountRequestDto dto, LocalDateTime created) { + return DraftAccountEntity.builder() + .businessUnit(BusinessUnitEntity.builder().build()) + .createdDate(created) + .submittedBy(dto.getSubmittedBy()) + .account(dto.getAccount()) + .accountSnapshot("{ \"data\": \"something snappy\"}") + .accountType(dto.getAccountType()) + .accountStatus(DraftAccountStatus.SUBMITTED) + .timelineData(dto.getTimelineData()) + .build(); + } + } diff --git a/src/integrationTest/java/uk/gov/hmcts/opal/controllers/util/UserStateUtil.java b/src/integrationTest/java/uk/gov/hmcts/opal/controllers/util/UserStateUtil.java index 38e2da42..6ceb3fb5 100644 --- a/src/integrationTest/java/uk/gov/hmcts/opal/controllers/util/UserStateUtil.java +++ b/src/integrationTest/java/uk/gov/hmcts/opal/controllers/util/UserStateUtil.java @@ -6,6 +6,7 @@ import uk.gov.hmcts.opal.authorisation.model.UserState; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; @@ -16,9 +17,14 @@ public static final UserState noPermissionsUser() { return UserState.builder() .userId(999L) .userName("no-permissions@users.com") + .businessUnitUser(Collections.emptySet()) .build(); } + public static final UserState allPermissionsUser() { + return new UserState.DeveloperUserState(); + } + public static final UserState permissionUser(Short buid, Permissions... permissions) { return UserState.builder() .userId(1L) diff --git a/src/main/java/uk/gov/hmcts/opal/authorisation/aspect/PermissionNotAllowedException.java b/src/main/java/uk/gov/hmcts/opal/authorisation/aspect/PermissionNotAllowedException.java index 05ab7369..fde1567e 100644 --- a/src/main/java/uk/gov/hmcts/opal/authorisation/aspect/PermissionNotAllowedException.java +++ b/src/main/java/uk/gov/hmcts/opal/authorisation/aspect/PermissionNotAllowedException.java @@ -14,7 +14,7 @@ public class PermissionNotAllowedException extends RuntimeException { private final BusinessUnitUser businessUnitUser; public PermissionNotAllowedException(Permissions... value) { - super(Arrays.toString(value) + " permission(s) are not allowed for the user"); + super(Arrays.toString(value) + " permission(s) are not allowed for the user."); this.permission = value; this.businessUnitUser = null; } @@ -27,7 +27,7 @@ public PermissionNotAllowedException(Collection buIds, Permissions... val public PermissionNotAllowedException(Permissions permission, BusinessUnitUser businessUnitUser) { - super(permission + " permission is not allowed for the business unit user " + super(permission + " permission is not allowed for the business unit user: " + businessUnitUser.getBusinessUnitUserId()); this.permission = new Permissions[] {permission}; this.businessUnitUser = businessUnitUser; diff --git a/src/main/java/uk/gov/hmcts/opal/controllers/DraftAccountController.java b/src/main/java/uk/gov/hmcts/opal/controllers/DraftAccountController.java index 2e197426..913c6129 100644 --- a/src/main/java/uk/gov/hmcts/opal/controllers/DraftAccountController.java +++ b/src/main/java/uk/gov/hmcts/opal/controllers/DraftAccountController.java @@ -142,18 +142,19 @@ public ResponseEntity> postDraftAccountsSearch( @CheckAcceptHeader public ResponseEntity postDraftAccount(@RequestBody AddDraftAccountRequestDto dto, @RequestHeader(value = "Authorization", required = false) String authHeaderValue) { - log.info(":POST:postDraftAccount: creating a new draft account entity."); + log.info(":POST:postDraftAccount: creating a new draft account entity: \n{}", dto.toPrettyJson()); - userStateService.checkForAuthorisedUser(authHeaderValue); - - - - - jsonSchemaValidationService.validateOrError(dto.toJson(), ADD_DRAFT_ACCOUNT_REQUEST_JSON); + UserState userState = userStateService.checkForAuthorisedUser(authHeaderValue); - DraftAccountEntity response = draftAccountService.submitDraftAccount(dto); + if (userState.hasBusinessUnitUserWithPermission(dto.getBusinessUnitId(), + Permissions.CREATE_MANAGE_DRAFT_ACCOUNTS)) { + jsonSchemaValidationService.validateOrError(dto.toJson(), ADD_DRAFT_ACCOUNT_REQUEST_JSON); - return buildCreatedResponse(toGetResponseDto(response)); + DraftAccountEntity response = draftAccountService.submitDraftAccount(dto); + return buildCreatedResponse(toGetResponseDto(response)); + } else { + throw new PermissionNotAllowedException(Permissions.CREATE_MANAGE_DRAFT_ACCOUNTS); + } } @Hidden diff --git a/src/main/java/uk/gov/hmcts/opal/controllers/advice/GlobalExceptionHandler.java b/src/main/java/uk/gov/hmcts/opal/controllers/advice/GlobalExceptionHandler.java index dbd37a96..04c57dd8 100644 --- a/src/main/java/uk/gov/hmcts/opal/controllers/advice/GlobalExceptionHandler.java +++ b/src/main/java/uk/gov/hmcts/opal/controllers/advice/GlobalExceptionHandler.java @@ -71,9 +71,9 @@ public ResponseEntity handlePermissionNotAllowedException(Exception ex, HttpServletRequest request) { String authorization = request.getHeader(AUTH_HEADER); String preferredName = extractPreferredUsername(authorization, tokenService); - String message = String.format("{\"error\": \"Forbidden\", \"message\" : \"For user %s, %s \"}", preferredName, + String message = String.format("{\"error\": \"Forbidden\", \"message\" : \"For user %s, %s\"}", preferredName, ex.getMessage()); - log.error(message); + log.error(":handlePermissionNotAllowedException: {}", message); return ResponseEntity.status(HttpStatus.FORBIDDEN).contentType(MediaType.APPLICATION_JSON).body(message); } diff --git a/src/main/java/uk/gov/hmcts/opal/dto/AddDraftAccountRequestDto.java b/src/main/java/uk/gov/hmcts/opal/dto/AddDraftAccountRequestDto.java index fd9a023b..1773e460 100644 --- a/src/main/java/uk/gov/hmcts/opal/dto/AddDraftAccountRequestDto.java +++ b/src/main/java/uk/gov/hmcts/opal/dto/AddDraftAccountRequestDto.java @@ -8,6 +8,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.NonNull; import uk.gov.hmcts.opal.util.KeepAsJsonDeserializer; import java.time.OffsetDateTime; @@ -29,6 +30,7 @@ public class AddDraftAccountRequestDto implements ToJsonString, DraftAccountRequ private OffsetDateTime validatedDate; @JsonProperty(value = "business_unit_id", required = true) + @NonNull private Short businessUnitId; @JsonProperty("validated_by") diff --git a/src/main/java/uk/gov/hmcts/opal/dto/DraftAccountRequestDto.java b/src/main/java/uk/gov/hmcts/opal/dto/DraftAccountRequestDto.java index 8ddb881b..82fc46d1 100644 --- a/src/main/java/uk/gov/hmcts/opal/dto/DraftAccountRequestDto.java +++ b/src/main/java/uk/gov/hmcts/opal/dto/DraftAccountRequestDto.java @@ -4,8 +4,6 @@ public interface DraftAccountRequestDto { String getAccount(); - Short getBusinessUnitId(); - String getSubmittedBy(); String getAccountType(); diff --git a/src/main/java/uk/gov/hmcts/opal/dto/ReplaceDraftAccountRequestDto.java b/src/main/java/uk/gov/hmcts/opal/dto/ReplaceDraftAccountRequestDto.java index 4f3c1399..8838ed71 100644 --- a/src/main/java/uk/gov/hmcts/opal/dto/ReplaceDraftAccountRequestDto.java +++ b/src/main/java/uk/gov/hmcts/opal/dto/ReplaceDraftAccountRequestDto.java @@ -8,6 +8,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.NonNull; import uk.gov.hmcts.opal.util.KeepAsJsonDeserializer; @Data @@ -18,6 +19,7 @@ public class ReplaceDraftAccountRequestDto implements ToJsonString, DraftAccountRequestDto { @JsonProperty(value = "business_unit_id", required = true) + @NonNull private Short businessUnitId; @JsonProperty(value = "submitted_by", required = true) diff --git a/src/main/java/uk/gov/hmcts/opal/dto/ToJsonString.java b/src/main/java/uk/gov/hmcts/opal/dto/ToJsonString.java index 5b5e71a1..174d29f8 100644 --- a/src/main/java/uk/gov/hmcts/opal/dto/ToJsonString.java +++ b/src/main/java/uk/gov/hmcts/opal/dto/ToJsonString.java @@ -60,4 +60,12 @@ static JsonNode toJsonNode(String json) throws JsonProcessingException { static ObjectMapper getObjectMapper() { return OBJECT_MAPPER; } + + static T toClassInstance(String json, Class clss) { + try { + return OBJECT_MAPPER.readValue(json, clss); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } } diff --git a/src/main/java/uk/gov/hmcts/opal/service/opal/DraftAccountService.java b/src/main/java/uk/gov/hmcts/opal/service/opal/DraftAccountService.java index d2082e6b..b893e385 100644 --- a/src/main/java/uk/gov/hmcts/opal/service/opal/DraftAccountService.java +++ b/src/main/java/uk/gov/hmcts/opal/service/opal/DraftAccountService.java @@ -41,9 +41,9 @@ @Qualifier("draftAccountService") public class DraftAccountService { - private static final String A_C_R_JSON_PATH = "$.accountCreateRequest"; - private static final String DEFENDANT_JSON_PATH = A_C_R_JSON_PATH + ".Defendant"; - private static final String ACCOUNT_JSON_PATH = A_C_R_JSON_PATH + ".Account"; + private static final String A_C_R_JSON_PATH = "$.account_create_request"; + private static final String DEFENDANT_JSON_PATH = A_C_R_JSON_PATH + ".defendant"; + private static final String ACCOUNT_JSON_PATH = A_C_R_JSON_PATH + ".account"; private static final EnumSet VALID_UPDATE_STATUSES = EnumSet.of(DraftAccountStatus.PENDING, DraftAccountStatus.REJECTED, DraftAccountStatus.DELETED); @@ -90,8 +90,6 @@ public List searchDraftAccounts(DraftAccountSearchDto criter return page.getContent(); } - - public DraftAccountEntity submitDraftAccount(AddDraftAccountRequestDto dto) { LocalDateTime created = LocalDateTime.now(); BusinessUnitEntity businessUnit = businessUnitRepository.findById(dto.getBusinessUnitId()).orElse(null); @@ -197,19 +195,19 @@ private DraftAccountSnapshots.Snapshot buildInitialSnapshot(String document, L JsonPathUtil.DocContext docContext = createDocContext(document); - String companyName = docContext.read(DEFENDANT_JSON_PATH + ".CompanyName"); + String companyName = docContext.read(DEFENDANT_JSON_PATH + ".company_name"); final boolean notCompany = companyName == null || companyName.isBlank(); String defendantName = notCompany - ? docContext.read(DEFENDANT_JSON_PATH + ".Surname") + ", " - + docContext.read(DEFENDANT_JSON_PATH + ".Forenames") + ? docContext.read(DEFENDANT_JSON_PATH + ".surname") + ", " + + docContext.read(DEFENDANT_JSON_PATH + ".forenames") : companyName; String dob = notCompany - ? docContext.read(DEFENDANT_JSON_PATH + ".DOB") + ? docContext.read(DEFENDANT_JSON_PATH + ".dob") : null; - String accType = docContext.read(ACCOUNT_JSON_PATH + ".AccountType"); + String accType = docContext.read(ACCOUNT_JSON_PATH + ".account_type"); return DraftAccountSnapshots.Snapshot.builder() .defendantName(defendantName) diff --git a/src/main/resources/jsonSchemas/replaceDraftAccountRequest.json b/src/main/resources/jsonSchemas/replaceDraftAccountRequest.json index b0bee81c..4b7dac49 100644 --- a/src/main/resources/jsonSchemas/replaceDraftAccountRequest.json +++ b/src/main/resources/jsonSchemas/replaceDraftAccountRequest.json @@ -38,7 +38,6 @@ "submitted_by", "account", "account_type", - "account_status", "timeline_data" ] } diff --git a/src/test/java/uk/gov/hmcts/opal/authorisation/aspect/PermissionNotAllowedExceptionTest.java b/src/test/java/uk/gov/hmcts/opal/authorisation/aspect/PermissionNotAllowedExceptionTest.java index 934b2591..c97f95f8 100644 --- a/src/test/java/uk/gov/hmcts/opal/authorisation/aspect/PermissionNotAllowedExceptionTest.java +++ b/src/test/java/uk/gov/hmcts/opal/authorisation/aspect/PermissionNotAllowedExceptionTest.java @@ -21,7 +21,7 @@ void constructor_ShouldSetMessage() { Permissions permission = Permissions.ACCOUNT_ENQUIRY_NOTES; PermissionNotAllowedException exception = new PermissionNotAllowedException(permission); - assertEquals("[" + permission + "]" + " permission(s) are not allowed for the user", + assertEquals("[" + permission + "]" + " permission(s) are not allowed for the user.", exception.getMessage()); } @@ -31,7 +31,7 @@ void constructor2_ShouldSetMessage() { PermissionNotAllowedException exception = new PermissionNotAllowedException( permission, BusinessUnitUser.builder().businessUnitUserId("A001").build()); - assertEquals(permission + " permission is not allowed for the business unit user A001", + assertEquals(permission + " permission is not allowed for the business unit user: A001", exception.getMessage()); } } diff --git a/src/test/java/uk/gov/hmcts/opal/service/opal/DraftAccountServiceTest.java b/src/test/java/uk/gov/hmcts/opal/service/opal/DraftAccountServiceTest.java index be203c02..a730d12f 100644 --- a/src/test/java/uk/gov/hmcts/opal/service/opal/DraftAccountServiceTest.java +++ b/src/test/java/uk/gov/hmcts/opal/service/opal/DraftAccountServiceTest.java @@ -112,6 +112,7 @@ void testSubmitDraftAccounts_success() { // Arrange DraftAccountEntity draftAccountEntity = DraftAccountEntity.builder().build(); AddDraftAccountRequestDto addDraftAccountDto = AddDraftAccountRequestDto.builder() + .businessUnitId((short)1) .account(createAccountString()) .build(); BusinessUnitEntity businessUnit = BusinessUnitEntity.builder() @@ -132,6 +133,7 @@ void testSubmitDraftAccounts_success() { void testSubmitDraftAccounts_fail() { // Arrange AddDraftAccountRequestDto addDraftAccountDto = AddDraftAccountRequestDto.builder() + .businessUnitId((short)1) .account("{}") .build(); BusinessUnitEntity businessUnit = BusinessUnitEntity.builder() @@ -145,7 +147,7 @@ void testSubmitDraftAccounts_fail() { draftAccountService.submitDraftAccount(addDraftAccountDto)); // Assert - assertEquals("Missing property in path $['accountCreateRequest']", re.getMessage()); + assertEquals("Missing property in path $['account_create_request']", re.getMessage()); } @Test @@ -245,7 +247,9 @@ void testReplaceDraftAccount_success() { void testReplaceDraftAccount_draftAccountNotFound() { // Arrange Long draftAccountId = 1L; - ReplaceDraftAccountRequestDto replaceDto = ReplaceDraftAccountRequestDto.builder().build(); + ReplaceDraftAccountRequestDto replaceDto = ReplaceDraftAccountRequestDto.builder() + .businessUnitId((short)1) + .build(); when(draftAccountRepository.findById(draftAccountId)).thenReturn(Optional.empty()); @@ -397,14 +401,14 @@ void testUpdateDraftAccount_invalidStatus() { private String createAccountString() { return """ { - "accountCreateRequest": { - "Defendant": { - "Surname": "Windsor", - "Forenames": "Charles", - "DOB": "August 1958" + "account_create_request": { + "defendant": { + "surname": "Windsor", + "forenames": "Charles", + "dob": "August 1958" }, - "Account": { - "AccountType": "Fine" + "account": { + "account_type": "Fine" } } }