Skip to content

Commit

Permalink
Adds functionality to remove admin reference when deleted (#237)
Browse files Browse the repository at this point in the history
* Adds functionality to remove admin reference when deleted
  • Loading branch information
dylanwrightCO authored Mar 12, 2024
1 parent 7f217ba commit d892531
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;

Expand Down Expand Up @@ -238,8 +239,14 @@ public ResponseEntity<GenericErrorDTO> updateApplicationForm(HttpServletRequest
@GetMapping("/{applicationId}/lastUpdated/email")
@CheckSchemeOwnership
public ResponseEntity<String> getLastUpdatedEmail(@PathVariable final Integer applicationId) {
final Integer lastUpdatedBy = applicationFormService.getLastUpdatedBy(applicationId);
final Optional<GrantAdmin> grantAdmin = userService.getGrantAdminById(lastUpdatedBy);
final ApplicationFormEntity applicationForm = applicationFormService.getApplicationById(applicationId);

if (applicationForm.getLastUpdateBy() == null && applicationForm.getLastUpdated() != null) {
return ResponseEntity.ok("Deleted user");
}

final Optional<GrantAdmin> grantAdmin = userService.getGrantAdminById(Objects
.requireNonNull(applicationForm.getLastUpdateBy()));
if (grantAdmin.isEmpty()) {
return ResponseEntity.notFound().build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import gov.cabinetoffice.gap.adminbackend.models.AdminSession;
import gov.cabinetoffice.gap.adminbackend.models.JwtPayload;
import gov.cabinetoffice.gap.adminbackend.services.JwtService;
import gov.cabinetoffice.gap.adminbackend.services.SchemeService;
import gov.cabinetoffice.gap.adminbackend.services.TechSupportUserService;
import gov.cabinetoffice.gap.adminbackend.services.UserService;
import gov.cabinetoffice.gap.adminbackend.utils.HelperUtils;
Expand Down Expand Up @@ -53,6 +54,8 @@ public class UserController {

private final TechSupportUserService techSupportUserService;

private final SchemeService schemeService;

@Value("${feature.onelogin.enabled}")
private boolean oneLoginEnabled;

Expand Down Expand Up @@ -110,6 +113,11 @@ public ResponseEntity<String> deleteUser(@RequestParam Optional<String> oneLogin
return ResponseEntity.status(403).body("User not authorized to delete user: " + oneLoginSub);
}


String userSub = oneLoginSub.orElseGet(() -> colaSub.map(Object::toString).orElseThrow(() ->
new IllegalStateException("oneLoginSub and colaSub are not present")));

schemeService.removeAdminReference(userSub);
userService.deleteUser(oneLoginSub, colaSub);
return ResponseEntity.ok("User deleted successfully");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import gov.cabinetoffice.gap.adminbackend.entities.SchemeEntity;
import gov.cabinetoffice.gap.adminbackend.models.AdminSession;
import gov.cabinetoffice.gap.adminbackend.utils.HelperUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import javax.persistence.PrePersist;
Expand All @@ -21,10 +21,12 @@ private void beforeAnyUpdate(SchemeEntity scheme) {

Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
.ifPresent(authentication -> {
final AdminSession adminSession = (AdminSession) authentication.getPrincipal();
if (!authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ANONYMOUS"))) {
final AdminSession adminSession = (AdminSession) authentication.getPrincipal();

scheme.setLastUpdated(Instant.now());
scheme.setLastUpdatedBy(adminSession.getGrantAdminId());
scheme.setLastUpdated(Instant.now());
scheme.setLastUpdatedBy(adminSession.getGrantAdminId());
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import gov.cabinetoffice.gap.adminbackend.dtos.application.questions.*;
import gov.cabinetoffice.gap.adminbackend.dtos.schemes.SchemeDTO;
import gov.cabinetoffice.gap.adminbackend.entities.ApplicationFormEntity;
import gov.cabinetoffice.gap.adminbackend.entities.GrantAdmin;
import gov.cabinetoffice.gap.adminbackend.entities.SchemeEntity;
import gov.cabinetoffice.gap.adminbackend.entities.TemplateApplicationFormEntity;
import gov.cabinetoffice.gap.adminbackend.enums.ApplicationStatusEnum;
Expand Down Expand Up @@ -380,15 +381,28 @@ public void updateQuestionOrder(final Integer applicationId, final String sectio
save(applicationForm);
}

public Integer getLastUpdatedBy(Integer applicationId) {
public ApplicationFormEntity getApplicationById(Integer applicationId) {
return this.applicationFormRepository.findById(applicationId)
.orElseThrow(() -> new NotFoundException("Application with id " + applicationId + " does not exist"))
.getLastUpdateBy();
.orElseThrow(() -> new NotFoundException("Application with id " + applicationId + " does not exist"));
}

public ApplicationStatusEnum getApplicationStatus(Integer applicationId) {
return this.applicationFormRepository.findById(applicationId)
.orElseThrow(() -> new NotFoundException("Application with id " + applicationId + " does not exist"))
.getApplicationStatus();
}

public void removeAdminReferenceBySchemeId(GrantAdmin grantAdmin, Integer schemeId) {
applicationFormRepository.findByGrantSchemeId(schemeId)
.ifPresent(application -> {
if (Objects.equals(application.getLastUpdateBy(), grantAdmin.getId())) {
application.setLastUpdateBy(null);
}
if (Objects.equals(application.getCreatedBy(), grantAdmin.getId())) {
application.setCreatedBy(null);
}

applicationFormRepository.save(application);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -512,11 +512,13 @@ public GetGrantAdvertPublishingInformationResponseDTO getGrantAdvertPublishingIn
GetGrantAdvertPublishingInformationResponseDTO publishingInfo = this.grantAdvertMapper
.grantAdvertPublishInformationResponseDtoFromGrantAdvert(grantAdvert);

String adminSub = grantAdvert.getLastUpdatedBy().getGapUser().getUserSub();
if (grantAdvert.getLastUpdatedBy() != null) {
String adminSub = grantAdvert.getLastUpdatedBy().getGapUser().getUserSub();

String emailAddress = userService.getEmailAddressForSub(adminSub);
String emailAddress = userService.getEmailAddressForSub(adminSub);

publishingInfo.setLastUpdatedByEmail(emailAddress);
publishingInfo.setLastUpdatedByEmail(emailAddress);
}

return publishingInfo;
}
Expand Down Expand Up @@ -590,4 +592,18 @@ public void patchCreatedBy(Integer adminId, Integer schemeId) {
save(advert);
});
}

public void removeAdminReferenceBySchemeId(GrantAdmin grantAdmin, Integer schemeId) {
grantAdvertRepository.findBySchemeId(schemeId)
.ifPresent(advert -> {
if (advert.getLastUpdatedBy() == grantAdmin) {
advert.setLastUpdatedBy(null);
}
if (advert.getCreatedBy() == grantAdmin) {
advert.setCreatedBy(null);
}

grantAdvertRepository.save(advert);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityNotFoundException;
import javax.servlet.http.HttpSession;
Expand All @@ -36,6 +37,10 @@ public class SchemeService {

private final GrantAdminRepository grantAdminRepository;

private final GrantAdvertService grantAdvertService;

private final ApplicationFormService applicationFormService;

private final FeatureFlagsConfigurationProperties featureFlagsConfigurationProperties;

public SchemeDTO getSchemeBySchemeId(Integer schemeId) {
Expand Down Expand Up @@ -170,6 +175,30 @@ public void patchCreatedBy(GrantAdmin grantAdmin, Integer schemeId) {
this.schemeRepo.save(scheme);
}

@Transactional
public void removeAdminReference(String userSub) {
grantAdminRepository.findByGapUserUserSub(userSub).ifPresent(grantAdmin -> {

List<SchemeEntity> schemes = schemeRepo.findByGrantAdminsIdOrderByCreatedDateDesc(grantAdmin.getId());

for (SchemeEntity scheme: schemes) {

if (scheme.getLastUpdatedBy().equals(grantAdmin.getId())) {
scheme.setLastUpdatedBy(null);
}

scheme.removeAdmin(grantAdmin);
grantAdvertService.removeAdminReferenceBySchemeId(grantAdmin, scheme.getId());
applicationFormService.removeAdminReferenceBySchemeId(grantAdmin, scheme.getId());
}

schemeRepo.saveAll(schemes);
});


}


public List<SchemeDTO> getPaginatedOwnedSchemesByAdminId(int adminId, Pageable pagination) {
final List<SchemeEntity> schemes = this.schemeRepo
.findByCreatedByOrderByLastUpdatedDescCreatedDateDesc(adminId, pagination);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ public void migrateUser(final String oneLoginSub, final UUID colaSub) {
@Transactional
public void deleteUser(final Optional<String> oneLoginSubOptional, final Optional<UUID> colaSubOptional) {
// Deleting COLA and OneLogin subs as either could be stored against the user
oneLoginSubOptional.ifPresent(grantApplicantRepository::deleteByUserId);
oneLoginSubOptional.ifPresent(sub -> {
grantApplicantRepository.deleteByUserId(sub);
grantAdminRepository.deleteByGapUserUserSub(sub);
});

if (colaSubOptional.isPresent()) {
grantApplicantRepository.deleteByUserId(colaSubOptional.get().toString());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ALTER TABLE IF EXISTS public.grant_advert
ALTER COLUMN created_by DROP NOT NULL;

ALTER TABLE IF EXISTS public.grant_advert
ALTER COLUMN last_updated_by DROP NOT NULL;

ALTER TABLE IF EXISTS public.grant_application
ALTER COLUMN created_by DROP NOT NULL;
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -420,7 +421,8 @@ void updateApplicationForm_GenericApplicationFormException() throws Exception {
@Test
void getLastUpdatedEmailHappyPath() throws Exception {
when(userService.getEmailAddressForSub(anyString())).thenReturn("[email protected]");
when(applicationFormRepository.findById(anyInt())).thenReturn(Optional.of(ApplicationFormEntity.builder().lastUpdateBy(1).build()));
when(applicationFormService.getApplicationById(anyInt())).thenReturn(ApplicationFormEntity.builder()
.lastUpdateBy(1).build());
when(userService.getGrantAdminById(anyInt())).thenReturn(Optional.of(GrantAdmin.builder().gapUser(GapUser.builder().userSub("sub").build()).build()));

this.mockMvc.perform(get("/application-forms/1/lastUpdated/email")).andExpect(status().isOk())
Expand All @@ -429,15 +431,20 @@ void getLastUpdatedEmailHappyPath() throws Exception {
}

@Test
void getLastUpdatedEmailReturnsNotFoundWhenNoApplicationFound() throws Exception {
when(applicationFormRepository.findById(anyInt())).thenReturn(Optional.empty());
this.mockMvc.perform(get("/application-forms/1/lastUpdated/email")).andExpect(status().isNotFound());
void shouldReturnDeletedUserWhenLastUpdatedByIsNullAndLastUpdatedIsValid() throws Exception {
when(userService.getEmailAddressForSub(anyString())).thenReturn("[email protected]");
when(applicationFormService.getApplicationById(anyInt())).thenReturn(ApplicationFormEntity.builder()
.lastUpdated(Instant.now()).build());

this.mockMvc.perform(get("/application-forms/1/lastUpdated/email")).andExpect(status().isOk())
.andExpect(content().string("Deleted user"));

}

@Test
void getLastUpdatedEmailReturnsNotFoundWhenNoGrantAdminFound() throws Exception {
when(applicationFormRepository.findById(anyInt())).
thenReturn(Optional.of(ApplicationFormEntity.builder().lastUpdateBy(1).build()));
when(applicationFormService.getApplicationById(anyInt())).thenReturn(ApplicationFormEntity.builder()
.lastUpdateBy(1).build());
when(userService.getGrantAdminById(anyInt())).thenReturn(Optional.empty());
this.mockMvc.perform(get("/application-forms/1/lastUpdated/email")).andExpect(status().isNotFound());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import gov.cabinetoffice.gap.adminbackend.models.AdminSession;
import gov.cabinetoffice.gap.adminbackend.models.JwtPayload;
import gov.cabinetoffice.gap.adminbackend.services.JwtService;
import gov.cabinetoffice.gap.adminbackend.services.SchemeService;
import gov.cabinetoffice.gap.adminbackend.services.TechSupportUserService;
import gov.cabinetoffice.gap.adminbackend.services.UserService;
import gov.cabinetoffice.gap.adminbackend.utils.HelperUtils;
Expand Down Expand Up @@ -71,6 +72,9 @@ class UserControllerTest {
@MockBean
private UserServiceConfig userServiceConfig;

@MockBean
private SchemeService schemeService;

@MockBean
private TechSupportUserService techSupportService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -746,17 +746,18 @@ void getLastUpdatedByByReturnsLastUpdatedByForApplication() {
Mockito.when(ApplicationFormServiceTest.this.applicationFormRepository.findById(1))
.thenReturn(Optional.of(testApplicationFormEntity));

Integer lastUpdatedBy = ApplicationFormServiceTest.this.applicationFormService.getLastUpdatedBy(1);
ApplicationFormEntity applicationForm = ApplicationFormServiceTest.this.applicationFormService
.getApplicationById(1);

assertThat(lastUpdatedBy).isEqualTo(2);
assertThat(applicationForm).isEqualTo(testApplicationFormEntity);
}

@Test
void getLastUpdatedByReturnsNFEIfNoApplicationFound() {
Mockito.when(ApplicationFormServiceTest.this.applicationFormRepository.findById(1))
.thenReturn(Optional.empty());

assertThatThrownBy(() -> ApplicationFormServiceTest.this.applicationFormService.getLastUpdatedBy(1)).isInstanceOf(NotFoundException.class)
assertThatThrownBy(() -> ApplicationFormServiceTest.this.applicationFormService.getApplicationById(1)).isInstanceOf(NotFoundException.class)
.hasMessage("Application with id 1 does not exist");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,16 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.json.JSONObject;

import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.*;
import static org.mockito.Mockito.*;

import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.web.reactive.function.client.WebClient;
Expand All @@ -50,7 +55,7 @@
class GrantAdvertServiceTest {

@Mock
private GrantAdvertRepository grantAdvertRepository;
GrantAdvertRepository grantAdvertRepository;

@Mock
private GrantAdminRepository grantAdminRepository;
Expand Down Expand Up @@ -1294,6 +1299,22 @@ void scheduleGrantAdvert_NotFound() {

}

@Test
void testRemoveAdminReferenceBySchemeId() {
GrantAdmin grantAdmin = GrantAdmin.builder().id(SAMPLE_SCHEME_ID).build();


GrantAdvert grantAdvert = RandomGrantAdvertGenerators.randomGrantAdvertEntity().build();


when(grantAdvertRepository.findBySchemeId(anyInt())).thenReturn(Optional.of(grantAdvert));

grantAdvertService.removeAdminReferenceBySchemeId(grantAdmin, 1);

verify(grantAdvertRepository).save(grantAdvert);
}


@Test
void patchCreatedByUpdatesGrantAdvert() {
final UUID grantAdvertId = UUID.fromString("5b30cb45-7339-466a-a700-270c3983c604");
Expand Down
Loading

0 comments on commit d892531

Please sign in to comment.