diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/CustomAttributesController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/CustomEntityAttributesDefinitionsController.java similarity index 80% rename from backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/CustomAttributesController.java rename to backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/CustomEntityAttributesDefinitionsController.java index 31d6ca809..86aeb90ed 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/CustomAttributesController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/CustomEntityAttributesDefinitionsController.java @@ -17,21 +17,21 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import edu.internet2.tier.shibboleth.admin.ui.domain.CustomAttributeDefinition; +import edu.internet2.tier.shibboleth.admin.ui.domain.CustomEntityAttributeDefinition; import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; -import edu.internet2.tier.shibboleth.admin.ui.service.CustomAttributesService; +import edu.internet2.tier.shibboleth.admin.ui.service.CustomEntityAttributesDefinitionService; @Controller -@RequestMapping(value = "/api/custom") -public class CustomAttributesController { +@RequestMapping(value = "/api/custom/entity") +public class CustomEntityAttributesDefinitionsController { @Autowired - private CustomAttributesService caService; + private CustomEntityAttributesDefinitionService caService; @PostMapping("/attribute") @Transactional - public ResponseEntity create(@RequestBody CustomAttributeDefinition definition) { + public ResponseEntity create(@RequestBody CustomEntityAttributeDefinition definition) { // If already defined, we can't create a new one, nor will this call update the definition - CustomAttributeDefinition cad = caService.find(definition.getName()); + CustomEntityAttributeDefinition cad = caService.find(definition.getName()); if (cad != null) { HttpHeaders headers = new HttpHeaders(); @@ -42,14 +42,14 @@ public ResponseEntity create(@RequestBody CustomAttributeDefinition definitio String.format("The custom attribute definition with name: [%s] already exists.", definition.getName()))); } - CustomAttributeDefinition result = caService.createOrUpdateDefinition(definition); + CustomEntityAttributeDefinition result = caService.createOrUpdateDefinition(definition); return ResponseEntity.status(HttpStatus.CREATED).body(result); } @PutMapping("/attribute") @Transactional - public ResponseEntity update(@RequestBody CustomAttributeDefinition definition) { - CustomAttributeDefinition cad = caService.find(definition.getName()); + public ResponseEntity update(@RequestBody CustomEntityAttributeDefinition definition) { + CustomEntityAttributeDefinition cad = caService.find(definition.getName()); if (cad == null) { HttpHeaders headers = new HttpHeaders(); headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/custom/attribute").build().toUri()); @@ -59,7 +59,7 @@ public ResponseEntity update(@RequestBody CustomAttributeDefinition definitio String.format("The custom attribute definition with name: [%s] does not already exist.", definition.getName()))); } - CustomAttributeDefinition result = caService.createOrUpdateDefinition(definition); + CustomEntityAttributeDefinition result = caService.createOrUpdateDefinition(definition); return ResponseEntity.ok(result); } @@ -72,7 +72,7 @@ public ResponseEntity getAll() { @GetMapping("/attribute/{name}") @Transactional(readOnly = true) public ResponseEntity getOne(@PathVariable String name) { - CustomAttributeDefinition cad = caService.find(name); + CustomEntityAttributeDefinition cad = caService.find(name); if (cad == null) { HttpHeaders headers = new HttpHeaders(); headers.setLocation( @@ -88,7 +88,7 @@ public ResponseEntity getOne(@PathVariable String name) { @DeleteMapping("/attribute/{name}") @Transactional public ResponseEntity delete(@PathVariable String name) { - CustomAttributeDefinition cad = caService.find(name); + CustomEntityAttributeDefinition cad = caService.find(name); if (cad == null) { HttpHeaders headers = new HttpHeaders(); headers.setLocation( diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/CustomAttributeDefinition.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/CustomEntityAttributeDefinition.java similarity index 77% rename from backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/CustomAttributeDefinition.java rename to backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/CustomEntityAttributeDefinition.java index 03b9db95d..b2be0f503 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/CustomAttributeDefinition.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/CustomEntityAttributeDefinition.java @@ -14,10 +14,10 @@ import lombok.Data; -@Entity(name = "custom_attribute_definition") +@Entity(name = "custom_entity_attribute_definition") @Audited @Data -public class CustomAttributeDefinition { +public class CustomEntityAttributeDefinition { @Id @Column(nullable = false) String name; @@ -32,7 +32,7 @@ public class CustomAttributeDefinition { String defaultValue; @ElementCollection - @CollectionTable(name = "custom_attr_list_defs", joinColumns = @JoinColumn(name = "name")) + @CollectionTable(name = "custom_entity_attr_list_items", joinColumns = @JoinColumn(name = "name")) @Column(name = "value", nullable = false) Set customAttrListDefinitions = new HashSet<>(); @@ -40,5 +40,5 @@ public class CustomAttributeDefinition { } enum CustomAttributeType { - BOOLEAN, INTEGER, LONG, DOUBLE, DURATION, SELECTION_LIST, SPRING_BEAN_ID + STRING, BOOLEAN, INTEGER, LONG, DOUBLE, DURATION, SELECTION_LIST, SPRING_BEAN_ID } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/CustomAttributeRepository.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/CustomAttributeRepository.java deleted file mode 100644 index 3470e9834..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/CustomAttributeRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.repository; - -import java.util.List; - -import org.springframework.data.jpa.repository.JpaRepository; - -import edu.internet2.tier.shibboleth.admin.ui.domain.CustomAttributeDefinition; - -/** - * Repository to manage {@link CustomAttributeDefinition} instances. - */ -public interface CustomAttributeRepository extends JpaRepository { - - List findAll(); - - CustomAttributeDefinition findByName(String name); - - @SuppressWarnings("unchecked") - CustomAttributeDefinition save(CustomAttributeDefinition attribute); -} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/CustomEntityAttributeDefinitionRepository.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/CustomEntityAttributeDefinitionRepository.java new file mode 100644 index 000000000..677d7cf87 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/CustomEntityAttributeDefinitionRepository.java @@ -0,0 +1,20 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import edu.internet2.tier.shibboleth.admin.ui.domain.CustomEntityAttributeDefinition; + +/** + * Repository to manage {@link CustomEntityAttributeDefinition} instances. + */ +public interface CustomEntityAttributeDefinitionRepository extends JpaRepository { + + List findAll(); + + CustomEntityAttributeDefinition findByName(String name); + + @SuppressWarnings("unchecked") + CustomEntityAttributeDefinition save(CustomEntityAttributeDefinition attribute); +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomAttributesService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomAttributesService.java deleted file mode 100644 index 6e2436bdf..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomAttributesService.java +++ /dev/null @@ -1,17 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.service; - -import java.util.List; - -import edu.internet2.tier.shibboleth.admin.ui.domain.CustomAttributeDefinition; - -public interface CustomAttributesService { - - CustomAttributeDefinition createOrUpdateDefinition(CustomAttributeDefinition definition); - - void deleteDefinition(CustomAttributeDefinition definition); - - CustomAttributeDefinition find(String name); - - List getAllDefinitions(); - -} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomAttributesServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomAttributesServiceImpl.java deleted file mode 100644 index 1dba4dae5..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomAttributesServiceImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.service; - -import java.util.List; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import edu.internet2.tier.shibboleth.admin.ui.domain.CustomAttributeDefinition; -import edu.internet2.tier.shibboleth.admin.ui.repository.CustomAttributeRepository; - -@Service -public class CustomAttributesServiceImpl implements CustomAttributesService { - @Autowired - private CustomAttributeRepository repository; - - @Override - public CustomAttributeDefinition createOrUpdateDefinition(CustomAttributeDefinition definition) { - return repository.save(definition); - } - - @Override - public void deleteDefinition(CustomAttributeDefinition definition) { - repository.delete(definition); - } - - @Override - public CustomAttributeDefinition find(String name) { - return repository.findByName(name); - } - - @Override - public List getAllDefinitions() { - return repository.findAll(); - } - -} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomEntityAttributesDefinitionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomEntityAttributesDefinitionService.java new file mode 100644 index 000000000..4087ad221 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomEntityAttributesDefinitionService.java @@ -0,0 +1,17 @@ +package edu.internet2.tier.shibboleth.admin.ui.service; + +import java.util.List; + +import edu.internet2.tier.shibboleth.admin.ui.domain.CustomEntityAttributeDefinition; + +public interface CustomEntityAttributesDefinitionService { + + CustomEntityAttributeDefinition createOrUpdateDefinition(CustomEntityAttributeDefinition definition); + + void deleteDefinition(CustomEntityAttributeDefinition definition); + + CustomEntityAttributeDefinition find(String name); + + List getAllDefinitions(); + +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomEntityAttributesDefinitionServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomEntityAttributesDefinitionServiceImpl.java new file mode 100644 index 000000000..506bf4e44 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomEntityAttributesDefinitionServiceImpl.java @@ -0,0 +1,36 @@ +package edu.internet2.tier.shibboleth.admin.ui.service; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import edu.internet2.tier.shibboleth.admin.ui.domain.CustomEntityAttributeDefinition; +import edu.internet2.tier.shibboleth.admin.ui.repository.CustomEntityAttributeDefinitionRepository; + +@Service +public class CustomEntityAttributesDefinitionServiceImpl implements CustomEntityAttributesDefinitionService { + @Autowired + private CustomEntityAttributeDefinitionRepository repository; + + @Override + public CustomEntityAttributeDefinition createOrUpdateDefinition(CustomEntityAttributeDefinition definition) { + return repository.save(definition); + } + + @Override + public void deleteDefinition(CustomEntityAttributeDefinition definition) { + repository.delete(definition); + } + + @Override + public CustomEntityAttributeDefinition find(String name) { + return repository.findByName(name); + } + + @Override + public List getAllDefinitions() { + return repository.findAll(); + } + +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/CustomAttributeRepositoryTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/CustomEntityAttributeDefinitionRepositoryTests.groovy similarity index 62% rename from backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/CustomAttributeRepositoryTests.groovy rename to backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/CustomEntityAttributeDefinitionRepositoryTests.groovy index f9af4b2a4..2601d4d42 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/CustomAttributeRepositoryTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/CustomEntityAttributeDefinitionRepositoryTests.groovy @@ -9,7 +9,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories import org.springframework.test.context.ContextConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration -import edu.internet2.tier.shibboleth.admin.ui.domain.CustomAttributeDefinition +import edu.internet2.tier.shibboleth.admin.ui.domain.CustomEntityAttributeDefinition import spock.lang.Specification /** @@ -20,18 +20,78 @@ import spock.lang.Specification @ContextConfiguration(classes=[InternationalizationConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") -class CustomAttributeRepositoryTests extends Specification { +class CustomEntityAttributeDefinitionRepositoryTests extends Specification { @Autowired - CustomAttributeRepository repo + CustomEntityAttributeDefinitionRepository repo @Autowired EntityManager entityManager + def "simple create test"() { + given: + def ca = new CustomEntityAttributeDefinition().with { + it.name = "ca-name" + it.attributeType = "STRING" + it.defaultValue = "foo" + it + } + + // Confirm empty state + when: + def atts = repo.findAll() + + then: + atts.size() == 0 + + // save check + when: + repo.save(ca) + entityManager.flush() + entityManager.clear() + + then: + // save check + def cas = repo.findAll() + cas.size() == 1 + def caFromDb1 = cas.get(0).asType(CustomEntityAttributeDefinition) + caFromDb1.equals(ca) == true + + // fetch checks + repo.findByName("not a name") == null + repo.findByName("ca-name").equals(ca) + } + + def "expected error"() { + given: + def ca = new CustomEntityAttributeDefinition().with { + it.name = "ca-name" + it.defaultValue = "foo" + it + } + + // Confirm empty state + when: + def atts = repo.findAll() + + then: + atts.size() == 0 + + // save check + when: + repo.save(ca) + entityManager.flush() + entityManager.clear() + + then: + // Missing non-nullable field should thrown error + final def exception = thrown(javax.persistence.PersistenceException) + } + def "basic CRUD operations validated"() { given: def setItems = new HashSet(["val1", "val2", "val3"]) - def ca = new CustomAttributeDefinition().with { + def ca = new CustomEntityAttributeDefinition().with { it.name = "ca-name" it.attributeType = "SELECTION_LIST" it.customAttrListDefinitions = setItems @@ -55,7 +115,7 @@ class CustomAttributeRepositoryTests extends Specification { // save check def cas = repo.findAll() cas.size() == 1 - def caFromDb1 = cas.get(0).asType(CustomAttributeDefinition) + def caFromDb1 = cas.get(0).asType(CustomEntityAttributeDefinition) caFromDb1.equals(ca) == true // fetch checks @@ -76,13 +136,13 @@ class CustomAttributeRepositoryTests extends Specification { then: def cas2 = repo.findAll() cas2.size() == 1 - def caFromDb2 = cas2.get(0).asType(CustomAttributeDefinition) + def caFromDb2 = cas2.get(0).asType(CustomEntityAttributeDefinition) caFromDb2.equals(ca) == false caFromDb2.equals(caFromDb1) == true // delete tests when: - def delByName = new CustomAttributeDefinition().with { + def delByName = new CustomEntityAttributeDefinition().with { it.name = "ca-name" it } @@ -99,19 +159,19 @@ class CustomAttributeRepositoryTests extends Specification { def setItems2 = new HashSet(["val2", "val1"]) def setItems3 = new HashSet(["val1", "val2", "val3"]) def setItems4 = new HashSet(["val1", "val2", "val3", "val4"]) - def ca2 = new CustomAttributeDefinition().with { + def ca2 = new CustomEntityAttributeDefinition().with { it.name = "ca-name" it.attributeType = "SELECTION_LIST" it.customAttrListDefinitions = setItems2 it } - def ca3 = new CustomAttributeDefinition().with { + def ca3 = new CustomEntityAttributeDefinition().with { it.name = "ca-name" it.attributeType = "SELECTION_LIST" it.customAttrListDefinitions = setItems3 it } - def ca4 = new CustomAttributeDefinition().with { + def ca4 = new CustomEntityAttributeDefinition().with { it.name = "ca-name" it.attributeType = "SELECTION_LIST" it.customAttrListDefinitions = setItems4 @@ -126,7 +186,7 @@ class CustomAttributeRepositoryTests extends Specification { then: def cas = repo.findAll() cas.size() == 1 - def caFromDb = cas.get(0).asType(CustomAttributeDefinition) + def caFromDb = cas.get(0).asType(CustomEntityAttributeDefinition) caFromDb.equals(ca3) == true // now update the attribute list items @@ -138,7 +198,7 @@ class CustomAttributeRepositoryTests extends Specification { entityManager.flush() entityManager.clear() - def caFromDb4 = repo.findAll().get(0).asType(CustomAttributeDefinition) + def caFromDb4 = repo.findAll().get(0).asType(CustomEntityAttributeDefinition) caFromDb4.equals(ca4) == true // now remove items @@ -150,7 +210,7 @@ class CustomAttributeRepositoryTests extends Specification { entityManager.flush() entityManager.clear() - def caFromDb2 = repo.findAll().get(0).asType(CustomAttributeDefinition) + def caFromDb2 = repo.findAll().get(0).asType(CustomEntityAttributeDefinition) caFromDb2.equals(ca2) == true } } \ No newline at end of file