diff --git a/src/integrationTest/java/uk/gov/hmcts/darts/audio/controller/AudioControllerPostAdminApproveMediaMarkedForDeletionIntTest.java b/src/integrationTest/java/uk/gov/hmcts/darts/audio/controller/AudioControllerPostAdminApproveMediaMarkedForDeletionIntTest.java new file mode 100644 index 0000000000..4a505234a1 --- /dev/null +++ b/src/integrationTest/java/uk/gov/hmcts/darts/audio/controller/AudioControllerPostAdminApproveMediaMarkedForDeletionIntTest.java @@ -0,0 +1,283 @@ +package uk.gov.hmcts.darts.audio.controller; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import uk.gov.hmcts.darts.audio.exception.AudioApiError; +import uk.gov.hmcts.darts.audio.model.AdminActionResponse; +import uk.gov.hmcts.darts.audio.model.MediaApproveMarkedForDeletionResponse; +import uk.gov.hmcts.darts.audio.model.Problem; +import uk.gov.hmcts.darts.authorisation.component.UserIdentity; +import uk.gov.hmcts.darts.common.entity.CourtroomEntity; +import uk.gov.hmcts.darts.common.entity.MediaEntity; +import uk.gov.hmcts.darts.common.enums.SecurityRoleEnum; +import uk.gov.hmcts.darts.common.repository.UserAccountRepository; +import uk.gov.hmcts.darts.testutils.IntegrationBase; +import uk.gov.hmcts.darts.testutils.stubs.CourtroomStub; +import uk.gov.hmcts.darts.testutils.stubs.MediaStub; +import uk.gov.hmcts.darts.testutils.stubs.ObjectAdminActionStub; +import uk.gov.hmcts.darts.testutils.stubs.ObjectHiddenReasonStub; +import uk.gov.hmcts.darts.testutils.stubs.SuperAdminUserStub; +import uk.gov.hmcts.darts.testutils.stubs.UserAccountStub; + +import java.time.OffsetDateTime; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static wiremock.org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric; + +@AutoConfigureMockMvc +class AudioControllerPostAdminApproveMediaMarkedForDeletionIntTest extends IntegrationBase { + private static final String MEDIA_ID_SUBSTITUTION_KEY = "{media_id}"; + private static final String ENDPOINT_URL = "/admin/medias/" + MEDIA_ID_SUBSTITUTION_KEY + "/approve-deletion"; + private static final OffsetDateTime START_TIME = OffsetDateTime.parse("2024-01-01T10:00:00Z"); + private static final OffsetDateTime END_TIME = OffsetDateTime.parse("2024-01-01T00:12:00Z"); + + @Autowired + private MockMvc mockMvc; + + @Autowired + private UserAccountRepository userAccountRepository; + + @Autowired + SuperAdminUserStub superAdminUserStub; + + @MockBean + UserIdentity userIdentity; + + @Autowired + private UserAccountStub userAccountStub; + + @Autowired + private CourtroomStub courtroomStub; + + @Autowired + private MediaStub mediaStub; + + @Autowired + private ObjectAdminActionStub objectAdminActionStub; + + @Autowired + private ObjectHiddenReasonStub objectHiddenReasonStub; + + private MediaEntity mediaEntity; + + private String endpoint; + + @BeforeEach + void setUp() { + String courtHouseName = randomAlphanumeric(8); + var courtroomEntity = courtroomStub.createCourtroomUnlessExists(courtHouseName, "Test Courtroom", + userAccountStub.getSystemUserAccountEntity()); + + // And a media that's marked for deletion, but not yet approved for deletion (not marked for manual deletion) + mediaEntity = createAndSaveMediaEntity(courtroomEntity); + + endpoint = ENDPOINT_URL.replace(MEDIA_ID_SUBSTITUTION_KEY, mediaEntity.getId().toString()); + } + + @Test + void postAdminApproveMediaMarkedForDeletionShouldReturnSuccess() throws Exception { + // given + var superAdminUser = superAdminUserStub.givenUserIsAuthorised(userIdentity); + + var testUser = dartsDatabase.getUserAccountStub().getIntegrationTestUserAccountEntity("testuser"); + objectAdminActionStub.createAndSave(ObjectAdminActionStub.ObjectAdminActionSpec.builder() + .media(mediaEntity) + .objectHiddenReason( + objectHiddenReasonStub.getAnyWithMarkedForDeletion(true)) + .markedForManualDeletion(false) + .markedForManualDelBy(null) + .markedForManualDelDateTime(null) + .hiddenBy(testUser) + .build()); + + // when + MvcResult mvcResult = mockMvc.perform(post(endpoint)) + .andExpect(status().isOk()) + .andReturn(); + + // then + MediaApproveMarkedForDeletionResponse mediaApproveMarkedForDeletionResponse + = objectMapper.readValue(mvcResult.getResponse().getContentAsByteArray(), MediaApproveMarkedForDeletionResponse.class); + AdminActionResponse actionResponse = mediaApproveMarkedForDeletionResponse.getAdminAction(); + assertNotNull(actionResponse.getMarkedForManualDeletionAt()); + assertEquals(superAdminUser.getId(), actionResponse.getMarkedForManualDeletionById()); + assertTrue(actionResponse.getIsMarkedForManualDeletion()); + + } + + @Test + void postAdminApproveMediaMarkedForDeletionWhereCurrentUserMarkedForDeletion() throws Exception { + // given + var superAdminUser = superAdminUserStub.givenUserIsAuthorised(userIdentity); + + objectAdminActionStub.createAndSave(ObjectAdminActionStub.ObjectAdminActionSpec.builder() + .media(mediaEntity) + .objectHiddenReason( + objectHiddenReasonStub.getAnyWithMarkedForDeletion(true)) + .markedForManualDeletion(false) + .markedForManualDelBy(null) + .markedForManualDelDateTime(null) + .hiddenBy(superAdminUser) + .build()); + + // when + MvcResult mvcResult = mockMvc.perform(post(endpoint)) + .andExpect(status().isBadRequest()) + .andReturn(); + + // then + String actualJson = mvcResult.getResponse().getContentAsString(); + + Problem problem = objectMapper.readValue(actualJson, Problem.class); + assertEquals(problem.getType(), AudioApiError.USER_CANNOT_APPROVE_THEIR_OWN_DELETION.getType()); + assertEquals(problem.getTitle(), AudioApiError.USER_CANNOT_APPROVE_THEIR_OWN_DELETION.getTitle()); + } + + @Test + void postAdminApproveMediaMarkedForDeletionWhereMediaMarkedForDeletionTwice() throws Exception { + // given + superAdminUserStub.givenUserIsAuthorised(userIdentity); + var testUser = dartsDatabase.getUserAccountStub().getIntegrationTestUserAccountEntity("testuser"); + + objectAdminActionStub.createAndSave(ObjectAdminActionStub.ObjectAdminActionSpec.builder() + .media(mediaEntity) + .objectHiddenReason( + objectHiddenReasonStub.getAnyWithMarkedForDeletion(true)) + .markedForManualDeletion(false) + .markedForManualDelBy(null) + .markedForManualDelDateTime(null) + .hiddenBy(testUser) + .build()); + + objectAdminActionStub.createAndSave(ObjectAdminActionStub.ObjectAdminActionSpec.builder() + .media(mediaEntity) + .objectHiddenReason( + objectHiddenReasonStub.getAnyWithMarkedForDeletion(true)) + .markedForManualDeletion(false) + .markedForManualDelBy(null) + .markedForManualDelDateTime(null) + .hiddenBy(testUser) + .build()); + + // when + MvcResult mvcResult = mockMvc.perform(post(endpoint)) + .andExpect(status().isBadRequest()) + .andReturn(); + + // then + String actualJson = mvcResult.getResponse().getContentAsString(); + + Problem problem = objectMapper.readValue(actualJson, Problem.class); + assertEquals(problem.getType(), AudioApiError.TOO_MANY_RESULTS.getType()); + assertEquals(problem.getTitle(), AudioApiError.TOO_MANY_RESULTS.getTitle()); + } + + @Test + void postAdminApproveMediaMarkedForDeletionWhereMediaNotMarkedForDeletion() throws Exception { + // given + superAdminUserStub.givenUserIsAuthorised(userIdentity); + var testUser = dartsDatabase.getUserAccountStub().getIntegrationTestUserAccountEntity("testuser"); + + objectAdminActionStub.createAndSave(ObjectAdminActionStub.ObjectAdminActionSpec.builder() + .media(mediaEntity) + .objectHiddenReason( + objectHiddenReasonStub.getAnyWithMarkedForDeletion(false)) + .markedForManualDeletion(false) + .markedForManualDelBy(null) + .markedForManualDelDateTime(null) + .hiddenBy(testUser) + .build()); + + // when + MvcResult mvcResult = mockMvc.perform(post(endpoint)) + .andExpect(status().isBadRequest()) + .andReturn(); + + // then + String actualJson = mvcResult.getResponse().getContentAsString(); + + Problem problem = objectMapper.readValue(actualJson, Problem.class); + assertEquals(problem.getType(), AudioApiError.MEDIA_MARKED_FOR_DELETION_REASON_NOT_FOUND.getType()); + assertEquals(problem.getTitle(), AudioApiError.MEDIA_MARKED_FOR_DELETION_REASON_NOT_FOUND.getTitle()); + } + + @Test + void postAdminApproveMediaMarkedForDeletionAlreadyApproved() throws Exception { + // given + superAdminUserStub.givenUserIsAuthorised(userIdentity); + + var testUser = dartsDatabase.getUserAccountStub().getIntegrationTestUserAccountEntity("testuser"); + objectAdminActionStub.createAndSave(ObjectAdminActionStub.ObjectAdminActionSpec.builder() + .media(mediaEntity) + .objectHiddenReason( + objectHiddenReasonStub.getAnyWithMarkedForDeletion(true)) + .hiddenBy(testUser) + .build()); + + // when + MvcResult mvcResult = mockMvc.perform(post(endpoint)) + .andExpect(status().isConflict()) + .andReturn(); + + // then + String actualJson = mvcResult.getResponse().getContentAsString(); + + Problem problem = objectMapper.readValue(actualJson, Problem.class); + assertEquals(problem.getType(), AudioApiError.MEDIA_ALREADY_MARKED_FOR_DELETION.getType()); + assertEquals(problem.getTitle(), AudioApiError.MEDIA_ALREADY_MARKED_FOR_DELETION.getTitle()); + + } + + @Test + void postAdminApproveMediaMarkedForDeletionMediaNotMarkedForDeletion() throws Exception { + // given + superAdminUserStub.givenUserIsAuthorised(userIdentity); + + // when + MvcResult mvcResult = mockMvc.perform(post(endpoint)) + .andExpect(status().isNotFound()) + .andReturn(); + + // then + String actualJson = mvcResult.getResponse().getContentAsString(); + + Problem problem = objectMapper.readValue(actualJson, Problem.class); + assertEquals(problem.getType(), AudioApiError.ADMIN_MEDIA_MARKED_FOR_DELETION_NOT_FOUND.getType()); + assertEquals(problem.getTitle(), AudioApiError.ADMIN_MEDIA_MARKED_FOR_DELETION_NOT_FOUND.getTitle()); + + } + + @ParameterizedTest + @EnumSource(value = SecurityRoleEnum.class, names = {"SUPER_ADMIN"}, mode = EnumSource.Mode.EXCLUDE) + void testForbidden(SecurityRoleEnum role) throws Exception { + // given + superAdminUserStub.givenUserIsAuthorised(userIdentity, role); + + // when then + mockMvc.perform(post(endpoint)) + .andExpect(status().isForbidden()) + .andReturn(); + + } + + private MediaEntity createAndSaveMediaEntity(CourtroomEntity courtroomEntity) { + return mediaStub.createMediaEntity(courtroomEntity.getCourthouse().getCourthouseName(), + courtroomEntity.getName(), + START_TIME, + END_TIME, + 1, + "MP2"); + } + +} diff --git a/src/integrationTest/java/uk/gov/hmcts/darts/common/repository/ObjectAdminActionRepositoryTest.java b/src/integrationTest/java/uk/gov/hmcts/darts/common/repository/ObjectAdminActionRepositoryTest.java index 9e44709ec2..642b8795cf 100644 --- a/src/integrationTest/java/uk/gov/hmcts/darts/common/repository/ObjectAdminActionRepositoryTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/darts/common/repository/ObjectAdminActionRepositoryTest.java @@ -101,6 +101,31 @@ void findAllWithAnyDeletionReasonShouldReturnExpectedResultsWhenMediaExistsMedia Assertions.assertEquals(expectedObjectAdminActionEntity.getId(), result.getFirst().getId()); } + @Test + void findByMediaIdAndMarkedForManualDeletionTrue() { + var media = dartsDatabase.getMediaStub().createAndSaveMedia(); + var markedForManualDeletionAction = objectAdminActionStub.createAndSave(ObjectAdminActionStub.ObjectAdminActionSpec.builder() + .media(media) + .objectHiddenReason( + objectHiddenReasonStub.getAnyWithMarkedForDeletion(true)) + .markedForManualDeletion(true) + .build()); + objectAdminActionStub.createAndSave(ObjectAdminActionStub.ObjectAdminActionSpec.builder() + .media(media) + .objectHiddenReason( + objectHiddenReasonStub.getAnyWithMarkedForDeletion(true)) + .markedForManualDeletion(false) + .build()); + + + // When + List result = repository.findByMediaIdAndMarkedForManualDeletionTrue(media.getId()); + + // Then + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(markedForManualDeletionAction.getId(), result.getFirst().getId()); + } + private MediaEntity createAndSaveMediaEntity(CourtroomEntity courtroomEntity) { return mediaStub.createMediaEntity(courtroomEntity.getCourthouse().getCourthouseName(), courtroomEntity.getName(), diff --git a/src/main/java/uk/gov/hmcts/darts/audio/controller/AudioController.java b/src/main/java/uk/gov/hmcts/darts/audio/controller/AudioController.java index 3558ce6268..5f3c618c79 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/controller/AudioController.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/controller/AudioController.java @@ -19,6 +19,7 @@ import uk.gov.hmcts.darts.audio.model.AudioPreview; import uk.gov.hmcts.darts.audio.model.GetAdminMediaResponseItem; import uk.gov.hmcts.darts.audio.model.GetTransformedMediaResponse; +import uk.gov.hmcts.darts.audio.model.MediaApproveMarkedForDeletionResponse; import uk.gov.hmcts.darts.audio.model.MediaHideRequest; import uk.gov.hmcts.darts.audio.model.MediaHideResponse; import uk.gov.hmcts.darts.audio.model.PostAdminMediasMarkedForDeletionItem; @@ -139,7 +140,6 @@ public ResponseEntity> getAdminMedias(Integer tr return new ResponseEntity<>(response, HttpStatus.OK); } - @Override @SecurityRequirement(name = SECURITY_SCHEMES_BEARER_AUTH) @Authorisation(contextId = ANY_ENTITY_ID, globalAccessSecurityRoles = {SUPER_ADMIN}) @@ -148,6 +148,14 @@ public ResponseEntity postAdminHideMediaId(Integer mediaId, M return new ResponseEntity<>(audioResponse, HttpStatus.OK); } + @Override + @SecurityRequirement(name = SECURITY_SCHEMES_BEARER_AUTH) + @Authorisation(contextId = ANY_ENTITY_ID, globalAccessSecurityRoles = {SUPER_ADMIN}) + public ResponseEntity postAdminApproveMediaMarkedForDeletion(Integer mediaId) { + MediaApproveMarkedForDeletionResponse audioResponse = adminMediaService.adminApproveMediaMarkedForDeletion(mediaId); + return new ResponseEntity<>(audioResponse, HttpStatus.OK); + } + @Override @SecurityRequirement(name = SECURITY_SCHEMES_BEARER_AUTH) @Authorisation(contextId = ANY_ENTITY_ID, globalAccessSecurityRoles = {SUPER_USER, SUPER_ADMIN}) diff --git a/src/main/java/uk/gov/hmcts/darts/audio/exception/AudioApiError.java b/src/main/java/uk/gov/hmcts/darts/audio/exception/AudioApiError.java index b12580c729..8a2670409c 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/exception/AudioApiError.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/exception/AudioApiError.java @@ -89,7 +89,29 @@ public enum AudioApiError implements DartsApiError { TOO_MANY_RESULTS( AddAudioErrorCode.TOO_MANY_RESULTS.getValue(), HttpStatus.BAD_REQUEST, - AddAudioTitleErrors.TOO_MANY_RESULTS.getValue()); + AddAudioTitleErrors.TOO_MANY_RESULTS.getValue() + ), + MEDIA_ALREADY_MARKED_FOR_DELETION( + AddAudioErrorCode.MEDIA_ALREADY_MARKED_FOR_DELETION.getValue(), + HttpStatus.CONFLICT, + AddAudioTitleErrors.MEDIA_ALREADY_MARKED_FOR_DELETION.getValue() + ), + ADMIN_MEDIA_MARKED_FOR_DELETION_NOT_FOUND( + AddAudioErrorCode.ADMIN_MEDIA_MARKED_FOR_DELETION_NOT_FOUND.getValue(), + HttpStatus.NOT_FOUND, + AddAudioTitleErrors.ADMIN_MEDIA_MARKED_FOR_DELETION_NOT_FOUND.getValue() + ), + MEDIA_MARKED_FOR_DELETION_REASON_NOT_FOUND( + AddAudioErrorCode.MARKED_FOR_DELETION_REASON_NOT_FOUND.getValue(), + HttpStatus.BAD_REQUEST, + AddAudioTitleErrors.MARKED_FOR_DELETION_REASON_NOT_FOUND.getValue() + ), + USER_CANNOT_APPROVE_THEIR_OWN_DELETION( + AddAudioErrorCode.USER_CANT_APPROVE_THEIR_OWN_DELETION.getValue(), + HttpStatus.BAD_REQUEST, + AddAudioTitleErrors.USER_CANT_APPROVE_THEIR_OWN_DELETION.getValue() + ); + private static final String ERROR_TYPE_PREFIX = "AUDIO"; diff --git a/src/main/java/uk/gov/hmcts/darts/audio/mapper/GetAdminMediaResponseMapper.java b/src/main/java/uk/gov/hmcts/darts/audio/mapper/GetAdminMediaResponseMapper.java index cc691cfa83..89e47f4e99 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/mapper/GetAdminMediaResponseMapper.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/mapper/GetAdminMediaResponseMapper.java @@ -8,6 +8,7 @@ import uk.gov.hmcts.darts.audio.model.GetAdminMediaResponseCourtroom; import uk.gov.hmcts.darts.audio.model.GetAdminMediaResponseHearing; import uk.gov.hmcts.darts.audio.model.GetAdminMediaResponseItem; +import uk.gov.hmcts.darts.audio.model.MediaApproveMarkedForDeletionResponse; import uk.gov.hmcts.darts.audio.model.MediaHideResponse; import uk.gov.hmcts.darts.common.entity.CourtCaseEntity; import uk.gov.hmcts.darts.common.entity.CourthouseEntity; @@ -83,20 +84,36 @@ public MediaHideResponse mapHideOrShowResponse(MediaEntity entity, ObjectAdminAc response.setIsDeleted(entity.isDeleted()); if (objectAdminActionEntity != null) { - AdminActionResponse aaResponse = new AdminActionResponse(); - aaResponse.setId(objectAdminActionEntity.getId()); - aaResponse.setReasonId(objectAdminActionEntity.getObjectHiddenReason().getId()); - aaResponse.setHiddenById(objectAdminActionEntity.getHiddenBy().getId()); - aaResponse.setHiddenAt(objectAdminActionEntity.getHiddenDateTime()); - aaResponse.setIsMarkedForManualDeletion(objectAdminActionEntity.isMarkedForManualDeletion()); - aaResponse.setMarkedForManualDeletionById( - objectAdminActionEntity.getMarkedForManualDelBy() == null ? null : objectAdminActionEntity.getMarkedForManualDelBy().getId()); - aaResponse.setMarkedForManualDeletionAt( - objectAdminActionEntity.getMarkedForManualDelDateTime() == null ? null : objectAdminActionEntity.getMarkedForManualDelDateTime()); - aaResponse.setTicketReference(objectAdminActionEntity.getTicketReference()); - aaResponse.setComments(objectAdminActionEntity.getComments()); - - response.setAdminAction(aaResponse); + response.setAdminAction(buildAdminActionResponse(objectAdminActionEntity)); + } + + return response; + } + + private static AdminActionResponse buildAdminActionResponse(ObjectAdminActionEntity objectAdminActionEntity) { + AdminActionResponse aaResponse = new AdminActionResponse(); + aaResponse.setId(objectAdminActionEntity.getId()); + aaResponse.setReasonId(objectAdminActionEntity.getObjectHiddenReason().getId()); + aaResponse.setHiddenById(objectAdminActionEntity.getHiddenBy().getId()); + aaResponse.setHiddenAt(objectAdminActionEntity.getHiddenDateTime()); + aaResponse.setIsMarkedForManualDeletion(objectAdminActionEntity.isMarkedForManualDeletion()); + aaResponse.setMarkedForManualDeletionById( + objectAdminActionEntity.getMarkedForManualDelBy() == null ? null : objectAdminActionEntity.getMarkedForManualDelBy().getId()); + aaResponse.setMarkedForManualDeletionAt( + objectAdminActionEntity.getMarkedForManualDelDateTime() == null ? null : objectAdminActionEntity.getMarkedForManualDelDateTime()); + aaResponse.setTicketReference(objectAdminActionEntity.getTicketReference()); + aaResponse.setComments(objectAdminActionEntity.getComments()); + return aaResponse; + } + + public MediaApproveMarkedForDeletionResponse mapMediaApproveMarkedForDeletionResponse(MediaEntity entity, ObjectAdminActionEntity objectAdminActionEntity) { + MediaApproveMarkedForDeletionResponse response = new MediaApproveMarkedForDeletionResponse(); + response.setId(entity.getId()); + response.setIsHidden(entity.isHidden()); + response.setIsDeleted(entity.isDeleted()); + + if (objectAdminActionEntity != null) { + response.setAdminAction(buildAdminActionResponse(objectAdminActionEntity)); } return response; diff --git a/src/main/java/uk/gov/hmcts/darts/audio/service/AdminMediaService.java b/src/main/java/uk/gov/hmcts/darts/audio/service/AdminMediaService.java index ac6d35ed8d..6748da4616 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/service/AdminMediaService.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/service/AdminMediaService.java @@ -2,6 +2,7 @@ import uk.gov.hmcts.darts.audio.model.AdminMediaResponse; import uk.gov.hmcts.darts.audio.model.GetAdminMediaResponseItem; +import uk.gov.hmcts.darts.audio.model.MediaApproveMarkedForDeletionResponse; import uk.gov.hmcts.darts.audio.model.PostAdminMediasMarkedForDeletionItem; import uk.gov.hmcts.darts.audio.model.PostAdminMediasSearchRequest; import uk.gov.hmcts.darts.audio.model.PostAdminMediasSearchResponseItem; @@ -24,4 +25,5 @@ default List filterMediasWithTransformedMediaId(Integ List getMediasMarkedForDeletion(); + MediaApproveMarkedForDeletionResponse adminApproveMediaMarkedForDeletion(Integer mediaId); } \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/darts/audio/service/MediaRequestService.java b/src/main/java/uk/gov/hmcts/darts/audio/service/MediaRequestService.java index 34aad967ec..2946eccabc 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/service/MediaRequestService.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/service/MediaRequestService.java @@ -63,4 +63,5 @@ public interface MediaRequestService { MediaPatchResponse patchMediaRequest(Integer mediaRequestId, MediaPatchRequest request); MediaHideResponse adminHideOrShowMediaById(Integer mediaId, MediaHideRequest mediaHideRequest); + } \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AdminMediaServiceImpl.java b/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AdminMediaServiceImpl.java index c4aae18c78..3aa9bb78a4 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AdminMediaServiceImpl.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AdminMediaServiceImpl.java @@ -4,6 +4,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import uk.gov.hmcts.darts.audio.entity.MediaRequestEntity; import uk.gov.hmcts.darts.audio.exception.AudioApiError; import uk.gov.hmcts.darts.audio.helper.PostAdminMediasSearchHelper; @@ -13,17 +14,21 @@ import uk.gov.hmcts.darts.audio.mapper.PostAdminMediaSearchResponseMapper; import uk.gov.hmcts.darts.audio.model.AdminMediaResponse; import uk.gov.hmcts.darts.audio.model.GetAdminMediaResponseItem; +import uk.gov.hmcts.darts.audio.model.MediaApproveMarkedForDeletionResponse; import uk.gov.hmcts.darts.audio.model.MediaSearchData; import uk.gov.hmcts.darts.audio.model.PostAdminMediasMarkedForDeletionItem; import uk.gov.hmcts.darts.audio.model.PostAdminMediasSearchRequest; import uk.gov.hmcts.darts.audio.model.PostAdminMediasSearchResponseItem; import uk.gov.hmcts.darts.audio.service.AdminMediaService; +import uk.gov.hmcts.darts.audio.validation.MediaApproveMarkForDeletionValidator; import uk.gov.hmcts.darts.audio.validation.SearchMediaValidator; +import uk.gov.hmcts.darts.authorisation.component.UserIdentity; import uk.gov.hmcts.darts.common.entity.HearingEntity; import uk.gov.hmcts.darts.common.entity.MediaEntity; import uk.gov.hmcts.darts.common.entity.ObjectAdminActionEntity; import uk.gov.hmcts.darts.common.entity.TransformedMediaEntity; import uk.gov.hmcts.darts.common.exception.DartsApiException; +import uk.gov.hmcts.darts.common.helper.CurrentTimeHelper; import uk.gov.hmcts.darts.common.repository.MediaRepository; import uk.gov.hmcts.darts.common.repository.ObjectAdminActionRepository; import uk.gov.hmcts.darts.common.repository.TransformedMediaRepository; @@ -48,6 +53,9 @@ public class AdminMediaServiceImpl implements AdminMediaService { private final SearchMediaValidator searchMediaValidator; private final TransformedMediaRepository transformedMediaRepository; private final ObjectAdminActionRepository objectAdminActionRepository; + private final MediaApproveMarkForDeletionValidator mediaApproveMarkForDeletionValidator; + private final UserIdentity userIdentity; + private final CurrentTimeHelper currentTimeHelper; public AdminMediaResponse getMediasById(Integer id) { var mediaEntity = mediaRepository.findById(id) @@ -123,4 +131,26 @@ private List getApplicableMediaHearings(MediaEntity mediaEntity, return hearingEntityList; } + + @Override + @Transactional + public MediaApproveMarkedForDeletionResponse adminApproveMediaMarkedForDeletion(Integer mediaId) { + + mediaApproveMarkForDeletionValidator.validate(mediaId); + List objectAdminActionEntityList = objectAdminActionRepository.findByMedia_Id(mediaId); + + Optional mediaEntityOptional = mediaRepository.findById(mediaId); + if (mediaEntityOptional.isEmpty()) { + throw new DartsApiException(AudioApiError.MEDIA_NOT_FOUND); + } + MediaEntity mediaEntity = mediaEntityOptional.get(); + var currentUser = userIdentity.getUserAccount(); + var objectAdminActionEntity = objectAdminActionEntityList.getFirst(); + objectAdminActionEntity.setMarkedForManualDeletion(true); + objectAdminActionEntity.setMarkedForManualDelBy(currentUser); + objectAdminActionEntity.setMarkedForManualDelDateTime(currentTimeHelper.currentOffsetDateTime()); + objectAdminActionRepository.save(objectAdminActionEntity); + + return GetAdminMediaResponseMapper.mapMediaApproveMarkedForDeletionResponse(mediaEntity, objectAdminActionEntity); + } } \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/darts/audio/service/impl/MediaRequestServiceImpl.java b/src/main/java/uk/gov/hmcts/darts/audio/service/impl/MediaRequestServiceImpl.java index 0096424fdb..c3da48ba44 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/service/impl/MediaRequestServiceImpl.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/service/impl/MediaRequestServiceImpl.java @@ -562,8 +562,7 @@ public MediaHideResponse adminHideOrShowMediaById(Integer mediaId, MediaHideRequ objectHiddenReasonEntity = objectHiddenReasonRepository.findById(mediaHideRequest.getAdminAction().getReasonId()); if (objectHiddenReasonEntity.isEmpty()) { - throw new DartsApiException(AudioApiError - .MEDIA_HIDE_ACTION_REASON_NOT_FOUND); + throw new DartsApiException(AudioApiError.MEDIA_HIDE_ACTION_REASON_NOT_FOUND); } // on hiding add the relevant hide record @@ -594,4 +593,5 @@ public MediaHideResponse adminHideOrShowMediaById(Integer mediaId, MediaHideRequ return response; } + } \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/darts/audio/validation/MediaApproveMarkForDeletionValidator.java b/src/main/java/uk/gov/hmcts/darts/audio/validation/MediaApproveMarkForDeletionValidator.java new file mode 100644 index 0000000000..10ac5be6c8 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/darts/audio/validation/MediaApproveMarkForDeletionValidator.java @@ -0,0 +1,56 @@ +package uk.gov.hmcts.darts.audio.validation; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import uk.gov.hmcts.darts.audio.exception.AudioApiError; +import uk.gov.hmcts.darts.authorisation.component.UserIdentity; +import uk.gov.hmcts.darts.common.component.validation.Validator; +import uk.gov.hmcts.darts.common.entity.ObjectHiddenReasonEntity; +import uk.gov.hmcts.darts.common.entity.UserAccountEntity; +import uk.gov.hmcts.darts.common.exception.DartsApiException; +import uk.gov.hmcts.darts.common.repository.ObjectAdminActionRepository; +import uk.gov.hmcts.darts.common.repository.ObjectHiddenReasonRepository; + +import static java.util.Objects.isNull; + +@Component +@RequiredArgsConstructor +public class MediaApproveMarkForDeletionValidator implements Validator { + + private final MediaIdValidator mediaIdValidator; + private final ObjectAdminActionRepository objectAdminActionRepository; + private final ObjectHiddenReasonRepository objectHiddenReasonRepository; + private final UserIdentity userIdentity; + + @Override + public void validate(Integer mediaId) { + mediaIdValidator.validate(mediaId); + var objectAdminActionEntityList = objectAdminActionRepository.findByMedia_Id(mediaId); + if (objectAdminActionEntityList.isEmpty()) { + throw new DartsApiException(AudioApiError.ADMIN_MEDIA_MARKED_FOR_DELETION_NOT_FOUND); + } else if (objectAdminActionEntityList.size() > 1) { + throw new DartsApiException(AudioApiError.TOO_MANY_RESULTS); + } + + var objectAdminActionEntity = objectAdminActionEntityList.getFirst(); + if (objectAdminActionEntity.isMarkedForManualDeletion()) { + throw new DartsApiException(AudioApiError.MEDIA_ALREADY_MARKED_FOR_DELETION); + } + + if (objectAdminActionEntity.getObjectHiddenReason() == null) { + throw new DartsApiException(AudioApiError.MEDIA_MARKED_FOR_DELETION_REASON_NOT_FOUND); + } + ObjectHiddenReasonEntity objectHiddenReasonEntity = + objectHiddenReasonRepository.findById(objectAdminActionEntity.getObjectHiddenReason().getId()) + .orElseThrow(() -> new DartsApiException(AudioApiError.MEDIA_MARKED_FOR_DELETION_REASON_NOT_FOUND)); + if (!objectHiddenReasonEntity.isMarkedForDeletion()) { + throw new DartsApiException(AudioApiError.MEDIA_MARKED_FOR_DELETION_REASON_NOT_FOUND); + } + UserAccountEntity currentUser = userIdentity.getUserAccount(); + UserAccountEntity hiddenBy = objectAdminActionEntity.getHiddenBy(); + if (isNull(hiddenBy) + || hiddenBy.getId().equals(currentUser.getId())) { + throw new DartsApiException(AudioApiError.USER_CANNOT_APPROVE_THEIR_OWN_DELETION); + } + } +} diff --git a/src/main/java/uk/gov/hmcts/darts/common/repository/ObjectAdminActionRepository.java b/src/main/java/uk/gov/hmcts/darts/common/repository/ObjectAdminActionRepository.java index 0e30d95e9d..0c8c4c2c7f 100644 --- a/src/main/java/uk/gov/hmcts/darts/common/repository/ObjectAdminActionRepository.java +++ b/src/main/java/uk/gov/hmcts/darts/common/repository/ObjectAdminActionRepository.java @@ -12,7 +12,9 @@ public interface ObjectAdminActionRepository extends JpaRepository { List findByTranscriptionDocument_Id(Integer transcriptionDocumentId); - List findByMedia_Id(Integer transcriptionDocumentId); + List findByMedia_Id(Integer mediaId); + + List findByMediaIdAndMarkedForManualDeletionTrue(Integer mediaId); @Query(""" SELECT objectAdminActionEntity diff --git a/src/main/resources/openapi/audio.yaml b/src/main/resources/openapi/audio.yaml index 28e49b068a..f1a653b18c 100644 --- a/src/main/resources/openapi/audio.yaml +++ b/src/main/resources/openapi/audio.yaml @@ -351,6 +351,42 @@ paths: allOf: - $ref: './problem.yaml' + /admin/medias/{media_id}/approve-deletion: + post: + tags: + - Audio + summary: Approves deletion of media + operationId: postAdminApproveMediaMarkedForDeletion + parameters: + - name: media_id + in: path + required: true + schema: + type: integer + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/MediaApproveMarkedForDeletionResponse' + '400': + description: A required parameter is missing or an invalid datatype or value was provided for property. + '409': + description: Data conflicting + content: + application/json+problem: + schema: + allOf: + - $ref: + './problem.yaml' + '404': + description: Not Found Error + content: + application/json+problem: + schema: + allOf: + - $ref: './problem.yaml' /admin/medias/search: post: @@ -464,6 +500,7 @@ components: admin_action: $ref: '#/components/schemas/AdminActionResponse' + CourthouseResponseObject: type: object properties: @@ -756,6 +793,10 @@ components: $ref: '#/components/schemas/AdminActionResponse' description: 'The media admin action data when the request was made' + MediaApproveMarkedForDeletionResponse: + allOf: + - $ref: '#/components/schemas/MediaHideResponse' + AdminActionResponse: type: object properties: @@ -955,6 +996,10 @@ components: - "AUDIO_113" - "AUDIO_115" - "AUDIO_116" + - "AUDIO_117" + - "AUDIO_118" + - "AUDIO_119" + - "AUDIO_120" x-enum-varnames: [ FAILED_TO_PROCESS_AUDIO_REQUEST, REQUESTED_DATA_CANNOT_BE_LOCATED, MEDIA_NOT_FOUND, @@ -970,7 +1015,12 @@ components: MEDIA_SHOW_ACTION_PAYLOAD_INCORRECT_USAGE, MEDIA_HIDE_ACTION_REASON_NOT_FOUND, ADMIN_SEARCH_CRITERIA_NOT_SUITABLE, - TOO_MANY_RESULTS ] + TOO_MANY_RESULTS, + MEDIA_ALREADY_MARKED_FOR_DELETION, + ADMIN_MEDIA_MARKED_FOR_DELETION_NOT_FOUND, + MARKED_FOR_DELETION_REASON_NOT_FOUND, + USER_CANT_APPROVE_THEIR_OWN_DELETION + ] AddAudioTitleErrors: type: string @@ -991,6 +1041,10 @@ components: - "Hide reason is incorrect" - "transformed_media_id OR one of hearing_id, start_at or end_at must be provided" - "Too many results" + - "Already marked for deletion" + - "Media marked for deletion not found" + - "Media marked for deletion reason not found" + - "User cannot approve their own deletion" x-enum-varnames: [ FAILED_TO_PROCESS_AUDIO_REQUEST, REQUESTED_DATA_CANNOT_BE_LOCATED, MEDIA_NOT_FOUND, @@ -1006,4 +1060,9 @@ components: MEDIA_SHOW_ACTION_PAYLOAD_INCORRECT_USAGE, MEDIA_HIDE_ACTION_REASON_NOT_FOUND, ADMIN_SEARCH_CRITERIA_NOT_SUITABLE, - TOO_MANY_RESULTS ] \ No newline at end of file + TOO_MANY_RESULTS, + MEDIA_ALREADY_MARKED_FOR_DELETION, + ADMIN_MEDIA_MARKED_FOR_DELETION_NOT_FOUND, + MARKED_FOR_DELETION_REASON_NOT_FOUND, + USER_CANT_APPROVE_THEIR_OWN_DELETION + ] \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AdminMediaServiceImplApproveMarkedForDeletionTest.java b/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AdminMediaServiceImplApproveMarkedForDeletionTest.java new file mode 100644 index 0000000000..bbee92a255 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AdminMediaServiceImplApproveMarkedForDeletionTest.java @@ -0,0 +1,117 @@ +package uk.gov.hmcts.darts.audio.service.impl; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.darts.audio.exception.AudioApiError; +import uk.gov.hmcts.darts.audio.model.MediaApproveMarkedForDeletionResponse; +import uk.gov.hmcts.darts.audio.validation.MediaApproveMarkForDeletionValidator; +import uk.gov.hmcts.darts.authorisation.component.UserIdentity; +import uk.gov.hmcts.darts.common.entity.MediaEntity; +import uk.gov.hmcts.darts.common.entity.UserAccountEntity; +import uk.gov.hmcts.darts.common.exception.DartsApiException; +import uk.gov.hmcts.darts.common.helper.CurrentTimeHelper; +import uk.gov.hmcts.darts.common.repository.MediaRepository; +import uk.gov.hmcts.darts.common.repository.ObjectAdminActionRepository; +import uk.gov.hmcts.darts.common.repository.ObjectHiddenReasonRepository; +import uk.gov.hmcts.darts.test.common.data.ObjectAdminActionTestData; +import uk.gov.hmcts.darts.test.common.data.ObjectHiddenReasonTestData; +import uk.gov.hmcts.darts.test.common.data.UserAccountTestData; + +import java.time.OffsetDateTime; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class AdminMediaServiceImplApproveMarkedForDeletionTest { + @Mock + private MediaRepository mediaRepository; + + @Mock + private ObjectAdminActionRepository objectAdminActionRepository; + + @Mock + private ObjectHiddenReasonRepository objectHiddenReasonRepository; + + @Mock + private MediaApproveMarkForDeletionValidator mediaApproveMarkForDeletionValidator; + + @Mock + private UserIdentity userIdentity; + + @Mock + private CurrentTimeHelper currentTimeHelper; + + @InjectMocks + private AdminMediaServiceImpl adminMediaService; + @Mock + private UserAccountEntity userAccount; + + @BeforeEach + void setUp() { + lenient().when(currentTimeHelper.currentOffsetDateTime()).thenReturn(OffsetDateTime.now()); + } + + @Test + void testAdminApproveMediaMarkedForDeletionSuccess() { + // given + Integer mediaId = 1; + MediaEntity mediaEntity = new MediaEntity(); + mediaEntity.setId(mediaId); + + var hiddenByUserAccount = UserAccountTestData.minimalUserAccount(); + hiddenByUserAccount.setId(123); + var objectAdminAction = ObjectAdminActionTestData.minimalObjectAdminAction(); + objectAdminAction.setMedia(mediaEntity); + objectAdminAction.setMarkedForManualDeletion(false); + objectAdminAction.setHiddenBy(hiddenByUserAccount); + + var hiddenReason = ObjectHiddenReasonTestData.otherDelete(); + objectAdminAction.setObjectHiddenReason(hiddenReason); + + var authorisedByUserAccount = UserAccountTestData.minimalUserAccount(); + authorisedByUserAccount.setId(345); + + when(mediaRepository.findById(mediaId)).thenReturn(Optional.of(mediaEntity)); + when(userIdentity.getUserAccount()).thenReturn(userAccount); + + when(objectAdminActionRepository.findByMedia_Id(mediaId)).thenReturn(List.of(objectAdminAction)); + when(userIdentity.getUserAccount()).thenReturn(authorisedByUserAccount); + + MediaApproveMarkedForDeletionResponse response = adminMediaService.adminApproveMediaMarkedForDeletion(mediaId); + + assertNotNull(response); + verify(mediaApproveMarkForDeletionValidator, times(1)).validate(mediaId); + verify(objectAdminActionRepository, times(1)).save(objectAdminAction); + } + + @Test + void testAdminApproveMediaMarkedForDeletionMediaNotFound() { + // given + Integer mediaId = 1; + + when(mediaRepository.findById(mediaId)).thenReturn(Optional.empty()); + + // when + DartsApiException exception = assertThrows(DartsApiException.class, () -> adminMediaService.adminApproveMediaMarkedForDeletion(mediaId)); + + //then + assertEquals(AudioApiError.MEDIA_NOT_FOUND, exception.getError()); + verify(mediaApproveMarkForDeletionValidator, times(1)).validate(mediaId); + verify(objectAdminActionRepository, never()).save(any()); + } + +} diff --git a/src/test/java/uk/gov/hmcts/darts/audio/validator/AudioMediaPatchRequestValidatorTest.java b/src/test/java/uk/gov/hmcts/darts/audio/validation/AudioMediaPatchRequestValidatorTest.java similarity index 81% rename from src/test/java/uk/gov/hmcts/darts/audio/validator/AudioMediaPatchRequestValidatorTest.java rename to src/test/java/uk/gov/hmcts/darts/audio/validation/AudioMediaPatchRequestValidatorTest.java index a09ad144b6..778bb6bb65 100644 --- a/src/test/java/uk/gov/hmcts/darts/audio/validator/AudioMediaPatchRequestValidatorTest.java +++ b/src/test/java/uk/gov/hmcts/darts/audio/validation/AudioMediaPatchRequestValidatorTest.java @@ -1,4 +1,4 @@ -package uk.gov.hmcts.darts.audio.validator; +package uk.gov.hmcts.darts.audio.validation; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -9,7 +9,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import uk.gov.hmcts.darts.audio.entity.MediaRequestEntity; import uk.gov.hmcts.darts.audio.exception.AudioRequestsApiError; -import uk.gov.hmcts.darts.audio.validation.AudioMediaPatchRequestValidator; import uk.gov.hmcts.darts.audiorequests.model.MediaPatchRequest; import uk.gov.hmcts.darts.common.entity.UserAccountEntity; import uk.gov.hmcts.darts.common.exception.DartsApiException; @@ -19,8 +18,6 @@ import java.util.Optional; -import static org.mockito.ArgumentMatchers.eq; - @ExtendWith(MockitoExtension.class) class AudioMediaPatchRequestValidatorTest { @@ -40,7 +37,7 @@ void successfulPatchWithoutOwner() { IdRequest mediaPatchRequest = new IdRequest<>(mediaPatchRequestId, mediaRequestId); MediaRequestEntity entityResponse = new MediaRequestEntity(); - Mockito.when(mediaRequestRepository.findById(eq(mediaRequestId))).thenReturn(Optional.of(entityResponse)); + Mockito.when(mediaRequestRepository.findById(mediaRequestId)).thenReturn(Optional.of(entityResponse)); audioMediaPatchRequestValidator.validate(mediaPatchRequest); } @@ -57,8 +54,8 @@ void successfulPatchWithOwner() { MediaRequestEntity entityResponse = new MediaRequestEntity(); UserAccountEntity userAccountEntity = new UserAccountEntity(); - Mockito.when(mediaRequestRepository.findById(eq(mediaRequestId))).thenReturn(Optional.of(entityResponse)); - Mockito.when(userAccountRepository.findById(eq(ownerIntger))).thenReturn(Optional.of(userAccountEntity)); + Mockito.when(mediaRequestRepository.findById(mediaRequestId)).thenReturn(Optional.of(entityResponse)); + Mockito.when(userAccountRepository.findById(ownerIntger)).thenReturn(Optional.of(userAccountEntity)); audioMediaPatchRequestValidator.validate(mediaPatchRequest); } @@ -72,7 +69,7 @@ void failureWithMediaRequestId() { mediaPatchRequestId.setOwnerId(ownerIntger); IdRequest mediaPatchRequest = new IdRequest<>(mediaPatchRequestId, mediaRequestId); - Mockito.when(mediaRequestRepository.findById(eq(mediaRequestId))).thenReturn(Optional.empty()); + Mockito.when(mediaRequestRepository.findById(mediaRequestId)).thenReturn(Optional.empty()); DartsApiException exception = Assertions.assertThrows(DartsApiException.class, () -> audioMediaPatchRequestValidator.validate(mediaPatchRequest)); @@ -90,8 +87,8 @@ void failureWithUserOwnerId() { MediaRequestEntity entityResponse = new MediaRequestEntity(); - Mockito.when(mediaRequestRepository.findById(eq(mediaRequestId))).thenReturn(Optional.of(entityResponse)); - Mockito.when(userAccountRepository.findById(eq(ownerIntger))).thenReturn(Optional.empty()); + Mockito.when(mediaRequestRepository.findById(mediaRequestId)).thenReturn(Optional.of(entityResponse)); + Mockito.when(userAccountRepository.findById(ownerIntger)).thenReturn(Optional.empty()); DartsApiException exception = Assertions.assertThrows(DartsApiException.class, () -> audioMediaPatchRequestValidator.validate(mediaPatchRequest)); diff --git a/src/test/java/uk/gov/hmcts/darts/audio/validation/MediaApproveMarkForDeletionValidatorTest.java b/src/test/java/uk/gov/hmcts/darts/audio/validation/MediaApproveMarkForDeletionValidatorTest.java new file mode 100644 index 0000000000..dd092a82f8 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/darts/audio/validation/MediaApproveMarkForDeletionValidatorTest.java @@ -0,0 +1,155 @@ +package uk.gov.hmcts.darts.audio.validation; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.darts.audio.exception.AudioApiError; +import uk.gov.hmcts.darts.authorisation.component.UserIdentity; +import uk.gov.hmcts.darts.common.exception.DartsApiException; +import uk.gov.hmcts.darts.common.repository.ObjectAdminActionRepository; +import uk.gov.hmcts.darts.common.repository.ObjectHiddenReasonRepository; +import uk.gov.hmcts.darts.test.common.data.ObjectAdminActionTestData; +import uk.gov.hmcts.darts.test.common.data.ObjectHiddenReasonTestData; +import uk.gov.hmcts.darts.test.common.data.UserAccountTestData; + +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MediaApproveMarkForDeletionValidatorTest { + + @Mock + private MediaIdValidator mediaIdValidator; + @Mock + private ObjectAdminActionRepository objectAdminActionRepository; + @Mock + private ObjectHiddenReasonRepository objectHiddenReasonRepository; + @Mock + private UserIdentity userIdentity; + + @InjectMocks + MediaApproveMarkForDeletionValidator mediaApproveMarkForDeletionValidator; + + @Test + void validateMediaWhereMediaNotMarkedForDeletion() { + // given + Integer mediaId = 200; + + // when + DartsApiException exception = assertThrows(DartsApiException.class, + () -> mediaApproveMarkForDeletionValidator.validate(mediaId)); + + // then + assertEquals(AudioApiError.ADMIN_MEDIA_MARKED_FOR_DELETION_NOT_FOUND, exception.getError()); + } + + @Test + void validateMediaWhereObjectAdminActionHasTooManyResults() { + // given + Integer mediaId = 200; + var objectAdminAction1 = ObjectAdminActionTestData.minimalObjectAdminAction(); + var objectAdminAction2 = ObjectAdminActionTestData.minimalObjectAdminAction(); + when(objectAdminActionRepository.findByMedia_Id(mediaId)).thenReturn(List.of(objectAdminAction1, objectAdminAction2)); + + + // when + DartsApiException exception = assertThrows(DartsApiException.class, + () -> mediaApproveMarkForDeletionValidator.validate(mediaId)); + + // then + assertEquals(AudioApiError.TOO_MANY_RESULTS, exception.getError()); + } + + @Test + void validateMediaWhereObjectAdminActionIsAlreadyAuthorised() { + // given + Integer mediaId = 200; + var objectAdminAction = ObjectAdminActionTestData.minimalObjectAdminAction(); + objectAdminAction.setMarkedForManualDeletion(true); + when(objectAdminActionRepository.findByMedia_Id(mediaId)).thenReturn(List.of(objectAdminAction)); + + + // when + DartsApiException exception = assertThrows(DartsApiException.class, + () -> mediaApproveMarkForDeletionValidator.validate(mediaId)); + + // then + assertEquals(AudioApiError.MEDIA_ALREADY_MARKED_FOR_DELETION, exception.getError()); + } + + @Test + void validateMediaWhereObjectAdminActionHasNullHiddenReason() { + // given + Integer mediaId = 200; + var objectAdminAction = ObjectAdminActionTestData.minimalObjectAdminAction(); + objectAdminAction.setMarkedForManualDeletion(false); + objectAdminAction.setObjectHiddenReason(null); + when(objectAdminActionRepository.findByMedia_Id(mediaId)).thenReturn(List.of(objectAdminAction)); + + // when + DartsApiException exception = assertThrows(DartsApiException.class, + () -> mediaApproveMarkForDeletionValidator.validate(mediaId)); + + // then + assertEquals(AudioApiError.MEDIA_MARKED_FOR_DELETION_REASON_NOT_FOUND, exception.getError()); + } + + @Test + void validateMediaWhereObjectAdminActionApprovedBySameUserAsHidden() { + // given + Integer mediaId = 200; + var userAccount = UserAccountTestData.minimalUserAccount(); + userAccount.setId(123); + var objectAdminAction = ObjectAdminActionTestData.minimalObjectAdminAction(); + objectAdminAction.setMarkedForManualDeletion(false); + objectAdminAction.setHiddenBy(userAccount); + + var hiddenReason = ObjectHiddenReasonTestData.otherDelete(); + objectAdminAction.setObjectHiddenReason(hiddenReason); + + when(objectAdminActionRepository.findByMedia_Id(mediaId)).thenReturn(List.of(objectAdminAction)); + when(objectHiddenReasonRepository.findById(hiddenReason.getId())).thenReturn(Optional.of(hiddenReason)); + when(userIdentity.getUserAccount()).thenReturn(userAccount); + + // when + DartsApiException exception = assertThrows(DartsApiException.class, + () -> mediaApproveMarkForDeletionValidator.validate(mediaId)); + + // then + assertEquals(AudioApiError.USER_CANNOT_APPROVE_THEIR_OWN_DELETION, exception.getError()); + } + + @Test + void validateMediaSuccess() { + // given + Integer mediaId = 200; + var hiddenByUserAccount = UserAccountTestData.minimalUserAccount(); + hiddenByUserAccount.setId(123); + var objectAdminAction = ObjectAdminActionTestData.minimalObjectAdminAction(); + objectAdminAction.setMarkedForManualDeletion(false); + objectAdminAction.setHiddenBy(hiddenByUserAccount); + + var hiddenReason = ObjectHiddenReasonTestData.otherDelete(); + objectAdminAction.setObjectHiddenReason(hiddenReason); + + var authorisedByUserAccount = UserAccountTestData.minimalUserAccount(); + authorisedByUserAccount.setId(345); + + when(objectAdminActionRepository.findByMedia_Id(mediaId)).thenReturn(List.of(objectAdminAction)); + when(objectHiddenReasonRepository.findById(hiddenReason.getId())).thenReturn(Optional.of(hiddenReason)); + when(userIdentity.getUserAccount()).thenReturn(authorisedByUserAccount); + + // when then + assertDoesNotThrow(() -> mediaApproveMarkForDeletionValidator.validate(mediaId)); + + } + + +} \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/darts/audio/validator/MediaHideOrShowValidatorTest.java b/src/test/java/uk/gov/hmcts/darts/audio/validation/MediaHideOrShowValidatorTest.java similarity index 97% rename from src/test/java/uk/gov/hmcts/darts/audio/validator/MediaHideOrShowValidatorTest.java rename to src/test/java/uk/gov/hmcts/darts/audio/validation/MediaHideOrShowValidatorTest.java index 8f86b284a9..8b369be3c4 100644 --- a/src/test/java/uk/gov/hmcts/darts/audio/validator/MediaHideOrShowValidatorTest.java +++ b/src/test/java/uk/gov/hmcts/darts/audio/validation/MediaHideOrShowValidatorTest.java @@ -1,4 +1,4 @@ -package uk.gov.hmcts.darts.audio.validator; +package uk.gov.hmcts.darts.audio.validation; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -10,8 +10,6 @@ import uk.gov.hmcts.darts.audio.exception.AudioApiError; import uk.gov.hmcts.darts.audio.model.AdminActionRequest; import uk.gov.hmcts.darts.audio.model.MediaHideRequest; -import uk.gov.hmcts.darts.audio.validation.MediaHideOrShowValidator; -import uk.gov.hmcts.darts.audio.validation.MediaIdValidator; import uk.gov.hmcts.darts.common.entity.ObjectAdminActionEntity; import uk.gov.hmcts.darts.common.entity.ObjectHiddenReasonEntity; import uk.gov.hmcts.darts.common.exception.DartsApiException; @@ -132,7 +130,7 @@ void failWhenHideWithActionRequestWithDbAction() { Mockito.verify(mediaIdValidator, times(1)).validate(mediaId); } - + @Test void failWhenHideWithActionRequestAndWithoutCorrectReason() { Integer mediaId = 200; diff --git a/src/test/java/uk/gov/hmcts/darts/audio/validator/SearchMediaValidatorTest.java b/src/test/java/uk/gov/hmcts/darts/audio/validation/SearchMediaValidatorTest.java similarity index 95% rename from src/test/java/uk/gov/hmcts/darts/audio/validator/SearchMediaValidatorTest.java rename to src/test/java/uk/gov/hmcts/darts/audio/validation/SearchMediaValidatorTest.java index 18b83e80ab..2ab75a71df 100644 --- a/src/test/java/uk/gov/hmcts/darts/audio/validator/SearchMediaValidatorTest.java +++ b/src/test/java/uk/gov/hmcts/darts/audio/validation/SearchMediaValidatorTest.java @@ -1,10 +1,9 @@ -package uk.gov.hmcts.darts.audio.validator; +package uk.gov.hmcts.darts.audio.validation; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import uk.gov.hmcts.darts.audio.exception.AudioApiError; import uk.gov.hmcts.darts.audio.model.MediaSearchData; -import uk.gov.hmcts.darts.audio.validation.SearchMediaValidator; import uk.gov.hmcts.darts.common.exception.DartsApiException; import java.time.OffsetDateTime;