diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleController.java index ca1c18af5..e438b77ae 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleController.java @@ -1,7 +1,9 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; import edu.internet2.tier.shibboleth.admin.ui.domain.AttributeBundle; +import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; +import edu.internet2.tier.shibboleth.admin.ui.security.exception.GroupDeleteException; import edu.internet2.tier.shibboleth.admin.ui.security.exception.GroupExistsConflictException; import edu.internet2.tier.shibboleth.admin.ui.security.model.Group; import edu.internet2.tier.shibboleth.admin.ui.service.AttributeBundleService; @@ -11,7 +13,9 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.access.annotation.Secured; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -37,7 +41,13 @@ public ResponseEntity create(@RequestBody AttributeBundle bundle) throws Obje return ResponseEntity.status(HttpStatus.CREATED).body(result); } - //DELETE + @Secured("ROLE_ADMIN") + @DeleteMapping("/{resourceId}") + @Transactional + public ResponseEntity delete(@PathVariable String resourceId) throws EntityNotFoundException { + attributeBundleService.deleteDefinition(resourceId); + return ResponseEntity.noContent().build(); + } //PUT } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/AttributeBundleService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/AttributeBundleService.java index f77983e92..15611a8b1 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/AttributeBundleService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/AttributeBundleService.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.service; import edu.internet2.tier.shibboleth.admin.ui.domain.AttributeBundle; +import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; import edu.internet2.tier.shibboleth.admin.ui.repository.AttributeBundleRepository; import org.springframework.beans.factory.annotation.Autowired; @@ -23,4 +24,11 @@ public AttributeBundle create(AttributeBundle bundle) throws ObjectIdExistsExcep public List findAll() { return attributeBundleRepository.findAll(); } + + public void deleteDefinition(String resourceId) throws EntityNotFoundException { + if (attributeBundleRepository.findByResourceId(resourceId).isEmpty()) { + throw new EntityNotFoundException(String.format("Unable to find attribute bundle with resource id: [%s] for deletion", resourceId)); + } + attributeBundleRepository.deleteById(resourceId); + } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/BundleableAttributeTypeValueSerializer.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/BundleableAttributeTypeValueSerializer.java index 32a7b7cc8..55aa1ab44 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/BundleableAttributeTypeValueSerializer.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/BundleableAttributeTypeValueSerializer.java @@ -10,8 +10,7 @@ /** * This simplifies translation to the front end. We use the ENUM on the backend, but the BundleableAttributeType * is tagged to serialize using this helper. - * Note: The deserialize is done naturally by setting spring.jackson.mapper.accept-case-insensitive-enums=true in - * the application.properties and by the setup of the ENUM itself + * Note: The deserialize is done by the setup of the ENUM itself */ public class BundleableAttributeTypeValueSerializer extends StdSerializer { public BundleableAttributeTypeValueSerializer() { diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleControllerTests.groovy index af0b428e7..a9180071f 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleControllerTests.groovy @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.MapperFeature import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.configuration.ShibUIConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.AttributeBundle +import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException import edu.internet2.tier.shibboleth.admin.ui.repository.AttributeBundleRepository import edu.internet2.tier.shibboleth.admin.ui.service.AttributeBundleService @@ -22,6 +23,7 @@ import spock.lang.Specification import static org.hamcrest.CoreMatchers.containsString import static org.hamcrest.Matchers.containsInAnyOrder import static org.springframework.http.MediaType.APPLICATION_JSON +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content @@ -127,6 +129,40 @@ class AttributeBundleControllerTests extends Specification { .andExpect(jsonPath("\$.attributes", containsInAnyOrder("eduPersonPrincipalName", "surname", "givenName"))) } + def "test delete" () { + expect: + attributeBundleRepository.findAll().isEmpty() + + when: + def json = """ + { + "name": "bundleName", + "resourceId": "randomIDVal", + "attributes": ["eduPersonPrincipalName", "surname", "givenName"] + } + """ + AttributeBundle bundle = objectMapper.readValue(json, AttributeBundle.class) + attributeBundleRepository.save(bundle) + + then: + attributeBundleRepository.findAll().size() == 1 + + // Delete something doesn't exist + try { + mockMvc.perform(delete("/api/custom/entity/bundles/randomIDValdoesntexist")) + false + } catch (NestedServletException expected) { + expected instanceof EntityNotFoundException + } + + when: "Delete what does exist" + def result = mockMvc.perform(delete("/api/custom/entity/bundles/randomIDVal")) + + then: + result.andExpect(status().isNoContent()) + attributeBundleRepository.findAll().isEmpty() + } + // can go away with merge to develop and this extends the base test class @TestConfiguration private static class ABCTConfig { diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/AttributeBundleRepositoryTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/AttributeBundleRepositoryTests.groovy index 148cceda8..e1c23c70a 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/AttributeBundleRepositoryTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/AttributeBundleRepositoryTests.groovy @@ -17,7 +17,7 @@ import spock.lang.Specification @ContextConfiguration(classes = [ShibUIConfiguration]) class AttributeBundleRepositoryTests extends Specification { @Autowired - AttributeBundleRepository abRepo + AttributeBundleRepository attributeBundleRepository ObjectMapper objectMapper = new ObjectMapper().with { it.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS) @@ -37,7 +37,7 @@ class AttributeBundleRepositoryTests extends Specification { AttributeBundle bundle = objectMapper.readValue(json, AttributeBundle.class) when: - def result = abRepo.save(bundle) + def result = attributeBundleRepository.save(bundle) then: result == bundle