From cdb469757e58d6d2e60437635988c901e945754c Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 5 Jun 2018 14:21:24 -0400 Subject: [PATCH 01/11] SHIBUI-518[535]: Jpa model work in progress --- .../DynamicMetadataResolverAttributes.java | 47 +++++++++++++++++++ .../LocalDynamicMetadataResolver.java | 23 +++++++++ 2 files changed, 70 insertions(+) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicMetadataResolverAttributes.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicMetadataResolverAttributes.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicMetadataResolverAttributes.java new file mode 100644 index 000000000..830d06a50 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicMetadataResolverAttributes.java @@ -0,0 +1,47 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Embeddable; + +@Embeddable +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@EqualsAndHashCode +public class DynamicMetadataResolverAttributes { + + private String parserPoolRef; + + private String taskTimerRef; + + private Double refreshDelayFactor; + + private String minCacheDuration; + + private String maxCacheDuration; + + private String maxIdleEntityData; + + private Boolean removeIdleEntityData; + + private String cleanupTaskInterval; + + private String persistentCacheManagerRef; + + private String persistentCacheManagerDirectory; + + private String persistentCacheKeyGeneratorRef; + + private Boolean initializeFromPersistentCacheInBackground; + + private String backgroundInitializationFromCacheDelay; + + private String initializationFromCachePredicateRef; + +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java new file mode 100644 index 000000000..1376c1f45 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java @@ -0,0 +1,23 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import javax.persistence.Embedded; +import javax.persistence.Entity; + +@Entity +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Getter +@Setter +@ToString +public class LocalDynamicMetadataResolver extends MetadataResolver { + + @Embedded + private DynamicMetadataResolverAttributes dynamicMetadataResolverAttributes; + +} From 1f6ee8ce8491fec38778726ed1434f074e9fe308 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 5 Jun 2018 14:24:32 -0400 Subject: [PATCH 02/11] SHIBUI-518[535] model wip --- .../ui/domain/resolvers/LocalDynamicMetadataResolver.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java index 1376c1f45..63ec78eb5 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java @@ -17,6 +17,12 @@ @ToString public class LocalDynamicMetadataResolver extends MetadataResolver { + private String sourceDirectory; + + private String sourceManagerRef; + + private String sourceKeyGeneratorRef; + @Embedded private DynamicMetadataResolverAttributes dynamicMetadataResolverAttributes; From dce23feab121b421d9c508989ced11c77b47a8eb Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 5 Jun 2018 15:54:52 -0400 Subject: [PATCH 03/11] SHIBUI-518[535]: JPA repository and tests --- ...ocalDynamicMetadataResolverRepository.java | 16 ++++ ...HttpMetadataResolverRepositoryTests.groovy | 2 +- ...amicMetadataResolverRepositoryTests.groovy | 84 +++++++++++++++++++ 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepository.java create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepositoryTests.groovy diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepository.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepository.java new file mode 100644 index 000000000..323b470d5 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepository.java @@ -0,0 +1,16 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository; + +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver; +import org.springframework.data.repository.CrudRepository; + +/** + * Spring Data CRUD repository for instances of {@link LocalDynamicMetadataResolver}s. + */ +public interface LocalDynamicMetadataResolverRepository extends CrudRepository { + + LocalDynamicMetadataResolver findByName(String name); + + boolean deleteByResourceId(String resourceId); + + LocalDynamicMetadataResolver findByResourceId(String resourceId); +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepositoryTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepositoryTests.groovy index b497a711f..a3103e29b 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepositoryTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepositoryTests.groovy @@ -54,7 +54,7 @@ class FileBackedHttpMetadataResolverRepositoryTests extends Specification { it.metadataFilters.add(new EntityAttributesFilter().with { it.entityAttributesFilterTarget = new EntityAttributesFilterTarget().with { it.entityAttributesFilterTargetType = ENTITY - it.setSingleValue(["hola"]) + it.setValue(["hola"]) it } it diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepositoryTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepositoryTests.groovy new file mode 100644 index 000000000..b68260455 --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepositoryTests.groovy @@ -0,0 +1,84 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository + +import com.fasterxml.jackson.databind.ObjectMapper +import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.MetadataResolverConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicMetadataResolverAttributes +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.domain.EntityScan +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.ContextConfiguration +import spock.lang.Specification + +import javax.persistence.EntityManager + +import static edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget.EntityAttributesFilterTargetType.ENTITY +import static edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes.HttpCachingType.memory + +@DataJpaTest +@ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration, MetadataResolverConfiguration]) +@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) +@EntityScan("edu.internet2.tier.shibboleth.admin.ui") +@DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) +class LocalDynamicMetadataResolverRepositoryTests extends Specification { + + @Autowired + LocalDynamicMetadataResolverRepository repositoryUnderTest + + @Autowired + EntityManager entityManager + + def "local dynamic metadata resolver instances persist OK"() { + when: + def mdr = new LocalDynamicMetadataResolver().with { + it.name = 'LocalDynamicMetadataResolver' + it.sourceDirectory = '/etc/shibui' + it.sourceKeyGeneratorRef = 'sourceKeyGeneratorBean' + it.sourceManagerRef = 'sourceManagerBean' + it.dynamicMetadataResolverAttributes = new DynamicMetadataResolverAttributes().with { + it.cleanupTaskInterval = 'PT5H' + it.maxCacheDuration = 'PT8H' + it.initializeFromPersistentCacheInBackground = true + it + } + + it.metadataFilters.add(new EntityAttributesFilter().with { + it.entityAttributesFilterTarget = new EntityAttributesFilterTarget().with { + it.entityAttributesFilterTargetType = ENTITY + it.setValue(['hola']) + it + } + it + }) + + it + } + repositoryUnderTest.save(mdr) + + then: + repositoryUnderTest.findAll().size() > 0 + def item = repositoryUnderTest.findByName("LocalDynamicMetadataResolver") + + item.name == "LocalDynamicMetadataResolver" + item.metadataFilters.size() == 1 + item.metadataFilters[0].entityAttributesFilterTarget.entityAttributesFilterTargetType == ENTITY + item.metadataFilters[0].entityAttributesFilterTarget.value.size() == 1 + item.metadataFilters[0].entityAttributesFilterTarget.value.get(0) == "hola" + item.sourceDirectory == '/etc/shibui' + item.sourceKeyGeneratorRef == 'sourceKeyGeneratorBean' + item.sourceManagerRef == 'sourceManagerBean' + item.dynamicMetadataResolverAttributes.cleanupTaskInterval == 'PT5H' + item.dynamicMetadataResolverAttributes.maxCacheDuration == 'PT8H' + item.dynamicMetadataResolverAttributes.initializeFromPersistentCacheInBackground + } + +} From 572b8a0b3d76472d4de19e74604dc39e418724f8 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 5 Jun 2018 16:01:01 -0400 Subject: [PATCH 04/11] SHIBUI-518[535]: polishing --- .../LocalDynamicMetadataResolverRepositoryTests.groovy | 5 ----- 1 file changed, 5 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepositoryTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepositoryTests.groovy index b68260455..027b9c030 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepositoryTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/LocalDynamicMetadataResolverRepositoryTests.groovy @@ -1,16 +1,12 @@ package edu.internet2.tier.shibboleth.admin.ui.repository -import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.MetadataResolverConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicMetadataResolverAttributes -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest @@ -22,7 +18,6 @@ import spock.lang.Specification import javax.persistence.EntityManager import static edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget.EntityAttributesFilterTargetType.ENTITY -import static edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes.HttpCachingType.memory @DataJpaTest @ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration, MetadataResolverConfiguration]) From 27a38e8762df13fcd2761f60f6aab5646b74f3af Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 5 Jun 2018 17:18:15 -0700 Subject: [PATCH 05/11] [SHIBUI-518] First pass at controller. Tests to follow. --- ...ocalDynamicMetadataProviderController.java | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/LocalDynamicMetadataProviderController.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/LocalDynamicMetadataProviderController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/LocalDynamicMetadataProviderController.java new file mode 100644 index 000000000..2d3a104ee --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/LocalDynamicMetadataProviderController.java @@ -0,0 +1,110 @@ +package edu.internet2.tier.shibboleth.admin.ui.controller; + +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver; +import edu.internet2.tier.shibboleth.admin.ui.repository.LocalDynamicMetadataResolverRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +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.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import java.net.URI; + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +@RestController +@RequestMapping("/api/MetadataProvider/LocalDynamic") +public class LocalDynamicMetadataProviderController { + private static final Logger logger = LoggerFactory.getLogger(LocalDynamicMetadataProviderController.class); + + @Autowired + LocalDynamicMetadataResolverRepository repository; + + @DeleteMapping("/{resourceId}") + public ResponseEntity deleteByResourceId(@PathVariable String resourceId) { + if (repository.deleteByResourceId(resourceId)) { + return ResponseEntity.accepted().build(); + } else { + return ResponseEntity.notFound().build(); + } + } + + @GetMapping("/name/{metadataProviderName}") + @Transactional(readOnly = true) + public ResponseEntity getOneByName(@PathVariable String metadataProviderName) { + LocalDynamicMetadataResolver resolver = repository.findByName(metadataProviderName); + if (resolver == null) { + return ResponseEntity.notFound().build(); + } else { + resolver.setVersion(resolver.hashCode()); + return ResponseEntity.ok(resolver); + } + } + + @GetMapping("/{resourceId}") + @Transactional(readOnly = true) + public ResponseEntity getOneByResourceId(@PathVariable String resourceId) { + LocalDynamicMetadataResolver resolver = repository.findByResourceId(resourceId); + if (resolver == null) { + return ResponseEntity.notFound().build(); + } else { + resolver.setVersion(resolver.hashCode()); + return ResponseEntity.ok(resolver); + } + } + + @PostMapping + public ResponseEntity create(@RequestBody LocalDynamicMetadataResolver resolver) { + if (repository.findByName(resolver.getName()) != null) { + return ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + + LocalDynamicMetadataResolver persistedResolver = repository.save(resolver); + persistedResolver.setVersion(persistedResolver.hashCode()); + + return ResponseEntity + .created(getResourceUriFor(persistedResolver)) + .body(persistedResolver); + } + + @PutMapping + public ResponseEntity update(@RequestBody LocalDynamicMetadataResolver resolver) { + LocalDynamicMetadataResolver existingResolver = repository.findByResourceId(resolver.getResourceId()); + + if (existingResolver == null) { + return ResponseEntity.notFound().build(); + } + + if (existingResolver.hashCode() != resolver.getVersion()) { + logger.info("Comparing: " + existingResolver.hashCode() + " with " + resolver.getVersion()); + return ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + + resolver.setAudId(existingResolver.getAudId()); + //TODO: Do we need to set anything else? dates? + + LocalDynamicMetadataResolver updatedResolver = repository.save(resolver); + updatedResolver.setVersion(updatedResolver.hashCode()); + + return ResponseEntity.ok(updatedResolver); + } + + private static URI getResourceUriFor(LocalDynamicMetadataResolver resolver) { + return ServletUriComponentsBuilder + .fromCurrentServletMapping().path("/api/MetadataProvider/LocalDynamic/") + .pathSegment(resolver.getResourceId()) + .build() + .toUri(); + } +} From 64c021e4a34a0ec1e9c5c9b8c5ab93b2b7a1f295 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Wed, 6 Jun 2018 16:45:44 -0700 Subject: [PATCH 06/11] [SHIBUI-518] Tests for LocalDynamicMetadataProviderController. --- ...amicMetadataProviderControllerTests.groovy | 275 ++++++++++++++++++ .../admin/ui/util/TestObjectGenerator.groovy | 42 +++ 2 files changed, 317 insertions(+) create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/LocalDynamicMetadataProviderControllerTests.groovy diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/LocalDynamicMetadataProviderControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/LocalDynamicMetadataProviderControllerTests.groovy new file mode 100644 index 000000000..bc13df607 --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/LocalDynamicMetadataProviderControllerTests.groovy @@ -0,0 +1,275 @@ +package edu.internet2.tier.shibboleth.admin.ui.controller + +import com.fasterxml.jackson.databind.ObjectMapper +import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.MetadataResolverConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration +import edu.internet2.tier.shibboleth.admin.ui.repository.LocalDynamicMetadataResolverRepository +import edu.internet2.tier.shibboleth.admin.ui.util.RandomGenerator +import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator +import edu.internet2.tier.shibboleth.admin.util.AttributeUtility +import groovy.json.JsonOutput +import groovy.json.JsonSlurper +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.domain.EntityScan +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import spock.lang.Specification + +import static org.hamcrest.CoreMatchers.containsString +import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8 +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.* +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.* + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +@DataJpaTest +@ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration, MetadataResolverConfiguration]) +@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) +@EntityScan("edu.internet2.tier.shibboleth.admin.ui") +class LocalDynamicMetadataProviderControllerTests extends Specification { + RandomGenerator randomGenerator + TestObjectGenerator testObjectGenerator + ObjectMapper mapper + + def repository = Mock(LocalDynamicMetadataResolverRepository) + def controller + def mockMvc + + @Autowired + AttributeUtility attributeUtility + + def setup() { + randomGenerator = new RandomGenerator() + testObjectGenerator = new TestObjectGenerator(attributeUtility) + mapper = new ObjectMapper() + + controller = new LocalDynamicMetadataProviderController ( + repository: repository + ) + + mockMvc = MockMvcBuilders.standaloneSetup(controller).build() + } + + def "DELETE deletes the desired resolver"() { + given: + def randomResourceId = randomGenerator.randomId() + + 1 * repository.deleteByResourceId(randomResourceId) >> true + + when: + def result = mockMvc.perform( + delete("/api/MetadataProvider/LocalDynamic/$randomResourceId")) + + then: + result.andExpect(status().isAccepted()) + } + + def "DELETE returns error when desired resolver is not found"() { + given: + def randomResourceId = randomGenerator.randomId() + + 1 * repository.deleteByResourceId(randomResourceId) >> false + + when: + def result = mockMvc.perform( + delete("/api/MetadataProvider/LocalDynamic/$randomResourceId")) + + then: + result.andExpect(status().isNotFound()) + } + + def "POST a new resolver properly persists and returns the new persisted resolver"() { + given: + def resolver = testObjectGenerator.buildLocalDynamicMetadataResolver() + resolver.version = resolver.hashCode() + def postedJsonBody = mapper.writeValueAsString(resolver) + + 1 * repository.findByName(resolver.getName()) >> null + 1 * repository.save(_) >> resolver + + def expectedResolverUUID = resolver.getResourceId() + def expectedResponseHeader = 'Location' + def expectedResponseHeaderValue = "/api/MetadataProvider/LocalDynamic/$expectedResolverUUID" + + when: + def result = mockMvc.perform( + post('/api/MetadataProvider/LocalDynamic') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + result.andExpect(status().isCreated()) + .andExpect(content().json(postedJsonBody, false)) + .andExpect(header().string(expectedResponseHeader, containsString(expectedResponseHeaderValue))) + } + + def "POST a new resolver that has a name of a persisted resolver returns conflict"() { + given: + def resolver = testObjectGenerator.buildLocalDynamicMetadataResolver() + resolver.version = resolver.hashCode() + def postedJsonBody = mapper.writeValueAsString(resolver) + + 1 * repository.findByName(resolver.name) >> resolver + 0 * repository.save(_) + + when: + def result = mockMvc.perform( + post('/api/MetadataProvider/LocalDynamic') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + result.andExpect(status().isConflict()) + } + + def "GET by resourceId returns the desired persisted resolver"() { + given: + def resolver = testObjectGenerator.buildLocalDynamicMetadataResolver() + resolver.version = resolver.hashCode() + def resolverJson = mapper.writeValueAsString(resolver) + def resolverId = resolver.resourceId + + 1 * repository.findByResourceId(resolverId) >> resolver + + def expectedResponseContentType = APPLICATION_JSON_UTF8 + + when: + def result = mockMvc.perform( + get("/api/MetadataProvider/LocalDynamic/$resolverId")) + + then: + result.andExpect(status().isOk()) + .andExpect(content().contentType(expectedResponseContentType)) + .andExpect(content().json(resolverJson, false)) + } + + def "GET by unknown resource id returns not found"() { + given: + def randomResourceId = randomGenerator.randomId() + + 1 * repository.findByResourceId(randomResourceId) >> null + + when: + def result = mockMvc.perform( + get("/api/MetadataProvider/LocalDynamic/$randomResourceId")) + + then: + result.andExpect(status().isNotFound()) + } + + def "GET by resolver name returns the desired persisted resolver"() { + given: + def resolver = testObjectGenerator.buildLocalDynamicMetadataResolver() + resolver.version = resolver.hashCode() + def resolverName = resolver.name + def resolverJson = mapper.writeValueAsString(resolver) + + 1 * repository.findByName(resolverName) >> resolver + + def expectedResponseContentType = APPLICATION_JSON_UTF8 + + when: + def result = mockMvc.perform( + get("/api/MetadataProvider/LocalDynamic/name/$resolverName")) + + then: + result.andExpect(status().isOk()) + .andExpect(content().contentType(expectedResponseContentType)) + .andExpect(content().json(resolverJson, false)) + } + + def "GET by unknown resolver name returns not found"() { + given: + def randomResolverName = randomGenerator.randomString(10) + + 1 * repository.findByName(randomResolverName) >> null + + when: + def result = mockMvc.perform( + get("/api/MetadataProvider/LocalDynamic/name/$randomResolverName")) + + then: + result.andExpect(status().isNotFound()) + } + + def "PUT allows for a successful update of an already-persisted resolver"() { + given: + def existingResolver = testObjectGenerator.buildLocalDynamicMetadataResolver() + existingResolver.version = existingResolver.hashCode() + def resourceId = existingResolver.resourceId + def updatedResolver = testObjectGenerator.buildLocalDynamicMetadataResolver() + updatedResolver.setResourceId(resourceId) + updatedResolver.setVersion(existingResolver.hashCode()) + def postedJsonBody = mapper.writeValueAsString(updatedResolver) + + 1 * repository.findByResourceId(resourceId) >> existingResolver + 1 * repository.save(_) >> updatedResolver + + def expectedResponseContentType = APPLICATION_JSON_UTF8 + + when: + def result = mockMvc.perform( + put('/api/MetadataProvider/LocalDynamic') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + def expectedJson = new JsonSlurper().parseText(postedJsonBody) + expectedJson << [version: updatedResolver.hashCode()] + result.andExpect(status().isOk()) + .andExpect(content().contentType(expectedResponseContentType)) + .andExpect(content().json(JsonOutput.toJson(expectedJson), false)) + } + + def "PUT of an updated resolver with an incorrect version returns a conflict"() { + given: + def existingResolver = testObjectGenerator.buildLocalDynamicMetadataResolver() + existingResolver.version = existingResolver.hashCode() + def resourceId = existingResolver.resourceId + + def updatedResolver = testObjectGenerator.buildLocalDynamicMetadataResolver() + updatedResolver.resourceId = resourceId + updatedResolver.version = updatedResolver.hashCode() + def postedJsonBody = mapper.writeValueAsString(updatedResolver) + + 1 * repository.findByResourceId(resourceId) >> existingResolver + 0 * repository.save(_) + + when: + def result = mockMvc.perform( + put('/api/MetadataProvider/LocalDynamic') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + result.andExpect(status().isConflict()) + } + + def "PUT of a resolver that is not persisted returns not found"() { + given: + def existingResolver = testObjectGenerator.buildLocalDynamicMetadataResolver() + existingResolver.version = existingResolver.hashCode() + def resourceId = existingResolver.resourceId + + def updatedResolver = testObjectGenerator.buildLocalDynamicMetadataResolver() + updatedResolver.resourceId = resourceId + updatedResolver.version = updatedResolver.hashCode() + def postedJsonBody = mapper.writeValueAsString(updatedResolver) + + 1 * repository.findByResourceId(resourceId) >> null + 0 * repository.save(_) + + when: + def result = mockMvc.perform( + put('/api/MetadataProvider/LocalDynamic') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + result.andExpect(status().isNotFound()) + } +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy index fce929b75..cd5026ede 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy @@ -14,6 +14,8 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterTargetRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.RelyingPartyOverridesRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicMetadataResolverAttributes +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver import edu.internet2.tier.shibboleth.admin.util.AttributeUtility import edu.internet2.tier.shibboleth.admin.util.MDDCConstants import org.opensaml.saml.saml2.metadata.Organization @@ -33,6 +35,46 @@ class TestObjectGenerator { this.attributeUtility = attributeUtility } + LocalDynamicMetadataResolver buildLocalDynamicMetadataResolver() { + def resolver = new LocalDynamicMetadataResolver().with { + it.dynamicMetadataResolverAttributes = buildDynamicMetadataResolverAttributes() + it.sourceDirectory = generator.randomString(10) + it.sourceKeyGeneratorRef = generator.randomString(10) + it.sourceManagerRef = generator.randomString(10) + it.failFastInitialization = generator.randomBoolean() + it.name = generator.randomString(10) + it.requireValidMetadata = generator.randomBoolean() + it.useDefaultPredicateRegistry = generator.randomBoolean() + it.criterionPredicateRegistryRef = generator.randomString(10) + it.satisfyAnyPredicates = generator.randomBoolean() + it.sortKey = generator.randomInt(1, 10) + it.metadataFilters = buildAllTypesOfFilterList() + it + } + return resolver + } + + DynamicMetadataResolverAttributes buildDynamicMetadataResolverAttributes() { + def attributes = new DynamicMetadataResolverAttributes().with { + it.backgroundInitializationFromCacheDelay = generator.randomString(10) + it.cleanupTaskInterval = generator.randomString(10) + it.initializationFromCachePredicateRef = generator.randomString(10) + it.initializeFromPersistentCacheInBackground = generator.randomBoolean() + it.maxCacheDuration = generator.randomString(5) + it.maxIdleEntityData = generator.randomString(5) + it.minCacheDuration = generator.randomString(5) + it.parserPoolRef = generator.randomString(10) + it.persistentCacheKeyGeneratorRef = generator.randomString(10) + it.persistentCacheManagerDirectory = generator.randomString(10) + it.persistentCacheManagerRef = generator.randomString(10) + it.refreshDelayFactor = generator.randomInt(1, 5) + it.removeIdleEntityData = generator.randomBoolean() + it.taskTimerRef = generator.randomString() + it + } + attributes + } + List buildAllTypesOfFilterList() { List filterList = new ArrayList<>() (1..generator.randomInt(4, 10)).each { From 801184580ac49a4be795daecec364b254cda8b53 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Thu, 7 Jun 2018 16:08:49 -0700 Subject: [PATCH 07/11] [SHIBUI-519] First pass at entity, repository, and controller for DynamicHttpMetadataProvider/Resolver --- ...DynamicHttpMetadataProviderController.java | 111 +++++++ .../DynamicHttpMetadataResolver.java | 39 +++ .../HttpMetadataResolverAttributes.java | 2 +- ...DynamicHttpMetadataResolverRepository.java | 18 ++ ...HttpMetadataProviderControllerTests.groovy | 271 ++++++++++++++++++ .../admin/ui/util/TestObjectGenerator.groovy | 48 ++++ 6 files changed, 488 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/DynamicHttpMetadataProviderController.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicHttpMetadataResolver.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/DynamicHttpMetadataResolverRepository.java create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/DynamicHttpMetadataProviderControllerTests.groovy diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/DynamicHttpMetadataProviderController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/DynamicHttpMetadataProviderController.java new file mode 100644 index 000000000..866f54231 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/DynamicHttpMetadataProviderController.java @@ -0,0 +1,111 @@ +package edu.internet2.tier.shibboleth.admin.ui.controller; + +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver; +import edu.internet2.tier.shibboleth.admin.ui.repository.DynamicHttpMetadataResolverRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +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.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import java.net.URI; + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +@RestController +@RequestMapping("/api/MetadataProvider/DynamicHttp") +public class DynamicHttpMetadataProviderController { + private static final Logger logger = LoggerFactory.getLogger(DynamicHttpMetadataProviderController.class); + + @Autowired + DynamicHttpMetadataResolverRepository repository; + + @DeleteMapping("/{resourceId}") + public ResponseEntity deleteByResourceId(@PathVariable String resourceId) { + if (repository.deleteByResourceId(resourceId)) { + return ResponseEntity.accepted().build(); + } else { + return ResponseEntity.notFound().build(); + } + } + + @GetMapping("/name/{metadataProviderName}") + @Transactional(readOnly = true) + public ResponseEntity getOneByName(@PathVariable String metadataProviderName) { + DynamicHttpMetadataResolver resolver = repository.findByName(metadataProviderName); + if (resolver == null) { + return ResponseEntity.notFound().build(); + } else { + resolver.setVersion(resolver.hashCode()); + return ResponseEntity.ok(resolver); + } + } + + @GetMapping("/{resourceId}") + @Transactional(readOnly = true) + public ResponseEntity getOneByResourceId(@PathVariable String resourceId) { + DynamicHttpMetadataResolver resolver = repository.findByResourceId(resourceId); + if (resolver == null) { + return ResponseEntity.notFound().build(); + } else { + resolver.setVersion(resolver.hashCode()); + return ResponseEntity.ok(resolver); + } + } + + @PostMapping + public ResponseEntity create(@RequestBody DynamicHttpMetadataResolver resolver) { + if (repository.findByName(resolver.getName()) != null) { + return ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + + DynamicHttpMetadataResolver persistedResolver = repository.save(resolver); + persistedResolver.setVersion(persistedResolver.hashCode()); + + return ResponseEntity + .created(getResourceUriFor(persistedResolver)) + .body(persistedResolver); + } + + @PutMapping + public ResponseEntity update(@RequestBody DynamicHttpMetadataResolver resolver) { + DynamicHttpMetadataResolver existingResolver = repository.findByResourceId(resolver.getResourceId()); + + if (existingResolver == null) { + return ResponseEntity.notFound().build(); + } + + if (existingResolver.hashCode() != resolver.getVersion()) { + logger.info("Comparing: " + existingResolver.hashCode() + " with " + resolver.getVersion()); + return ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + + resolver.setAudId(existingResolver.getAudId()); + //TODO: Do we need to set anything else? dates? + + DynamicHttpMetadataResolver updatedResolver = repository.save(resolver); + updatedResolver.setVersion(updatedResolver.hashCode()); + + return ResponseEntity.ok(updatedResolver); + } + + private static URI getResourceUriFor(DynamicHttpMetadataResolver resolver) { + return ServletUriComponentsBuilder + .fromCurrentServletMapping().path("/api/MetadataProvider/DynamicHttp/") + .pathSegment(resolver.getResourceId()) + .build() + .toUri(); + } + +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicHttpMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicHttpMetadataResolver.java new file mode 100644 index 000000000..886839bf8 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicHttpMetadataResolver.java @@ -0,0 +1,39 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import javax.persistence.ElementCollection; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.OrderColumn; +import java.util.List; + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +@Entity +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Getter +@Setter +@ToString +public class DynamicHttpMetadataResolver extends MetadataResolver { + + @Embedded + private DynamicMetadataResolverAttributes dynamicMetadataResolverAttributes; + + @Embedded + private HttpMetadataResolverAttributes httpMetadataResolverAttributes; + + private int maxConnectionsTotal; + + private int maxConnectionsPerRoute; + + @ElementCollection + @OrderColumn + private List supportedContentTypes; +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/HttpMetadataResolverAttributes.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/HttpMetadataResolverAttributes.java index 437516ffd..f8612a60f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/HttpMetadataResolverAttributes.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/HttpMetadataResolverAttributes.java @@ -52,7 +52,7 @@ public class HttpMetadataResolverAttributes { private Integer httpMaxCacheEntrySize; - private enum HttpCachingType { + public enum HttpCachingType { none,file,memory } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/DynamicHttpMetadataResolverRepository.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/DynamicHttpMetadataResolverRepository.java new file mode 100644 index 000000000..c4a08804f --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/DynamicHttpMetadataResolverRepository.java @@ -0,0 +1,18 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository; + +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver; +import org.springframework.data.repository.CrudRepository; + +/** + * Spring Data CRUD repository for instances of {@link DynamicHttpMetadataResolver}s. + * + * @author Bill Smith (wsmith@unicon.net) + */ +public interface DynamicHttpMetadataResolverRepository extends CrudRepository { + + DynamicHttpMetadataResolver findByName(String name); + + boolean deleteByResourceId(String resourceId); + + DynamicHttpMetadataResolver findByResourceId(String resourceId); +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/DynamicHttpMetadataProviderControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/DynamicHttpMetadataProviderControllerTests.groovy new file mode 100644 index 000000000..bf4ce2ffe --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/DynamicHttpMetadataProviderControllerTests.groovy @@ -0,0 +1,271 @@ +package edu.internet2.tier.shibboleth.admin.ui.controller + +import com.fasterxml.jackson.databind.ObjectMapper +import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.MetadataResolverConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration +import edu.internet2.tier.shibboleth.admin.ui.repository.DynamicHttpMetadataResolverRepository +import edu.internet2.tier.shibboleth.admin.ui.util.RandomGenerator +import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator +import edu.internet2.tier.shibboleth.admin.util.AttributeUtility +import groovy.json.JsonOutput +import groovy.json.JsonSlurper +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.domain.EntityScan +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import spock.lang.Specification + +import static org.hamcrest.CoreMatchers.containsString +import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8 +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.* +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.* + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +@DataJpaTest +@ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration, MetadataResolverConfiguration]) +@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) +@EntityScan("edu.internet2.tier.shibboleth.admin.ui") +class DynamicHttpMetadataProviderControllerTests extends Specification { + RandomGenerator randomGenerator + TestObjectGenerator testObjectGenerator + ObjectMapper mapper + + def repository = Mock(DynamicHttpMetadataResolverRepository) + def controller + def mockMvc + + @Autowired + AttributeUtility attributeUtility + + def setup() { + randomGenerator = new RandomGenerator() + testObjectGenerator = new TestObjectGenerator(attributeUtility) + mapper = new ObjectMapper() + + controller = new DynamicHttpMetadataProviderController ( + repository: repository + ) + + mockMvc = MockMvcBuilders.standaloneSetup(controller).build() + } + + def "DELETE deletes the desired resolver"() { + given: + def randomResourceId = randomGenerator.randomId() + + 1 * repository.deleteByResourceId(randomResourceId) >> true + + when: + def result = mockMvc.perform( + delete("/api/MetadataProvider/DynamicHttp/$randomResourceId")) + + then: + result.andExpect(status().isAccepted()) + } + + def "DELETE returns error when desired resolver is not found"() { + given: + def randomResourceId = randomGenerator.randomId() + + 1 * repository.deleteByResourceId(randomResourceId) >> false + + when: + def result = mockMvc.perform( + delete("/api/MetadataProvider/DynamicHttp/$randomResourceId")) + + then: + result.andExpect(status().isNotFound()) + } + + def "POST a new resolver properly persists and returns the new persisted resolver"() { + given: + def resolver = testObjectGenerator.buildDynamicHttpMetadataResolver() + resolver.setVersion(resolver.hashCode()) + def postedJsonBody = mapper.writeValueAsString(resolver) + + 1 * repository.findByName(resolver.getName()) >> null + 1 * repository.save(_) >> resolver + + def expectedResolverUUID = resolver.getResourceId() + def expectedResponseHeader = 'Location' + def expectedResponseHeaderValue = "/api/MetadataProvider/DynamicHttp/$expectedResolverUUID" + + when: + def result = mockMvc.perform( + post('/api/MetadataProvider/DynamicHttp') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + result.andExpect(status().isCreated()) + .andExpect(content().json(postedJsonBody, false)) + .andExpect(header().string(expectedResponseHeader, containsString(expectedResponseHeaderValue))) + + } + + def "POST a new resolver that has a name of a persisted resolver returns conflict"() { + given: + def resolver = testObjectGenerator.buildDynamicHttpMetadataResolver() + def resolverName = resolver.name + def postedJsonBody = mapper.writeValueAsString(resolver) + + 1 * repository.findByName(resolverName) >> resolver + 0 * repository.save(_) + + when: + def result = mockMvc.perform( + post('/api/MetadataProvider/DynamicHttp') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + result.andExpect(status().isConflict()) + } + + def "GET by resourceId returns the desired persisted resolver"() { + given: + def resolver = testObjectGenerator.buildDynamicHttpMetadataResolver() + resolver.version = resolver.hashCode() + def resourceId = resolver.resourceId + def resolverJson = mapper.writeValueAsString(resolver) + + 1 * repository.findByResourceId(resourceId) >> resolver + + def expectedResponseContentType = APPLICATION_JSON_UTF8 + + when: + def result = mockMvc.perform( + get("/api/MetadataProvider/DynamicHttp/$resourceId")) + + then: + result.andExpect(status().isOk()) + .andExpect(content().contentType(expectedResponseContentType)) + .andExpect(content().json(resolverJson, false)) + } + + def "GET by unknown resource id returns not found"() { + given: + def randomResourceId = randomGenerator.randomId() + + 1 * repository.findByResourceId(randomResourceId) >> null + + when: + def result = mockMvc.perform( + get("/api/MetadataProvider/DynamicHttp/$randomResourceId")) + + then: + result.andExpect(status().isNotFound()) + } + + def "GET by resolver name returns the desired persisted resolver"() { + given: + def resolver = testObjectGenerator.buildDynamicHttpMetadataResolver() + resolver.version = resolver.hashCode() + def resolverName = resolver.name + def resolverJson = mapper.writeValueAsString(resolver) + + 1 * repository.findByName(resolverName) >> resolver + + def expectedResponseContentType = APPLICATION_JSON_UTF8 + + when: + def result = mockMvc.perform( + get("/api/MetadataProvider/DynamicHttp/name/$resolverName")) + + then: + result.andExpect(status().isOk()) + .andExpect(content().contentType(expectedResponseContentType)) + .andExpect(content().json(resolverJson, false)) + } + + def "GET by unknown resolver name returns not found"() { + given: + def randomResolverName = randomGenerator.randomString(10) + + 1 * repository.findByName(randomResolverName) >> null + + when: + def result = mockMvc.perform( + get("/api/MetadataProvider/DynamicHttp/name/$randomResolverName")) + + then: + result.andExpect(status().isNotFound()) + } + + def "PUT allows for a successful update of an already-persisted resolver"() { + given: + def existingResolver = testObjectGenerator.buildDynamicHttpMetadataResolver() + existingResolver.version = existingResolver.hashCode() + def resourceId = existingResolver.resourceId + def existingResolverJson = mapper.writeValueAsString(existingResolver) + + def updatedResolver = testObjectGenerator.buildDynamicHttpMetadataResolver() + updatedResolver.resourceId = existingResolver.resourceId + updatedResolver.version = existingResolver.version + def postedJsonBody = mapper.writeValueAsString(updatedResolver) + + 1 * repository.findByResourceId(existingResolver.resourceId) >> existingResolver + 1 * repository.save(_) >> updatedResolver + + def expectedResponseContentType = APPLICATION_JSON_UTF8 + + when: + def result = mockMvc.perform( + put('/api/MetadataProvider/DynamicHttp') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + def expectedJson = new JsonSlurper().parseText(postedJsonBody) + expectedJson << [version: updatedResolver.hashCode()] + result.andExpect(status().isOk()) + .andExpect(content().contentType(expectedResponseContentType)) + .andExpect(content().json(JsonOutput.toJson(expectedJson), false)) + } + + def "PUT of an updated resolver with an incorrect version returns a conflict"() { + given: + def existingResolver = testObjectGenerator.buildDynamicHttpMetadataResolver() + existingResolver.version = existingResolver.hashCode() + + def updatedResolver = testObjectGenerator.buildDynamicHttpMetadataResolver() + updatedResolver.resourceId = existingResolver.resourceId + updatedResolver.version = updatedResolver.hashCode() + def postedJsonBody = mapper.writeValueAsString(updatedResolver) + + 1 * repository.findByResourceId(existingResolver.resourceId) >> existingResolver + 0 * repository.save(_) + + when: + def result = mockMvc.perform( + put('/api/MetadataProvider/DynamicHttp') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + result.andExpect(status().isConflict()) + } + + def "PUT of a resolver that is not persisted returns not found"() { + given: + def resolver = testObjectGenerator.buildDynamicHttpMetadataResolver() + def postedJsonBody = mapper.writeValueAsString(resolver) + + 1 * repository.findByResourceId(resolver.resourceId) >> null + 0 * repository.save(_) + + when: + def result = mockMvc.perform( + put('/api/MetadataProvider/DynamicHttp') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + result.andExpect(status().isNotFound()) + } +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy index cd5026ede..cea76c233 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy @@ -14,7 +14,9 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterTargetRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.RelyingPartyOverridesRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicMetadataResolverAttributes +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver import edu.internet2.tier.shibboleth.admin.util.AttributeUtility import edu.internet2.tier.shibboleth.admin.util.MDDCConstants @@ -35,6 +37,52 @@ class TestObjectGenerator { this.attributeUtility = attributeUtility } + DynamicHttpMetadataResolver buildDynamicHttpMetadataResolver() { + def resolver = new DynamicHttpMetadataResolver().with { + it.dynamicMetadataResolverAttributes = buildDynamicMetadataResolverAttributes() + it.httpMetadataResolverAttributes = buildHttpMetadataResolverAttributes() + it.maxConnectionsPerRoute = generator.randomInt(1, 100) + it.maxConnectionsTotal = generator.randomInt(1, 100) + it.supportedContentTypes = generator.randomStringList() + it.name = generator.randomString(10) + it.requireValidMetadata = generator.randomBoolean() + it.failFastInitialization = generator.randomBoolean() + it.sortKey = generator.randomInt(1, 10) + it.criterionPredicateRegistryRef = generator.randomString(10) + it.useDefaultPredicateRegistry = generator.randomBoolean() + it.satisfyAnyPredicates = generator.randomBoolean() + it.metadataFilters = buildAllTypesOfFilterList() + it + } + return resolver + } + + HttpMetadataResolverAttributes buildHttpMetadataResolverAttributes() { + def attributes = new HttpMetadataResolverAttributes().with { + it.disregardTLSCertificate = generator.randomBoolean() + it.connectionRequestTimeout = generator.randomString(10) + it.httpClientRef = generator.randomString(10) + it.httpCacheDirectory = generator.randomString(10) + it.httpCaching = randomHttpCachingType() + it.httpClientSecurityParametersRef = generator.randomString(10) + it.httpMaxCacheEntries = generator.randomInt(1, 10) + it.httpMaxCacheEntrySize = generator.randomInt(100, 10000) + it.proxyHost = generator.randomString(10) + it.proxyPassword = generator.randomString(10) + it.proxyPort = generator.randomString(5) + it.proxyUser = generator.randomString(10) + it.requestTimeout = generator.randomString(10) + it.socketTimeout = generator.randomString(10) + it.tlsTrustEngineRef = generator.randomString(10) + it + } + return attributes + } + + HttpMetadataResolverAttributes.HttpCachingType randomHttpCachingType() { + HttpMetadataResolverAttributes.HttpCachingType.values()[generator.randomInt(0, 2)] + } + LocalDynamicMetadataResolver buildLocalDynamicMetadataResolver() { def resolver = new LocalDynamicMetadataResolver().with { it.dynamicMetadataResolverAttributes = buildDynamicMetadataResolverAttributes() From e63f9805490427daf6319eccb5d0445d4ec6b8be Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Mon, 11 Jun 2018 09:49:23 -0700 Subject: [PATCH 08/11] [SHIBUI-519] constructXmlNode WIP --- .../JPAMetadataResolverServiceImpl.groovy | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy index 5ba9620ff..97c146ad3 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy @@ -3,6 +3,7 @@ package edu.internet2.tier.shibboleth.admin.ui.service; import com.google.common.base.Predicate; import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter; import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import groovy.xml.DOMBuilder @@ -135,4 +136,42 @@ public class JPAMetadataResolverServiceImpl implements MetadataResolverService { return DOMBuilder.newInstance().parseText(writer.toString()) } } + + void constructXmlNodeFor(LocalDynamicMetadataResolver resolver, def markupBuilderDelegate) { + markupBuilderDelegate.MetadataProvider(id: resolver.name, + 'xsi:type': 'LocalDynamicMetadataProvider', + backingFile: resolver.backingFile, + metadataURL: resolver.metadataURL, + initializeFromBackupFile: !resolver.initializeFromBackupFile ?: null, + backupFileInitNextRefreshDelay: resolver.backupFileInitNextRefreshDelay, + requireValidMetadata: !resolver.requireValidMetadata ?: null, + failFastInitialization: !resolver.failFastInitialization ?: null, + sortKey: resolver.sortKey, + criterionPredicateRegistryRef: resolver.criterionPredicateRegistryRef, + useDefaultPredicateRegistry: !resolver.useDefaultPredicateRegistry ?: null, + satisfyAnyPredicates: resolver.satisfyAnyPredicates ?: null, + + parserPoolRef: resolver.reloadableMetadataResolverAttributes?.parserPoolRef, + minRefreshDelay: resolver.reloadableMetadataResolverAttributes?.minRefreshDelay, + maxRefreshDelay: resolver.reloadableMetadataResolverAttributes?.maxRefreshDelay, + refreshDelayFactor: resolver.reloadableMetadataResolverAttributes?.refreshDelayFactor, + indexesRef: resolver.reloadableMetadataResolverAttributes?.indexesRef, + resolveViaPredicatesOnly: resolver.reloadableMetadataResolverAttributes?.resolveViaPredicatesOnly ?: null, + expirationWarningThreshold: resolver.reloadableMetadataResolverAttributes?.expirationWarningThreshold, + + httpClientRef: resolver.httpMetadataResolverAttributes?.httpClientRef, + connectionRequestTimeout: resolver.httpMetadataResolverAttributes?.connectionRequestTimeout, + connectionTimeout: resolver.httpMetadataResolverAttributes?.connectionTimeout, + socketTimeout: resolver.httpMetadataResolverAttributes?.socketTimeout, + disregardTLSCertificate: resolver.httpMetadataResolverAttributes?.disregardTLSCertificate ?: null, + httpClientSecurityParametersRef: resolver.httpMetadataResolverAttributes?.httpClientSecurityParametersRef, + proxyHost: resolver.httpMetadataResolverAttributes?.proxyHost, + proxyPort: resolver.httpMetadataResolverAttributes?.proxyHost, + proxyUser: resolver.httpMetadataResolverAttributes?.proxyUser, + proxyPassword: resolver.httpMetadataResolverAttributes?.proxyPassword, + httpCaching: resolver.httpMetadataResolverAttributes?.httpCaching, + httpCacheDirectory: resolver.httpMetadataResolverAttributes?.httpCacheDirectory, + httpMaxCacheEntries: resolver.httpMetadataResolverAttributes?.httpMaxCacheEntries, + httpMaxCacheEntrySize: resolver.httpMetadataResolverAttributes?.httpMaxCacheEntrySize) + } } From c5ad998dccbf8beee1d95b0fff543fb0af7e081a Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Mon, 11 Jun 2018 13:54:48 -0700 Subject: [PATCH 09/11] [SHIBUI-519] constructXMLNodeFor DynamicHttpMetadataResolver WIP. --- .../JPAMetadataResolverServiceImpl.groovy | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy index 97c146ad3..f8ea4ffc5 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy @@ -3,6 +3,7 @@ package edu.internet2.tier.shibboleth.admin.ui.service; import com.google.common.base.Predicate; import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter; import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository @@ -137,13 +138,9 @@ public class JPAMetadataResolverServiceImpl implements MetadataResolverService { } } - void constructXmlNodeFor(LocalDynamicMetadataResolver resolver, def markupBuilderDelegate) { + void constructXmlNodeFor(DynamicHttpMetadataResolver resolver, def markupBuilderDelegate) { markupBuilderDelegate.MetadataProvider(id: resolver.name, - 'xsi:type': 'LocalDynamicMetadataProvider', - backingFile: resolver.backingFile, - metadataURL: resolver.metadataURL, - initializeFromBackupFile: !resolver.initializeFromBackupFile ?: null, - backupFileInitNextRefreshDelay: resolver.backupFileInitNextRefreshDelay, + 'xsi:type': 'DynamicHttpMetadataProvider', requireValidMetadata: !resolver.requireValidMetadata ?: null, failFastInitialization: !resolver.failFastInitialization ?: null, sortKey: resolver.sortKey, @@ -151,14 +148,25 @@ public class JPAMetadataResolverServiceImpl implements MetadataResolverService { useDefaultPredicateRegistry: !resolver.useDefaultPredicateRegistry ?: null, satisfyAnyPredicates: resolver.satisfyAnyPredicates ?: null, - parserPoolRef: resolver.reloadableMetadataResolverAttributes?.parserPoolRef, - minRefreshDelay: resolver.reloadableMetadataResolverAttributes?.minRefreshDelay, - maxRefreshDelay: resolver.reloadableMetadataResolverAttributes?.maxRefreshDelay, - refreshDelayFactor: resolver.reloadableMetadataResolverAttributes?.refreshDelayFactor, - indexesRef: resolver.reloadableMetadataResolverAttributes?.indexesRef, - resolveViaPredicatesOnly: resolver.reloadableMetadataResolverAttributes?.resolveViaPredicatesOnly ?: null, - expirationWarningThreshold: resolver.reloadableMetadataResolverAttributes?.expirationWarningThreshold, - + parserPoolRef: resolver.dynamicMetadataResolverAttributes?.parserPoolRef, + taskTimerRef: resolver.dynamicMetadataResolverAttributes?.taskTimerRef, + refreshDelayFactor: resolver.dynamicMetadataResolverAttributes?.refreshDelayFactor, + minCacheDuration: resolver.dynamicMetadataResolverAttributes?.minCacheDuration, + maxCacheDuration: resolver.dynamicMetadataResolverAttributes?.maxCacheDuration, + maxIdleEntityData: resolver.dynamicMetadataResolverAttributes?.maxIdleEntityData, + removeIdleEntityData: !resolver.dynamicMetadataResolverAttributes?.removeIdleEntityData ?: null, + cleanupTaskInterval: resolver.dynamicMetadataResolverAttributes?.cleanupTaskInterval, + persistentCacheManagerRef: resolver.dynamicMetadataResolverAttributes?.persistentCacheManagerRef, + persistentCacheManagerDirectory: resolver.dynamicMetadataResolverAttributes?.persistentCacheManagerDirectory, + persistentCacheKeyGeneratorRef: resolver.dynamicMetadataResolverAttributes?.persistentCacheKeyGeneratorRef, + initializeFromPersistentCacheInBackground: !resolver.dynamicMetadataResolverAttributes?.initializeFromPersistentCacheInBackground ?: null, + backgroundInitializationFromCacheDelay: resolver.dynamicMetadataResolverAttributes?.backgroundInitializationFromCacheDelay, + initializationFromCachePredicateRef: resolver.dynamicMetadataResolverAttributes?.initializationFromCachePredicateRef, + + maxConnectionsTotal: resolver.maxConnectionsTotal, + maxConnectionsPerRoute: resolver.maxConnectionsPerRoute, + supportedContentTypes: resolver.supportedContentTypes?.value, //not sure this is right. maybe take off the ?.value + httpClientRef: resolver.httpMetadataResolverAttributes?.httpClientRef, connectionRequestTimeout: resolver.httpMetadataResolverAttributes?.connectionRequestTimeout, connectionTimeout: resolver.httpMetadataResolverAttributes?.connectionTimeout, From 1d1ef9bca3f7f168dcbfdca68752d830bdd3eea0 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Mon, 11 Jun 2018 16:30:54 -0700 Subject: [PATCH 10/11] [SHIBUI-519] Set default values on some resolvers. Test updates. --- .../DynamicHttpMetadataResolver.java | 16 ++++++--- .../DynamicMetadataResolverAttributes.java | 14 ++++---- .../HttpMetadataResolverAttributes.java | 2 +- .../ui/domain/resolvers/MetadataResolver.java | 2 +- ...JPAMetadataResolverServiceImplTests.groovy | 5 ++- .../admin/ui/util/TestObjectGenerator.groovy | 7 ++++ backend/src/test/resources/conf/278.2.xml | 34 +++++++++++++++---- backend/src/test/resources/conf/278.xml | 21 ++++++++++++ 8 files changed, 79 insertions(+), 22 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicHttpMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicHttpMetadataResolver.java index 886839bf8..0910c9050 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicHttpMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicHttpMetadataResolver.java @@ -2,7 +2,6 @@ import lombok.EqualsAndHashCode; import lombok.Getter; -import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; @@ -17,23 +16,32 @@ */ @Entity @EqualsAndHashCode(callSuper = true) -@NoArgsConstructor @Getter @Setter @ToString public class DynamicHttpMetadataResolver extends MetadataResolver { + public static final String DEFAULT_TIMEOUT = "PT5S"; + @Embedded private DynamicMetadataResolverAttributes dynamicMetadataResolverAttributes; @Embedded private HttpMetadataResolverAttributes httpMetadataResolverAttributes; - private int maxConnectionsTotal; + private Integer maxConnectionsTotal = 100; - private int maxConnectionsPerRoute; + private Integer maxConnectionsPerRoute = 100; @ElementCollection @OrderColumn private List supportedContentTypes; + + public DynamicHttpMetadataResolver() { + this.httpMetadataResolverAttributes = new HttpMetadataResolverAttributes(); + this.httpMetadataResolverAttributes.setConnectionRequestTimeout(DEFAULT_TIMEOUT); + this.httpMetadataResolverAttributes.setConnectionTimeout(DEFAULT_TIMEOUT); + this.httpMetadataResolverAttributes.setSocketTimeout(DEFAULT_TIMEOUT); + this.dynamicMetadataResolverAttributes = new DynamicMetadataResolverAttributes(); + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicMetadataResolverAttributes.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicMetadataResolverAttributes.java index 830d06a50..564f2871e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicMetadataResolverAttributes.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/DynamicMetadataResolverAttributes.java @@ -20,17 +20,17 @@ public class DynamicMetadataResolverAttributes { private String taskTimerRef; - private Double refreshDelayFactor; + private Double refreshDelayFactor = 0.75; - private String minCacheDuration; + private String minCacheDuration = "PT10M"; - private String maxCacheDuration; + private String maxCacheDuration = "PT8H"; - private String maxIdleEntityData; + private String maxIdleEntityData = "PT8H"; private Boolean removeIdleEntityData; - private String cleanupTaskInterval; + private String cleanupTaskInterval = "PT30M"; private String persistentCacheManagerRef; @@ -38,9 +38,9 @@ public class DynamicMetadataResolverAttributes { private String persistentCacheKeyGeneratorRef; - private Boolean initializeFromPersistentCacheInBackground; + private Boolean initializeFromPersistentCacheInBackground = true; - private String backgroundInitializationFromCacheDelay; + private String backgroundInitializationFromCacheDelay = "PT2S"; private String initializationFromCachePredicateRef; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/HttpMetadataResolverAttributes.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/HttpMetadataResolverAttributes.java index 706c34e08..8054ba852 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/HttpMetadataResolverAttributes.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/HttpMetadataResolverAttributes.java @@ -28,7 +28,7 @@ public class HttpMetadataResolverAttributes { private String socketTimeout; - private Boolean disregardTLSCertificate; + private Boolean disregardTLSCertificate = false; private String tlsTrustEngineRef; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java index 659380db6..1bbafefba 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java @@ -45,7 +45,7 @@ public class MetadataResolver extends AbstractAuditable { private Boolean useDefaultPredicateRegistry = true; - private Boolean satisfyAnyPredicates; + private Boolean satisfyAnyPredicates = false; @OneToMany(cascade = CascadeType.ALL) @OrderColumn diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy index 9208aa635..af9497b6e 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy @@ -107,9 +107,8 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification { mr.setName("HTTPMetadata") metadataResolverRepository.save(mr) - mr = new TestObjectGenerator(attributeUtility).buildDynamicHttpMetadataResolver() - mr.name = "DynamicHttpMetadata" - metadataResolverRepository.save(mr) + // Generate and test edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver. + metadataResolverRepository.save(new TestObjectGenerator(attributeUtility).dynamicHttpMetadataResolver()) } return resolver diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy index ae9e99db9..e7f2eb949 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy @@ -317,6 +317,13 @@ class TestObjectGenerator { } } + DynamicHttpMetadataResolver dynamicHttpMetadataResolver() { + new DynamicHttpMetadataResolver().with { + it.name = 'DynamicHTTP' + it + } + } + FileBackedHttpMetadataResolver buildFileBackedHttpMetadataResolver() { def resolver = new FileBackedHttpMetadataResolver() resolver.name = generator.randomString(10) diff --git a/backend/src/test/resources/conf/278.2.xml b/backend/src/test/resources/conf/278.2.xml index d8305ada3..94bf255f8 100644 --- a/backend/src/test/resources/conf/278.2.xml +++ b/backend/src/test/resources/conf/278.2.xml @@ -8,6 +8,34 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xsi:schemaLocation="urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:resource http://shibboleth.net/schema/idp/shibboleth-resource.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd"> + + + + + md:SPSSODescriptor + + + + there + + https://sp1.example.org + + md:SPSSODescriptor - - - there - - https://sp1.example.org - diff --git a/backend/src/test/resources/conf/278.xml b/backend/src/test/resources/conf/278.xml index e6e0e88d0..5b3577044 100644 --- a/backend/src/test/resources/conf/278.xml +++ b/backend/src/test/resources/conf/278.xml @@ -8,6 +8,27 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xsi:schemaLocation="urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:resource http://shibboleth.net/schema/idp/shibboleth-resource.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd"> + + + + + md:SPSSODescriptor + + Date: Wed, 13 Jun 2018 10:27:06 -0700 Subject: [PATCH 11/11] [SHIBUI-518] Added LocalDynamicMetadataResolver to resolver service tests. --- .../JPAMetadataResolverServiceImpl.groovy | 32 +++++++++++++++++++ ...JPAMetadataResolverServiceImplTests.groovy | 3 ++ .../admin/ui/util/TestObjectGenerator.groovy | 7 ++++ backend/src/test/resources/conf/278.2.xml | 10 ++++++ backend/src/test/resources/conf/278.xml | 11 ++++++- 5 files changed, 62 insertions(+), 1 deletion(-) diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy index 9177fb137..5885eae26 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy @@ -222,4 +222,36 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { childNodes() } } + + void constructXmlNodeForResolver(LocalDynamicMetadataResolver resolver, def markupBuilderDelegate, Closure childNodes) { + markupBuilderDelegate.MetadataProvider(sourceDirectory: resolver.sourceDirectory, + sourceManagerRef: resolver.sourceManagerRef, + sourceKeyGeneratorRef: resolver.sourceKeyGeneratorRef, + + id: resolver.name, + 'xsi:type': 'DynamicHttpMetadataProvider', + requireValidMetadata: !resolver.requireValidMetadata ?: null, + failFastInitialization: !resolver.failFastInitialization ?: null, + sortKey: resolver.sortKey, + criterionPredicateRegistryRef: resolver.criterionPredicateRegistryRef, + useDefaultPredicateRegistry: !resolver.useDefaultPredicateRegistry ?: null, + satisfyAnyPredicates: resolver.satisfyAnyPredicates ?: null, + parserPoolRef: resolver.dynamicMetadataResolverAttributes?.parserPoolRef, + taskTimerRef: resolver.dynamicMetadataResolverAttributes?.taskTimerRef, + refreshDelayFactor: resolver.dynamicMetadataResolverAttributes?.refreshDelayFactor, + minCacheDuration: resolver.dynamicMetadataResolverAttributes?.minCacheDuration, + maxCacheDuration: resolver.dynamicMetadataResolverAttributes?.maxCacheDuration, + maxIdleEntityData: resolver.dynamicMetadataResolverAttributes?.maxIdleEntityData, + removeIdleEntityData: !resolver.dynamicMetadataResolverAttributes?.removeIdleEntityData ?: null, + cleanupTaskInterval: resolver.dynamicMetadataResolverAttributes?.cleanupTaskInterval, + persistentCacheManagerRef: resolver.dynamicMetadataResolverAttributes?.persistentCacheManagerRef, + persistentCacheManagerDirectory: resolver.dynamicMetadataResolverAttributes?.persistentCacheManagerDirectory, + persistentCacheKeyGeneratorRef: resolver.dynamicMetadataResolverAttributes?.persistentCacheKeyGeneratorRef, + initializeFromPersistentCacheInBackground: !resolver.dynamicMetadataResolverAttributes?.initializeFromPersistentCacheInBackground ?: null, + backgroundInitializationFromCacheDelay: resolver.dynamicMetadataResolverAttributes?.backgroundInitializationFromCacheDelay, + initializationFromCachePredicateRef: resolver.dynamicMetadataResolverAttributes?.initializationFromCachePredicateRef) { + + childNodes() + } + } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy index af9497b6e..c9af03e34 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy @@ -109,6 +109,9 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification { // Generate and test edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver. metadataResolverRepository.save(new TestObjectGenerator(attributeUtility).dynamicHttpMetadataResolver()) + + // Generate and test edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver. + metadataResolverRepository.save(new TestObjectGenerator(attributeUtility).localDynamicMetadataResolver()) } return resolver diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy index e7f2eb949..e42534914 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy @@ -324,6 +324,13 @@ class TestObjectGenerator { } } + LocalDynamicMetadataResolver localDynamicMetadataResolver() { + new LocalDynamicMetadataResolver().with { + it.name = 'LocalDynamic' + it + } + } + FileBackedHttpMetadataResolver buildFileBackedHttpMetadataResolver() { def resolver = new FileBackedHttpMetadataResolver() resolver.name = generator.randomString(10) diff --git a/backend/src/test/resources/conf/278.2.xml b/backend/src/test/resources/conf/278.2.xml index 94bf255f8..208501c45 100644 --- a/backend/src/test/resources/conf/278.2.xml +++ b/backend/src/test/resources/conf/278.2.xml @@ -50,5 +50,15 @@ md:SPSSODescriptor + + + + + md:SPSSODescriptor + + diff --git a/backend/src/test/resources/conf/278.xml b/backend/src/test/resources/conf/278.xml index 5b3577044..0d08ba252 100644 --- a/backend/src/test/resources/conf/278.xml +++ b/backend/src/test/resources/conf/278.xml @@ -43,5 +43,14 @@ md:SPSSODescriptor - + + + + + md:SPSSODescriptor + +