From 81a6359ac4e9d3e74b9739b9c5e0f9eeaeef1a7d Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 17 May 2018 16:59:31 -0400 Subject: [PATCH 01/15] [SHIBUI-517]: SHIBUI-528 JPA model --- .../JPAMetadataResolverServiceImpl.groovy | 4 +- .../MetadataResolverConfiguration.java | 2 +- .../admin/ui/controller/FilterController.java | 2 +- .../admin/ui/domain/MetadataResolver.java | 53 ------------------ .../FileBackedHttpMetadataResolver.java | 26 +++++++++ .../HttpMetadataResolverAttributes.java | 56 +++++++++++++++++++ .../ui/domain/resolvers/MetadataResolver.java | 48 ++++++++++++++++ .../ReloadableMetadataResolverAttributes.java | 33 +++++++++++ .../MetadataResolverRepository.java | 4 +- .../controller/FilterControllerTests.groovy | 2 +- .../MetadataResolverRepositoryTest.groovy | 2 +- ...JPAMetadataResolverServiceImplTests.groovy | 5 +- ...JPAMetadataResolverServiceImplTests.groovy | 3 +- 13 files changed, 173 insertions(+), 67 deletions(-) delete mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/MetadataResolver.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/HttpMetadataResolverAttributes.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ReloadableMetadataResolverAttributes.java 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 da474a717..f28480e73 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 @@ -40,7 +40,7 @@ public class JPAMetadataResolverServiceImpl implements MetadataResolverService { // MetadataResolver targetMetadataResolver = chainingMetadataResolver.getResolvers().stream().filter(r -> r.getId().equals(metadataResolverName)).findFirst().get(); MetadataResolver targetMetadataResolver = chainingMetadataResolver.getResolvers().find { it.id == metadataResolverName } - edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver jpaMetadataResolver = metadataResolverRepository.findByName(metadataResolverName); + edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver jpaMetadataResolver = metadataResolverRepository.findByName(metadataResolverName); if (targetMetadataResolver && targetMetadataResolver.getMetadataFilter() instanceof MetadataFilterChain) { MetadataFilterChain metadataFilterChain = (MetadataFilterChain)targetMetadataResolver.getMetadataFilter(); @@ -88,7 +88,7 @@ public class JPAMetadataResolverServiceImpl implements MetadataResolverService { 'xsi:type': 'ChainingMetadataProvider', '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' ) { - metadataResolverRepository.findAll().each { edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver mr -> + metadataResolverRepository.findAll().each { edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr -> MetadataProvider(id: 'HTTPMetadata', 'xsi:type': 'FileBackedHTTPMetadataProvider', backingFile: '%{idp.home}/metadata/incommonmd.xml', diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MetadataResolverConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MetadataResolverConfiguration.java index f6a88b27d..51ba89b05 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MetadataResolverConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MetadataResolverConfiguration.java @@ -95,7 +95,7 @@ protected void processConditionalRetrievalHeaders(HttpResponse response) { resolvers.add(incommonMR); if (!metadataResolverRepository.findAll().iterator().hasNext()) { - edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver mr = new edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver(); + edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr = new edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver(); mr.setName("incommonmd"); metadataResolverRepository.save(mr); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FilterController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FilterController.java index 093a5b9ff..71db1e409 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FilterController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FilterController.java @@ -2,7 +2,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter; import edu.internet2.tier.shibboleth.admin.ui.domain.MetadataFilter; -import edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver; +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterRepresentation; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; import edu.internet2.tier.shibboleth.admin.ui.service.FilterService; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/MetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/MetadataResolver.java deleted file mode 100644 index 9d5288dbc..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/MetadataResolver.java +++ /dev/null @@ -1,53 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain; - -import lombok.EqualsAndHashCode; - -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.OneToMany; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -@Entity -@EqualsAndHashCode(callSuper = true) -public class MetadataResolver extends AbstractAuditable { - private String name; - private String resourceId = UUID.randomUUID().toString(); - - @OneToMany(cascade = CascadeType.ALL) - private List metadataFilters = new ArrayList<>(); - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getResourceId() { - return resourceId; - } - - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - public List getMetadataFilters() { - return metadataFilters; - } - - public void setMetadataFilters(List metadataFilters) { - this.metadataFilters = metadataFilters; - } - - @Override - public String toString() { - return "MetadataResolver{\n" + - "name='" + name + "\'\n" + - ", resourceId='" + resourceId + "\'\n" + - ", metadataFilters=\n" + metadataFilters + - '}'; - } -} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java new file mode 100644 index 000000000..c9850ecc6 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java @@ -0,0 +1,26 @@ +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 FileBackedHttpMetadataResolver extends MetadataResolver { + + @Embedded + private ReloadableMetadataResolverAttributes reloadableMetadataResolverAttributes; + + @Embedded + private HttpMetadataResolverAttributes httpMetadataResolverAttributes; + +} 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 new file mode 100644 index 000000000..a3d9d2c80 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/HttpMetadataResolverAttributes.java @@ -0,0 +1,56 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.Enumerated; + +import static javax.persistence.EnumType.STRING; + +@Embeddable +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +public class HttpMetadataResolverAttributes { + + private String httpClientRef; + + private String connectionRequestTimeout; + + private String requestTimeout; + + private String socketTimeout; + + private Boolean disregardTLSCertificate; + + private String tlsTrustEngineRef; + + private String httpClientSecurityParametersRef; + + private String proxyHost; + + private String proxyPort; + + private String proxyUser; + + private String proxyPassword; + + @Enumerated(STRING) + @Column(length = 5) + private HttpCachingType httpCaching; + + private String httpCacheDirectory; + + private Integer httpMaxCacheEntries; + + private Integer httpMaxCacheEntrySize; + + private enum HttpCachingType { + none,file,memory + } +} 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 new file mode 100644 index 000000000..e211cb27d --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java @@ -0,0 +1,48 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; + +import edu.internet2.tier.shibboleth.admin.ui.domain.AbstractAuditable; +import edu.internet2.tier.shibboleth.admin.ui.domain.MetadataFilter; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; + +import javax.persistence.OneToMany; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Entity +@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Getter +@Setter +@ToString +public class MetadataResolver extends AbstractAuditable { + + private String name; + + private String resourceId = UUID.randomUUID().toString(); + + private Boolean requireValidMetadata; + + private Boolean failFastInitialization; + + private Integer sortKey; + + private String criterionPredicateRegistryRef; + + private Boolean useDefaultPredicateRegistry; + + private Boolean satisfyAnyPredicates; + + @OneToMany(cascade = CascadeType.ALL) + private List metadataFilters = new ArrayList<>(); +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ReloadableMetadataResolverAttributes.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ReloadableMetadataResolverAttributes.java new file mode 100644 index 000000000..ad21f7a23 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ReloadableMetadataResolverAttributes.java @@ -0,0 +1,33 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Embeddable; + +@Embeddable +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +public class ReloadableMetadataResolverAttributes { + + private String parserPoolRef; + + private String taskTimerRef; + + private String minRefreshDelay; + + private String maxRefreshDelay; + + private Double refreshDelayFactor; + + private String indexesRef; + + private Boolean resolveViaPredicatesOnly; + + private String expirationWarningThreshold; + +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepository.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepository.java index 5dba01872..fc415aef1 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepository.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepository.java @@ -1,10 +1,10 @@ package edu.internet2.tier.shibboleth.admin.ui.repository; -import edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver; +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver; import org.springframework.data.repository.CrudRepository; /** - * Repository to manage {@link edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver} instances. + * Repository to manage {@link MetadataResolver} instances. */ public interface MetadataResolverRepository extends CrudRepository { MetadataResolver findByName(String name); diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FilterControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FilterControllerTests.groovy index fdf90d65d..9d8a1f72c 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FilterControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FilterControllerTests.groovy @@ -5,7 +5,7 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfigurat 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.EntityAttributesFilter -import edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import edu.internet2.tier.shibboleth.admin.ui.service.FilterService import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverService diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy index 713471f48..06584b52c 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy @@ -5,7 +5,7 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.MetadataResolverConf import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget -import edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest 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 12112d0b9..7628f30de 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 @@ -4,14 +4,11 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfigurat import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget -import edu.internet2.tier.shibboleth.admin.ui.domain.MetadataFilter import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import edu.internet2.tier.shibboleth.admin.util.AttributeUtility -import org.apache.http.impl.client.HttpClients import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver import org.opensaml.saml.metadata.resolver.MetadataResolver -import org.opensaml.saml.metadata.resolver.impl.FileBackedHTTPMetadataResolver import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest @@ -100,7 +97,7 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification { } if (!metadataResolverRepository.findAll().iterator().hasNext()) { - edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver mr = new edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver() + edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr = new edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver() mr.setName("incommonmd") metadataResolverRepository.save(mr) } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy index faa913f6b..afc93df62 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy @@ -1,7 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.service 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.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget @@ -75,7 +74,7 @@ class JPAMetadataResolverServiceImplTests extends Specification { ''' when: - def mdr = new edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver().with { + def mdr = new edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver().with { it.name = "testme" it.metadataFilters.add(new EntityAttributesFilter().with { it.entityAttributesFilterTarget = new EntityAttributesFilterTarget().with { From e1e8fcc1d9e5b3209ffb70ea9a6914dad211df05 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 18 May 2018 15:17:06 -0400 Subject: [PATCH 02/15] [SHIBUI-517]: SHIBUI-528 --- .../HttpMetadataResolverAttributes.java | 2 +- ...eBackedHttpMetadataResolverRepository.java | 12 ++++ ...HttpMetadataResolverRepositoryTests.groovy | 67 +++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepository.java create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepositoryTests.groovy 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 a3d9d2c80..cc880cc32 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 @@ -41,7 +41,7 @@ public class HttpMetadataResolverAttributes { private String proxyPassword; @Enumerated(STRING) - @Column(length = 5) + @Column(length = 6) private HttpCachingType httpCaching; private String httpCacheDirectory; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepository.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepository.java new file mode 100644 index 000000000..c4adea391 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepository.java @@ -0,0 +1,12 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository; + +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver; +import org.springframework.data.repository.CrudRepository; + +/** + * Spring Data CRUD repository for instances of {@link FileBackedHttpMetadataResolver}s. + */ +public interface FileBackedHttpMetadataResolverRepository extends CrudRepository { + + FileBackedHttpMetadataResolver findByName(String name); +} 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 new file mode 100644 index 000000000..710a966d3 --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepositoryTests.groovy @@ -0,0 +1,67 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository + +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.EntityAttributesFilter +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget +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.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.context.ContextConfiguration +import spock.lang.Specification + +import static edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget.EntityAttributesFilterTargetType.* +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") +class FileBackedHttpMetadataResolverRepositoryTests extends Specification { + + @Autowired + FileBackedHttpMetadataResolverRepository repositoryUnderTest + + def "file backed http metadata resolver instances persist OK"() { + when: + def mdr = new FileBackedHttpMetadataResolver().with { + it.name = "FileBackedHttpMetadata" + it.httpMetadataResolverAttributes = new HttpMetadataResolverAttributes() + it.reloadableMetadataResolverAttributes = new ReloadableMetadataResolverAttributes() + + it.httpMetadataResolverAttributes.connectionRequestTimeout = "PT05" + it.httpMetadataResolverAttributes.disregardTLSCertificate = true + it.httpMetadataResolverAttributes.httpCaching = memory + it.reloadableMetadataResolverAttributes.indexesRef = "indexesSpringBeanId" + it.metadataFilters.add(new EntityAttributesFilter().with { + it.entityAttributesFilterTarget = new EntityAttributesFilterTarget().with { + it.entityAttributesFilterTargetType = ENTITY + it.setValue(["hola"]) + return it + } + return it + }) + return it + } + repositoryUnderTest.save(mdr) + + then: + repositoryUnderTest.findAll().size() > 0 + FileBackedHttpMetadataResolver item = repositoryUnderTest.findByName("FileBackedHttpMetadata") + + item.name == "FileBackedHttpMetadata" + 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.httpMetadataResolverAttributes.connectionRequestTimeout == "PT05" + item.httpMetadataResolverAttributes.disregardTLSCertificate + item.httpMetadataResolverAttributes.httpCaching == memory + item.reloadableMetadataResolverAttributes.indexesRef == "indexesSpringBeanId" + } +} From a4eaecc4c940fef65cbbb311943e24f4e943f7ec Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 18 May 2018 15:37:57 -0400 Subject: [PATCH 03/15] Tests polishing --- ...HttpMetadataResolverRepositoryTests.groovy | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) 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 710a966d3..0cef56367 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 @@ -31,22 +31,27 @@ class FileBackedHttpMetadataResolverRepositoryTests extends Specification { when: def mdr = new FileBackedHttpMetadataResolver().with { it.name = "FileBackedHttpMetadata" - it.httpMetadataResolverAttributes = new HttpMetadataResolverAttributes() - it.reloadableMetadataResolverAttributes = new ReloadableMetadataResolverAttributes() - it.httpMetadataResolverAttributes.connectionRequestTimeout = "PT05" - it.httpMetadataResolverAttributes.disregardTLSCertificate = true - it.httpMetadataResolverAttributes.httpCaching = memory - it.reloadableMetadataResolverAttributes.indexesRef = "indexesSpringBeanId" + it.httpMetadataResolverAttributes = new HttpMetadataResolverAttributes().with { + it.connectionRequestTimeout = "PT05" + it.disregardTLSCertificate = true + it.httpCaching = memory + it + } + it.reloadableMetadataResolverAttributes = new ReloadableMetadataResolverAttributes().with { + it.indexesRef = "indexesSpringBeanId" + it + } + it.metadataFilters.add(new EntityAttributesFilter().with { it.entityAttributesFilterTarget = new EntityAttributesFilterTarget().with { it.entityAttributesFilterTargetType = ENTITY it.setValue(["hola"]) - return it + it } - return it + it }) - return it + it } repositoryUnderTest.save(mdr) From 65b42b3ee0e335a2bfba84c42fa5ab4a8ed813e5 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Mon, 21 May 2018 16:06:35 -0700 Subject: [PATCH 04/15] [SHIBUI-517] First pass at FileBackedHttpMetadataProviderController. More to come. --- ...eBackedHttpMetadataProviderController.java | 82 +++++++++++++++++++ .../ui/domain/resolvers/MetadataResolver.java | 3 + ...eBackedHttpMetadataResolverRepository.java | 2 + 3 files changed, 87 insertions(+) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java new file mode 100644 index 000000000..56fa92729 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java @@ -0,0 +1,82 @@ +package edu.internet2.tier.shibboleth.admin.ui.controller; + +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver; +import edu.internet2.tier.shibboleth.admin.ui.repository.FileBackedHttpMetadataResolverRepository; +import org.springframework.beans.factory.annotation.Autowired; +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/FileBackedHttp") +public class FileBackedHttpMetadataProviderController { + + @Autowired + FileBackedHttpMetadataResolverRepository 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) { + return ResponseEntity.ok(repository.findByName(metadataProviderName)); + } + + @GetMapping("/{resourceId}") + @Transactional(readOnly = true) + public ResponseEntity getOneByResourceId(@PathVariable String resourceId) { + return ResponseEntity.ok(repository.findByResourceId(resourceId)); + } + + @PostMapping + public ResponseEntity create(@RequestBody FileBackedHttpMetadataResolver resolver) { + //TODO: Check for duplicates based on name + FileBackedHttpMetadataResolver persistedResolver = repository.save(resolver); + + return ResponseEntity + .created(getResourceUriFor(persistedResolver)) + .body(persistedResolver); + + } + + @PutMapping + public ResponseEntity update(@RequestBody FileBackedHttpMetadataResolver resolver) { + FileBackedHttpMetadataResolver existingResolver = repository.findByResourceId(resolver.getResourceId()); + //TODO: Handle not found. + //TODO: Handle contention. + + resolver.setAudId(existingResolver.getAudId()); + + FileBackedHttpMetadataResolver updatedResolver = repository.save(resolver); + + return ResponseEntity.ok(updatedResolver); + } + + private static URI getResourceUriFor(FileBackedHttpMetadataResolver resolver) { + return ServletUriComponentsBuilder + .fromCurrentServletMapping().path("/api/MetadataProvider/FileBackedHttp/") + .pathSegment(resolver.getResourceId()) + .build() + .toUri(); + } +} 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 e211cb27d..f8ad0c216 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 @@ -9,6 +9,7 @@ import lombok.ToString; import javax.persistence.CascadeType; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; @@ -27,8 +28,10 @@ @ToString public class MetadataResolver extends AbstractAuditable { + @Column(unique=true) private String name; + @Column(unique=true) private String resourceId = UUID.randomUUID().toString(); private Boolean requireValidMetadata; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepository.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepository.java index c4adea391..97d069173 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepository.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/FileBackedHttpMetadataResolverRepository.java @@ -9,4 +9,6 @@ public interface FileBackedHttpMetadataResolverRepository extends CrudRepository { FileBackedHttpMetadataResolver findByName(String name); + boolean deleteByResourceId(String resourceId); + FileBackedHttpMetadataResolver findByResourceId(String resourceId); } From ea3b0e9c61d0304bb17817c6c9d169264d3224fa Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Thu, 24 May 2018 12:45:29 -0700 Subject: [PATCH 05/15] [SHIBUI-517] Updates to controller and tests. More tests incoming. --- ...eBackedHttpMetadataProviderController.java | 39 +++++++++++-- .../admin/ui/domain/AbstractAuditable.java | 2 + .../HttpMetadataResolverAttributes.java | 2 + .../ui/domain/resolvers/MetadataResolver.java | 8 ++- .../ReloadableMetadataResolverAttributes.java | 2 + ...HttpMetadataResolverRepositoryTests.groovy | 57 ++++++++++++++++++- 6 files changed, 102 insertions(+), 8 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java index 56fa92729..572c728ae 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java @@ -2,7 +2,10 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver; import edu.internet2.tier.shibboleth.admin.ui.repository.FileBackedHttpMetadataResolverRepository; +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; @@ -23,6 +26,7 @@ @RestController @RequestMapping("/api/MetadataProvider/FileBackedHttp") public class FileBackedHttpMetadataProviderController { + private static final Logger logger = LoggerFactory.getLogger(FileBackedHttpMetadataProviderController.class); @Autowired FileBackedHttpMetadataResolverRepository repository; @@ -39,33 +43,56 @@ public ResponseEntity deleteByResourceId(@PathVariable String resourceId) { @GetMapping("/name/{metadataProviderName}") @Transactional(readOnly = true) public ResponseEntity getOneByName(@PathVariable String metadataProviderName) { - return ResponseEntity.ok(repository.findByName(metadataProviderName)); + FileBackedHttpMetadataResolver resolver = repository.findByResourceId(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) { - return ResponseEntity.ok(repository.findByResourceId(resourceId)); + FileBackedHttpMetadataResolver 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 FileBackedHttpMetadataResolver resolver) { - //TODO: Check for duplicates based on name + if (repository.findByName(resolver.getName()) != null) { + return ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + FileBackedHttpMetadataResolver persistedResolver = repository.save(resolver); + persistedResolver.setVersion(persistedResolver.hashCode()); return ResponseEntity .created(getResourceUriFor(persistedResolver)) .body(persistedResolver); - } @PutMapping public ResponseEntity update(@RequestBody FileBackedHttpMetadataResolver resolver) { FileBackedHttpMetadataResolver existingResolver = repository.findByResourceId(resolver.getResourceId()); - //TODO: Handle not found. - //TODO: Handle contention. + + 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? FileBackedHttpMetadataResolver updatedResolver = repository.save(resolver); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java index 8f530bdd6..1d23d5113 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java @@ -1,5 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; +import lombok.EqualsAndHashCode; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; import org.springframework.data.annotation.CreatedBy; @@ -20,6 +21,7 @@ @MappedSuperclass @EntityListeners(AuditingEntityListener.class) +@EqualsAndHashCode public abstract class AbstractAuditable implements Auditable { @Id 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 cc880cc32..437516ffd 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 @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -16,6 +17,7 @@ @AllArgsConstructor @Getter @Setter +@EqualsAndHashCode public class HttpMetadataResolverAttributes { private String httpClientRef; 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 f8ad0c216..4deebcbcb 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 @@ -15,13 +15,15 @@ import javax.persistence.InheritanceType; import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; +import javax.persistence.Transient; import java.util.ArrayList; import java.util.List; import java.util.UUID; @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode(callSuper = true, exclude={"version"}) @NoArgsConstructor @Getter @Setter @@ -47,5 +49,9 @@ public class MetadataResolver extends AbstractAuditable { private Boolean satisfyAnyPredicates; @OneToMany(cascade = CascadeType.ALL) + @OrderColumn private List metadataFilters = new ArrayList<>(); + + @Transient + private int version; } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ReloadableMetadataResolverAttributes.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ReloadableMetadataResolverAttributes.java index ad21f7a23..cddf5b935 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ReloadableMetadataResolverAttributes.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ReloadableMetadataResolverAttributes.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -12,6 +13,7 @@ @AllArgsConstructor @Getter @Setter +@EqualsAndHashCode public class ReloadableMetadataResolverAttributes { private String parserPoolRef; 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 0cef56367..d4aea60ba 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 @@ -1,5 +1,6 @@ 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 @@ -12,21 +13,28 @@ 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 static edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget.EntityAttributesFilterTargetType.* +import javax.persistence.EntityManager + +import static edu.internet2.tier.shibboleth.admin.ui.domain.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 FileBackedHttpMetadataResolverRepositoryTests extends Specification { @Autowired FileBackedHttpMetadataResolverRepository repositoryUnderTest + @Autowired + EntityManager entityManager + def "file backed http metadata resolver instances persist OK"() { when: def mdr = new FileBackedHttpMetadataResolver().with { @@ -69,4 +77,51 @@ class FileBackedHttpMetadataResolverRepositoryTests extends Specification { item.httpMetadataResolverAttributes.httpCaching == memory item.reloadableMetadataResolverAttributes.indexesRef == "indexesSpringBeanId" } + + def "FileBackedHttpMetadataResolver hashcode works as desired"() { + given: + // TODO: Ask JJ why an empty reloadableMetadataResolverAttributes object results in a null object for item2 below + def resolverJson = '''{ + "name": "name", + "requireValidMetadata": true, + "failFastInitialization": true, + "sortKey": 7, + "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", + "useDefaultPredicateRegistry": true, + "satisfyAnyPredicates": true, + "metadataFilters": [], + "reloadableMetadataResolverAttributes": { + }, + "httpMetadataResolverAttributes": { + "httpClientRef": "httpClientRef", + "connectionRequestTimeout": "connectionRequestTimeout", + "requestTimeout": "requestTimeout", + "socketTimeout": "socketTimeout", + "disregardTLSCertificate": true, + "tlsTrustEngineRef": "tlsTrustEngineRef", + "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", + "proxyHost": "proxyHost", + "proxyPort": "proxyPort", + "proxyUser": "proxyUser", + "proxyPassword": "proxyPassword", + "httpCaching": "none", + "httpCacheDirectory": "httpCacheDirectory", + "httpMaxCacheEntries": 1, + "httpMaxCacheEntrySize": 2 + } +}''' + + when: + def resolver = new ObjectMapper().readValue(resolverJson.bytes, FileBackedHttpMetadataResolver) + def persistedResolver = repositoryUnderTest.save(resolver) + entityManager.flush() + + then: + entityManager.clear() + def item1 = repositoryUnderTest.findByResourceId(persistedResolver.resourceId) + entityManager.clear() + def item2 = repositoryUnderTest.findByResourceId(persistedResolver.resourceId) + + item1.hashCode() == item2.hashCode() + } } From fb9eb6a6564a572d8222660c77f83188ae31ea4e Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Fri, 25 May 2018 11:53:46 -0700 Subject: [PATCH 06/15] [SHIBUI-517] Added unit tests for all controller operations. --- ...eBackedHttpMetadataProviderController.java | 3 +- ...HttpMetadataProviderControllerTests.groovy | 594 ++++++++++++++++++ ...HttpMetadataResolverRepositoryTests.groovy | 5 +- 3 files changed, 599 insertions(+), 3 deletions(-) create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java index 572c728ae..5b8000482 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderController.java @@ -43,7 +43,7 @@ public ResponseEntity deleteByResourceId(@PathVariable String resourceId) { @GetMapping("/name/{metadataProviderName}") @Transactional(readOnly = true) public ResponseEntity getOneByName(@PathVariable String metadataProviderName) { - FileBackedHttpMetadataResolver resolver = repository.findByResourceId(metadataProviderName); + FileBackedHttpMetadataResolver resolver = repository.findByName(metadataProviderName); if (resolver == null) { return ResponseEntity.notFound().build(); } else { @@ -95,6 +95,7 @@ public ResponseEntity update(@RequestBody FileBackedHttpMetadataResolver reso //TODO: Do we need to set anything else? dates? FileBackedHttpMetadataResolver updatedResolver = repository.save(resolver); + updatedResolver.setVersion(updatedResolver.hashCode()); return ResponseEntity.ok(updatedResolver); } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy new file mode 100644 index 000000000..377722b5d --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy @@ -0,0 +1,594 @@ +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.domain.resolvers.FileBackedHttpMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.repository.FileBackedHttpMetadataResolverRepository +import edu.internet2.tier.shibboleth.admin.ui.util.RandomGenerator +import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator +import groovy.json.JsonOutput +import groovy.json.JsonSlurper +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 FileBackedHttpMetadataProviderControllerTests extends Specification { + TestObjectGenerator testObjectGenerator + RandomGenerator randomGenerator + ObjectMapper mapper + + def repository = Mock(FileBackedHttpMetadataResolverRepository) + def controller + def mockMvc + + def setup() { + randomGenerator = new RandomGenerator() + //testObjectGenerator = new TestObjectGenerator(attributeUtility) + mapper = new ObjectMapper() + + controller = new FileBackedHttpMetadataProviderController ( + 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/FileBackedHttp/$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/FileBackedHttp/$randomResourceId")) + + then: + result.andExpect(status().isNotFound()) + } + + def "POST a new resolver properly persists and returns the new persisted resolver"() { + given: + def postedJsonBody = '''{ + "name": "name", + "requireValidMetadata": true, + "failFastInitialization": true, + "sortKey": 7, + "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", + "useDefaultPredicateRegistry": true, + "satisfyAnyPredicates": true, + "metadataFilters": [], + "reloadableMetadataResolverAttributes": { + "parserPoolRef": "parserPoolRef", + "taskTimerRef": "taskTimerRef", + "minRefreshDelay": "minRefreshDelay", + "maxRefreshDelay": "maxRefreshDelay", + "refreshDelayFactor": 1.0, + "indexesRef": "indexesRef", + "resolveViaPredicatesOnly": true, + "expirationWarningThreshold": "expirationWarningThreshold" + }, + "httpMetadataResolverAttributes": { + "httpClientRef": "httpClientRef", + "connectionRequestTimeout": "connectionRequestTimeout", + "requestTimeout": "requestTimeout", + "socketTimeout": "socketTimeout", + "disregardTLSCertificate": true, + "tlsTrustEngineRef": "tlsTrustEngineRef", + "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", + "proxyHost": "proxyHost", + "proxyPort": "proxyPort", + "proxyUser": "proxyUser", + "proxyPassword": "proxyPassword", + "httpCaching": "none", + "httpCacheDirectory": "httpCacheDirectory", + "httpMaxCacheEntries": 1, + "httpMaxCacheEntrySize": 2 + } +}''' + def resolver = new ObjectMapper().readValue(postedJsonBody.bytes, FileBackedHttpMetadataResolver) + 1 * repository.findByName(resolver.getName()) >> null + 1 * repository.save(_) >> resolver + + def expectedResolverUUID = resolver.getResourceId() + def expectedResponseHeader = 'Location' + def expectedResponseHeaderValue = "/api/MetadataProvider/FileBackedHttp/$expectedResolverUUID" + + when: + def result = mockMvc.perform( + post('/api/MetadataProvider/FileBackedHttp') + .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 randomResolverName = randomGenerator.randomString(10) + def postedJsonBody = """{ + "name": "$randomResolverName", + "requireValidMetadata": true, + "failFastInitialization": true, + "sortKey": 7, + "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", + "useDefaultPredicateRegistry": true, + "satisfyAnyPredicates": true, + "metadataFilters": [], + "reloadableMetadataResolverAttributes": { + "parserPoolRef": "parserPoolRef", + "taskTimerRef": "taskTimerRef", + "minRefreshDelay": "minRefreshDelay", + "maxRefreshDelay": "maxRefreshDelay", + "refreshDelayFactor": 1.0, + "indexesRef": "indexesRef", + "resolveViaPredicatesOnly": true, + "expirationWarningThreshold": "expirationWarningThreshold" + }, + "httpMetadataResolverAttributes": { + "httpClientRef": "httpClientRef", + "connectionRequestTimeout": "connectionRequestTimeout", + "requestTimeout": "requestTimeout", + "socketTimeout": "socketTimeout", + "disregardTLSCertificate": true, + "tlsTrustEngineRef": "tlsTrustEngineRef", + "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", + "proxyHost": "proxyHost", + "proxyPort": "proxyPort", + "proxyUser": "proxyUser", + "proxyPassword": "proxyPassword", + "httpCaching": "none", + "httpCacheDirectory": "httpCacheDirectory", + "httpMaxCacheEntries": 1, + "httpMaxCacheEntrySize": 2 + } +}""" + def resolver = new ObjectMapper().readValue(postedJsonBody.bytes, FileBackedHttpMetadataResolver) + 1 * repository.findByName(randomResolverName) >> resolver + 0 * repository.save(_) + + when: + def result = mockMvc.perform( + post('/api/MetadataProvider/FileBackedHttp') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + result.andExpect(status().isConflict()) + } + + def "GET by resourceId returns the desired persisted resolver"() { + given: + def randomUUID = randomGenerator.randomId() + def resolverJson = """{ + "name": "name", + "resourceId": "$randomUUID", + "requireValidMetadata": true, + "failFastInitialization": true, + "sortKey": 7, + "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", + "useDefaultPredicateRegistry": true, + "satisfyAnyPredicates": true, + "metadataFilters": [], + "reloadableMetadataResolverAttributes": { + "parserPoolRef": "parserPoolRef", + "taskTimerRef": "taskTimerRef", + "minRefreshDelay": "minRefreshDelay", + "maxRefreshDelay": "maxRefreshDelay", + "refreshDelayFactor": 1.0, + "indexesRef": "indexesRef", + "resolveViaPredicatesOnly": true, + "expirationWarningThreshold": "expirationWarningThreshold" + }, + "httpMetadataResolverAttributes": { + "httpClientRef": "httpClientRef", + "connectionRequestTimeout": "connectionRequestTimeout", + "requestTimeout": "requestTimeout", + "socketTimeout": "socketTimeout", + "disregardTLSCertificate": true, + "tlsTrustEngineRef": "tlsTrustEngineRef", + "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", + "proxyHost": "proxyHost", + "proxyPort": "proxyPort", + "proxyUser": "proxyUser", + "proxyPassword": "proxyPassword", + "httpCaching": "none", + "httpCacheDirectory": "httpCacheDirectory", + "httpMaxCacheEntries": 1, + "httpMaxCacheEntrySize": 2 + } +}""" + + def resolver = new ObjectMapper().readValue(resolverJson.bytes, FileBackedHttpMetadataResolver) + resolver.setResourceId(randomUUID) + + 1 * repository.findByResourceId(randomUUID) >> resolver + + def expectedResponseContentType = APPLICATION_JSON_UTF8 + + when: + def result = mockMvc.perform( + get("/api/MetadataProvider/FileBackedHttp/$randomUUID")) + + 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/FileBackedHttp/$randomResourceId")) + + then: + result.andExpect(status().isNotFound()) + } + + def "GET by resolver name returns the desired persisted resolver"() { + given: + def randomResolverName = randomGenerator.randomString(10) + def resolverJson = """{ + "name": "$randomResolverName", + "requireValidMetadata": true, + "failFastInitialization": true, + "sortKey": 7, + "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", + "useDefaultPredicateRegistry": true, + "satisfyAnyPredicates": true, + "metadataFilters": [], + "reloadableMetadataResolverAttributes": { + "parserPoolRef": "parserPoolRef", + "taskTimerRef": "taskTimerRef", + "minRefreshDelay": "minRefreshDelay", + "maxRefreshDelay": "maxRefreshDelay", + "refreshDelayFactor": 1.0, + "indexesRef": "indexesRef", + "resolveViaPredicatesOnly": true, + "expirationWarningThreshold": "expirationWarningThreshold" + }, + "httpMetadataResolverAttributes": { + "httpClientRef": "httpClientRef", + "connectionRequestTimeout": "connectionRequestTimeout", + "requestTimeout": "requestTimeout", + "socketTimeout": "socketTimeout", + "disregardTLSCertificate": true, + "tlsTrustEngineRef": "tlsTrustEngineRef", + "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", + "proxyHost": "proxyHost", + "proxyPort": "proxyPort", + "proxyUser": "proxyUser", + "proxyPassword": "proxyPassword", + "httpCaching": "none", + "httpCacheDirectory": "httpCacheDirectory", + "httpMaxCacheEntries": 1, + "httpMaxCacheEntrySize": 2 + } +}""" + + def resolver = new ObjectMapper().readValue(resolverJson.bytes, FileBackedHttpMetadataResolver) + + 1 * repository.findByName(randomResolverName) >> resolver + + def expectedResponseContentType = APPLICATION_JSON_UTF8 + + when: + def result = mockMvc.perform( + get("/api/MetadataProvider/FileBackedHttp/name/$randomResolverName")) + + 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/FileBackedHttp/name/$randomResolverName")) + + then: + result.andExpect(status().isNotFound()) + } + + def "PUT allows for a successful update of an already-persisted resolver"() { + given: + def randomResourceId = "resourceId" + def existingResolverJson = """{ + "name": "name", + "resourceId": "$randomResourceId", + "requireValidMetadata": true, + "failFastInitialization": true, + "sortKey": 7, + "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", + "useDefaultPredicateRegistry": true, + "satisfyAnyPredicates": true, + "metadataFilters": [], + "reloadableMetadataResolverAttributes": { + "parserPoolRef": "parserPoolRef", + "taskTimerRef": "taskTimerRef", + "minRefreshDelay": "minRefreshDelay", + "maxRefreshDelay": "maxRefreshDelay", + "refreshDelayFactor": 1.0, + "indexesRef": "indexesRef", + "resolveViaPredicatesOnly": true, + "expirationWarningThreshold": "expirationWarningThreshold" + }, + "httpMetadataResolverAttributes": { + "httpClientRef": "httpClientRef", + "connectionRequestTimeout": "connectionRequestTimeout", + "requestTimeout": "requestTimeout", + "socketTimeout": "socketTimeout", + "disregardTLSCertificate": true, + "tlsTrustEngineRef": "tlsTrustEngineRef", + "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", + "proxyHost": "proxyHost", + "proxyPort": "proxyPort", + "proxyUser": "proxyUser", + "proxyPassword": "proxyPassword", + "httpCaching": "none", + "httpCacheDirectory": "httpCacheDirectory", + "httpMaxCacheEntries": 1, + "httpMaxCacheEntrySize": 2 + } +}""" + def existingResolver = new ObjectMapper().readValue(existingResolverJson.bytes, FileBackedHttpMetadataResolver) + def existingResolverVersion = existingResolver.hashCode() + + def randomName = randomGenerator.randomString(10) + def postedJsonBody = """{ + "name": "$randomName", + "resourceId": "$randomResourceId", + "version": "$existingResolverVersion", + "requireValidMetadata": true, + "failFastInitialization": true, + "sortKey": 7, + "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", + "useDefaultPredicateRegistry": true, + "satisfyAnyPredicates": true, + "metadataFilters": [], + "reloadableMetadataResolverAttributes": { + "parserPoolRef": "parserPoolRef", + "taskTimerRef": "taskTimerRef", + "minRefreshDelay": "minRefreshDelay", + "maxRefreshDelay": "maxRefreshDelay", + "refreshDelayFactor": 1.0, + "indexesRef": "indexesRef", + "resolveViaPredicatesOnly": true, + "expirationWarningThreshold": "expirationWarningThreshold" + }, + "httpMetadataResolverAttributes": { + "httpClientRef": "httpClientRef", + "connectionRequestTimeout": "connectionRequestTimeout", + "requestTimeout": "requestTimeout", + "socketTimeout": "socketTimeout", + "disregardTLSCertificate": true, + "tlsTrustEngineRef": "tlsTrustEngineRef", + "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", + "proxyHost": "proxyHost", + "proxyPort": "proxyPort", + "proxyUser": "proxyUser", + "proxyPassword": "proxyPassword", + "httpCaching": "none", + "httpCacheDirectory": "httpCacheDirectory", + "httpMaxCacheEntries": 1, + "httpMaxCacheEntrySize": 2 + } +}""" + def updatedResolver = new ObjectMapper().readValue(postedJsonBody.bytes, FileBackedHttpMetadataResolver) + 1 * repository.findByResourceId(randomResourceId) >> existingResolver + 1 * repository.save(_) >> updatedResolver + + def expectedResponseContentType = APPLICATION_JSON_UTF8 + + when: + def result = mockMvc.perform( + put('/api/MetadataProvider/FileBackedHttp') + .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 randomResourceId = "resourceId" + def existingResolverJson = """{ + "name": "name", + "resourceId": "$randomResourceId", + "requireValidMetadata": true, + "failFastInitialization": true, + "sortKey": 7, + "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", + "useDefaultPredicateRegistry": true, + "satisfyAnyPredicates": true, + "metadataFilters": [], + "reloadableMetadataResolverAttributes": { + "parserPoolRef": "parserPoolRef", + "taskTimerRef": "taskTimerRef", + "minRefreshDelay": "minRefreshDelay", + "maxRefreshDelay": "maxRefreshDelay", + "refreshDelayFactor": 1.0, + "indexesRef": "indexesRef", + "resolveViaPredicatesOnly": true, + "expirationWarningThreshold": "expirationWarningThreshold" + }, + "httpMetadataResolverAttributes": { + "httpClientRef": "httpClientRef", + "connectionRequestTimeout": "connectionRequestTimeout", + "requestTimeout": "requestTimeout", + "socketTimeout": "socketTimeout", + "disregardTLSCertificate": true, + "tlsTrustEngineRef": "tlsTrustEngineRef", + "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", + "proxyHost": "proxyHost", + "proxyPort": "proxyPort", + "proxyUser": "proxyUser", + "proxyPassword": "proxyPassword", + "httpCaching": "none", + "httpCacheDirectory": "httpCacheDirectory", + "httpMaxCacheEntries": 1, + "httpMaxCacheEntrySize": 2 + } +}""" + def existingResolver = new ObjectMapper().readValue(existingResolverJson.bytes, FileBackedHttpMetadataResolver) + def existingResolverVersion = existingResolver.hashCode() + + def randomName = randomGenerator.randomString(10) + def randomVersion = randomGenerator.randomInt() + def postedJsonBody = """{ + "name": "$randomName", + "resourceId": "$randomResourceId", + "version": "$randomVersion", + "requireValidMetadata": true, + "failFastInitialization": true, + "sortKey": 7, + "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", + "useDefaultPredicateRegistry": true, + "satisfyAnyPredicates": true, + "metadataFilters": [], + "reloadableMetadataResolverAttributes": { + "parserPoolRef": "parserPoolRef", + "taskTimerRef": "taskTimerRef", + "minRefreshDelay": "minRefreshDelay", + "maxRefreshDelay": "maxRefreshDelay", + "refreshDelayFactor": 1.0, + "indexesRef": "indexesRef", + "resolveViaPredicatesOnly": true, + "expirationWarningThreshold": "expirationWarningThreshold" + }, + "httpMetadataResolverAttributes": { + "httpClientRef": "httpClientRef", + "connectionRequestTimeout": "connectionRequestTimeout", + "requestTimeout": "requestTimeout", + "socketTimeout": "socketTimeout", + "disregardTLSCertificate": true, + "tlsTrustEngineRef": "tlsTrustEngineRef", + "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", + "proxyHost": "proxyHost", + "proxyPort": "proxyPort", + "proxyUser": "proxyUser", + "proxyPassword": "proxyPassword", + "httpCaching": "none", + "httpCacheDirectory": "httpCacheDirectory", + "httpMaxCacheEntries": 1, + "httpMaxCacheEntrySize": 2 + } +}""" + 1 * repository.findByResourceId(randomResourceId) >> existingResolver + 0 * repository.save(_) + + when: + def result = mockMvc.perform( + put('/api/MetadataProvider/FileBackedHttp') + .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 randomResourceId = randomGenerator.randomId() + def postedJsonBody = """{ + "name": "name", + "resourceId": "$randomResourceId", + "requireValidMetadata": true, + "failFastInitialization": true, + "sortKey": 7, + "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", + "useDefaultPredicateRegistry": true, + "satisfyAnyPredicates": true, + "metadataFilters": [], + "reloadableMetadataResolverAttributes": { + "parserPoolRef": "parserPoolRef", + "taskTimerRef": "taskTimerRef", + "minRefreshDelay": "minRefreshDelay", + "maxRefreshDelay": "maxRefreshDelay", + "refreshDelayFactor": 1.0, + "indexesRef": "indexesRef", + "resolveViaPredicatesOnly": true, + "expirationWarningThreshold": "expirationWarningThreshold" + }, + "httpMetadataResolverAttributes": { + "httpClientRef": "httpClientRef", + "connectionRequestTimeout": "connectionRequestTimeout", + "requestTimeout": "requestTimeout", + "socketTimeout": "socketTimeout", + "disregardTLSCertificate": true, + "tlsTrustEngineRef": "tlsTrustEngineRef", + "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", + "proxyHost": "proxyHost", + "proxyPort": "proxyPort", + "proxyUser": "proxyUser", + "proxyPassword": "proxyPassword", + "httpCaching": "none", + "httpCacheDirectory": "httpCacheDirectory", + "httpMaxCacheEntries": 1, + "httpMaxCacheEntrySize": 2 + } +}""" + 1 * repository.findByResourceId(randomResourceId) >> null + 0 * repository.save(_) + + when: + def result = mockMvc.perform( + put('/api/MetadataProvider/FileBackedHttp') + .contentType(APPLICATION_JSON_UTF8) + .content(postedJsonBody)) + + then: + result.andExpect(status().isNotFound()) + } +} 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 d4aea60ba..d0beb24d2 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 @@ -80,7 +80,8 @@ class FileBackedHttpMetadataResolverRepositoryTests extends Specification { def "FileBackedHttpMetadataResolver hashcode works as desired"() { given: - // TODO: Ask JJ why an empty reloadableMetadataResolverAttributes object results in a null object for item2 below + // TODO: There is weirdness here if reloadableMetadataResolverAttributes is empty. + // I suspect similar weirdness if httpMetadataResolverAttributes is an empty object, too. def resolverJson = '''{ "name": "name", "requireValidMetadata": true, @@ -91,6 +92,7 @@ class FileBackedHttpMetadataResolverRepositoryTests extends Specification { "satisfyAnyPredicates": true, "metadataFilters": [], "reloadableMetadataResolverAttributes": { + "parserPoolRef": "parserPoolRef" }, "httpMetadataResolverAttributes": { "httpClientRef": "httpClientRef", @@ -117,7 +119,6 @@ class FileBackedHttpMetadataResolverRepositoryTests extends Specification { entityManager.flush() then: - entityManager.clear() def item1 = repositoryUnderTest.findByResourceId(persistedResolver.resourceId) entityManager.clear() def item2 = repositoryUnderTest.findByResourceId(persistedResolver.resourceId) From 7d0c33ce669a0ba08294002e3c0ec2d3fa9df02f Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Fri, 25 May 2018 12:00:57 -0700 Subject: [PATCH 07/15] [SHIBUI-517] Small refactor. --- .../FileBackedHttpMetadataProviderControllerTests.groovy | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy index 377722b5d..1cf30ab69 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy @@ -7,7 +7,6 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.repository.FileBackedHttpMetadataResolverRepository import edu.internet2.tier.shibboleth.admin.ui.util.RandomGenerator -import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator import groovy.json.JsonOutput import groovy.json.JsonSlurper import org.springframework.boot.autoconfigure.domain.EntityScan @@ -30,7 +29,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") class FileBackedHttpMetadataProviderControllerTests extends Specification { - TestObjectGenerator testObjectGenerator RandomGenerator randomGenerator ObjectMapper mapper @@ -40,7 +38,6 @@ class FileBackedHttpMetadataProviderControllerTests extends Specification { def setup() { randomGenerator = new RandomGenerator() - //testObjectGenerator = new TestObjectGenerator(attributeUtility) mapper = new ObjectMapper() controller = new FileBackedHttpMetadataProviderController ( From f96a45d21ac49f7ea99e50168e788cafdaaf6544 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 8 Jun 2018 13:51:05 -0400 Subject: [PATCH 08/15] SHIBUI-517[532] work in progress --- .../JPAMetadataResolverServiceImpl.groovy | 88 +++++++++++-------- .../FileBackedHttpMetadataResolver.java | 9 ++ ...HttpMetadataResolverRepositoryTests.groovy | 6 +- ...JPAMetadataResolverServiceImplTests.groovy | 53 +++++++++++ .../admin/ui/util/TestHelpers.groovy | 12 +++ .../admin/ui/util/TestObjectGenerator.groovy | 22 +++++ backend/src/test/resources/conf/532.xml | 15 ++++ 7 files changed, 165 insertions(+), 40 deletions(-) create mode 100644 backend/src/test/resources/conf/532.xml 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 f28480e73..fdf84927d 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 @@ -1,28 +1,29 @@ package edu.internet2.tier.shibboleth.admin.ui.service; -import com.google.common.base.Predicate; -import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter; +import com.google.common.base.Predicate +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget -import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository +import groovy.util.logging.Slf4j import groovy.xml.DOMBuilder -import groovy.xml.MarkupBuilder; -import net.shibboleth.utilities.java.support.resolver.ResolverException; -import org.opensaml.saml.common.profile.logic.EntityIdPredicate; -import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver; -import org.opensaml.saml.metadata.resolver.MetadataResolver; -import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver; -import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; -import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; -import org.opensaml.saml.saml2.core.Attribute; -import org.opensaml.saml.saml2.metadata.EntityDescriptor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.w3c.dom.Document; - -public class JPAMetadataResolverServiceImpl implements MetadataResolverService { - private static final Logger logger = LoggerFactory.getLogger(JPAMetadataResolverServiceImpl.class); +import groovy.xml.MarkupBuilder +import net.shibboleth.utilities.java.support.resolver.ResolverException +import org.opensaml.saml.common.profile.logic.EntityIdPredicate +import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver +import org.opensaml.saml.metadata.resolver.MetadataResolver +import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain +import org.opensaml.saml.saml2.core.Attribute +import org.opensaml.saml.saml2.metadata.EntityDescriptor + +import org.springframework.beans.factory.annotation.Autowired +import org.w3c.dom.Document + +@Slf4j +class JPAMetadataResolverServiceImpl implements MetadataResolverService { @Autowired private MetadataResolver metadataResolver @@ -35,52 +36,52 @@ public class JPAMetadataResolverServiceImpl implements MetadataResolverService { // TODO: enhance @Override - public void reloadFilters(String metadataResolverName) { - ChainingMetadataResolver chainingMetadataResolver = (ChainingMetadataResolver)metadataResolver; - - // MetadataResolver targetMetadataResolver = chainingMetadataResolver.getResolvers().stream().filter(r -> r.getId().equals(metadataResolverName)).findFirst().get(); + void reloadFilters(String metadataResolverName) { + ChainingMetadataResolver chainingMetadataResolver = (ChainingMetadataResolver)metadataResolver MetadataResolver targetMetadataResolver = chainingMetadataResolver.getResolvers().find { it.id == metadataResolverName } - edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver jpaMetadataResolver = metadataResolverRepository.findByName(metadataResolverName); + edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver jpaMetadataResolver = metadataResolverRepository.findByName(metadataResolverName) if (targetMetadataResolver && targetMetadataResolver.getMetadataFilter() instanceof MetadataFilterChain) { - MetadataFilterChain metadataFilterChain = (MetadataFilterChain)targetMetadataResolver.getMetadataFilter(); + MetadataFilterChain metadataFilterChain = (MetadataFilterChain)targetMetadataResolver.getMetadataFilter() - List metadataFilters = new ArrayList<>(); + List metadataFilters = new ArrayList<>() for (edu.internet2.tier.shibboleth.admin.ui.domain.MetadataFilter metadataFilter : jpaMetadataResolver.getMetadataFilters()) { if (metadataFilter instanceof EntityAttributesFilter) { - EntityAttributesFilter entityAttributesFilter = (EntityAttributesFilter) metadataFilter; + EntityAttributesFilter entityAttributesFilter = (EntityAttributesFilter) metadataFilter - org.opensaml.saml.metadata.resolver.filter.impl.EntityAttributesFilter target = new org.opensaml.saml.metadata.resolver.filter.impl.EntityAttributesFilter(); - Map, Collection> rules = new HashMap<>(); + org.opensaml.saml.metadata.resolver.filter.impl.EntityAttributesFilter target = new org.opensaml.saml.metadata.resolver.filter.impl.EntityAttributesFilter() + Map, Collection> rules = new HashMap<>() if (entityAttributesFilter.getEntityAttributesFilterTarget().getEntityAttributesFilterTargetType() == EntityAttributesFilterTarget.EntityAttributesFilterTargetType.ENTITY) { rules.put( new EntityIdPredicate(entityAttributesFilter.getEntityAttributesFilterTarget().getValue()), (List)(List)entityAttributesFilter.getAttributes() - ); + ) } - target.setRules(rules); - metadataFilters.add(target); + target.setRules(rules) + metadataFilters.add(target) } } - metadataFilterChain.setFilters(metadataFilters); + metadataFilterChain.setFilters(metadataFilters) } if (metadataResolver instanceof RefreshableMetadataResolver) { try { - ((RefreshableMetadataResolver)metadataResolver).refresh(); + ((RefreshableMetadataResolver)metadataResolver).refresh() } catch (ResolverException e) { - logger.warn("error refreshing metadataResolver " + metadataResolverName, e); + log.warn("error refreshing metadataResolver " + metadataResolverName, e) } } } // TODO: enhance @Override - public Document generateConfiguration() { + Document generateConfiguration() { // TODO: this can probably be a better writer new StringWriter().withCloseable { writer -> def xml = new MarkupBuilder(writer) + xml.omitEmptyAttributes = true + xml.omitNullAttributes = true xml.MetadataProvider(id: 'ShibbolethMetadata', xmlns: 'urn:mace:shibboleth:2.0:metadata', @@ -135,4 +136,17 @@ public class JPAMetadataResolverServiceImpl implements MetadataResolverService { return DOMBuilder.newInstance().parseText(writer.toString()) } } + + void constructXmlNodeFor(FileBackedHttpMetadataResolver resolver, def markupBuilderDelegate) { + def attributes = [id: "${resolver.name}", + 'xsi:type': 'FileBackedHTTPMetadataProvider', + backingFile: resolver.backingFile, + metadataURL: resolver.metadataURL, + minRefreshDelay: resolver.reloadableMetadataResolverAttributes?.minRefreshDelay, + maxRefreshDelay: resolver.reloadableMetadataResolverAttributes?.maxRefreshDelay, + refreshDelayFactor: resolver.reloadableMetadataResolverAttributes?.refreshDelayFactor] + + markupBuilderDelegate.MetadataProvider(attributes) + } + } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java index c9850ecc6..4678dca1d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java @@ -17,6 +17,15 @@ @ToString public class FileBackedHttpMetadataResolver extends MetadataResolver { + private String metadataURL; + + private String backingFile; + + private Boolean initializeFromBackupFile; + + private String backupFileInitNextRefreshDelay; + + @Embedded private ReloadableMetadataResolverAttributes reloadableMetadataResolverAttributes; 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 d0beb24d2..5074750ea 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 @@ -30,7 +30,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetada class FileBackedHttpMetadataResolverRepositoryTests extends Specification { @Autowired - FileBackedHttpMetadataResolverRepository repositoryUnderTest + MetadataResolverRepository repositoryUnderTest @Autowired EntityManager entityManager @@ -119,9 +119,9 @@ class FileBackedHttpMetadataResolverRepositoryTests extends Specification { entityManager.flush() then: - def item1 = repositoryUnderTest.findByResourceId(persistedResolver.resourceId) + def item1 = repositoryUnderTest.findByName(persistedResolver.name) entityManager.clear() - def item2 = repositoryUnderTest.findByResourceId(persistedResolver.resourceId) + def item2 = repositoryUnderTest.findByName(persistedResolver.name) item1.hashCode() == item2.hashCode() } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy index afc93df62..a20ce8eb9 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy @@ -6,6 +6,11 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository + +import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator +import edu.internet2.tier.shibboleth.admin.util.AttributeUtility +import groovy.xml.DOMBuilder +import groovy.xml.MarkupBuilder import net.shibboleth.ext.spring.resource.ResourceHelper import net.shibboleth.utilities.java.support.resolver.CriteriaSet import org.joda.time.DateTime @@ -28,6 +33,8 @@ import org.xmlunit.builder.DiffBuilder import org.xmlunit.builder.Input import spock.lang.Specification +import static edu.internet2.tier.shibboleth.admin.ui.util.TestHelpers.generatedXmlIsTheSameAsExpectedXml + @SpringBootTest @DataJpaTest @ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration]) @@ -50,6 +57,30 @@ class JPAMetadataResolverServiceImplTests extends Specification { @Autowired OpenSamlObjects openSamlObjects + @Autowired + AttributeUtility attributeUtility + + TestObjectGenerator testObjectGenerator + + DOMBuilder domBuilder + + StringWriter writer + + MarkupBuilder markupBuilder + + def setup() { + testObjectGenerator = new TestObjectGenerator(attributeUtility) + domBuilder = DOMBuilder.newInstance() + writer = new StringWriter() + markupBuilder = new MarkupBuilder(writer) + markupBuilder.omitNullAttributes = true + markupBuilder.omitEmptyAttributes = true + } + + def cleanup() { + writer.close() + } + def 'test adding a filter'() { given: def expectedXML = ''' @@ -98,6 +129,28 @@ class JPAMetadataResolverServiceImplTests extends Specification { !diff.hasDifferences() } + def 'test generating FileBackedHttMetadataResolver xml snippet'() { + given: + def resolver = testObjectGenerator.fileBackedHttpMetadataResolver() + + when: + genXmlSnippet(markupBuilder) { JPAMetadataResolverServiceImpl.cast(metadataResolverService).constructXmlNodeFor(resolver, it) } + + then: + assert generatedXmlIsTheSameAsExpectedXml('/conf/532.xml', domBuilder.parseText(writer.toString())) + } + + static genXmlSnippet(MarkupBuilder xml, Closure xmlNodeGenerator) { + xml.MetadataProvider('id': 'ShibbolethMetadata', + 'xmlns': 'urn:mace:shibboleth:2.0:metadata', + 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:type': 'ChainingMetadataProvider', + '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' + ) { + xmlNodeGenerator(delegate) + } + } + @TestConfiguration static class Config { @Autowired diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy index 1a6a085e2..3d8b834e8 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy @@ -2,6 +2,9 @@ package edu.internet2.tier.shibboleth.admin.ui.util import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.RelyingPartyOverridesRepresentation import org.apache.commons.lang.StringUtils +import org.w3c.dom.Document +import org.xmlunit.builder.DiffBuilder +import org.xmlunit.builder.Input /** * @author Bill Smith (wsmith@unicon.net) @@ -22,4 +25,13 @@ class TestHelpers { return count } + + static generatedXmlIsTheSameAsExpectedXml(String expectedXmlResource, Document generatedXml) { + def diffs = DiffBuilder.compare(Input.fromStream(this.getResourceAsStream(expectedXmlResource))).withTest(Input.fromDocument + (generatedXml)) + .ignoreComments().ignoreWhitespace().build().differences + + !DiffBuilder.compare(Input.fromStream(this.getResourceAsStream(expectedXmlResource))).withTest(Input.fromDocument(generatedXml)) + .ignoreComments().ignoreWhitespace().build().hasDifferences() + } } 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 302bdac95..b8adc23d0 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 @@ -12,10 +12,16 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationURL 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.FileBackedHttpMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes import edu.internet2.tier.shibboleth.admin.util.AttributeUtility import edu.internet2.tier.shibboleth.admin.util.MDDCConstants import org.opensaml.saml.saml2.metadata.Organization +import static edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget.EntityAttributesFilterTargetType.ENTITY +import static edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes.HttpCachingType.memory + /** * @author Bill Smith (wsmith@unicon.net) */ @@ -190,6 +196,22 @@ class TestObjectGenerator { return contactPerson } + FileBackedHttpMetadataResolver fileBackedHttpMetadataResolver() { + new FileBackedHttpMetadataResolver().with { + it.name = 'HTTPMetadata' + it.backingFile = '%{idp.home}/metadata/incommonmd.xml' + it.metadataURL = 'http://md.incommon.org/InCommon/InCommon-metadata.xml' + + it.reloadableMetadataResolverAttributes = new ReloadableMetadataResolverAttributes().with { + it.minRefreshDelay = 'PT5M' + it.maxRefreshDelay = 'PT1H' + it.refreshDelayFactor = 0.75 + it + } + it + } + } + /** * This method takes a type and a size and builds a List of that size containing objects of that type. This is * intended to be used with things that extend LocalizedName such as {@link OrganizationName}, {@link OrganizationDisplayName}, diff --git a/backend/src/test/resources/conf/532.xml b/backend/src/test/resources/conf/532.xml new file mode 100644 index 000000000..cdfd93301 --- /dev/null +++ b/backend/src/test/resources/conf/532.xml @@ -0,0 +1,15 @@ + + + + + From 546daeb50978ebfb9fe714d27c87f9e48e4ad509 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 8 Jun 2018 13:54:07 -0400 Subject: [PATCH 09/15] Polishing --- .../tier/shibboleth/admin/ui/util/TestHelpers.groovy | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy index 3d8b834e8..bbac2be5f 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy @@ -27,10 +27,6 @@ class TestHelpers { } static generatedXmlIsTheSameAsExpectedXml(String expectedXmlResource, Document generatedXml) { - def diffs = DiffBuilder.compare(Input.fromStream(this.getResourceAsStream(expectedXmlResource))).withTest(Input.fromDocument - (generatedXml)) - .ignoreComments().ignoreWhitespace().build().differences - !DiffBuilder.compare(Input.fromStream(this.getResourceAsStream(expectedXmlResource))).withTest(Input.fromDocument(generatedXml)) .ignoreComments().ignoreWhitespace().build().hasDifferences() } From 478c23e0176c2d015bccde9843c3405ce186bf02 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 8 Jun 2018 14:44:12 -0400 Subject: [PATCH 10/15] SHIBUI-517[532] --- .../JPAMetadataResolverServiceImpl.groovy | 44 +++++++++++++++---- .../FileBackedHttpMetadataResolver.java | 2 +- .../HttpMetadataResolverAttributes.java | 2 +- .../ui/domain/resolvers/MetadataResolver.java | 6 +-- 4 files changed, 40 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 fdf84927d..610aa2181 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 @@ -138,15 +138,41 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { } void constructXmlNodeFor(FileBackedHttpMetadataResolver resolver, def markupBuilderDelegate) { - def attributes = [id: "${resolver.name}", - 'xsi:type': 'FileBackedHTTPMetadataProvider', - backingFile: resolver.backingFile, - metadataURL: resolver.metadataURL, - minRefreshDelay: resolver.reloadableMetadataResolverAttributes?.minRefreshDelay, - maxRefreshDelay: resolver.reloadableMetadataResolverAttributes?.maxRefreshDelay, - refreshDelayFactor: resolver.reloadableMetadataResolverAttributes?.refreshDelayFactor] - - markupBuilderDelegate.MetadataProvider(attributes) + markupBuilderDelegate.MetadataProvider(id: resolver.name, + 'xsi:type': 'FileBackedHTTPMetadataProvider', + 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) } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java index 4678dca1d..37748e6c0 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java @@ -21,7 +21,7 @@ public class FileBackedHttpMetadataResolver extends MetadataResolver { private String backingFile; - private Boolean initializeFromBackupFile; + private Boolean initializeFromBackupFile = true; private String backupFileInitNextRefreshDelay; 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..f286fca01 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 @@ -24,7 +24,7 @@ public class HttpMetadataResolverAttributes { private String connectionRequestTimeout; - private String requestTimeout; + private String connectionTimeout; private String socketTimeout; 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 4deebcbcb..5efd6f5d2 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 @@ -36,15 +36,15 @@ public class MetadataResolver extends AbstractAuditable { @Column(unique=true) private String resourceId = UUID.randomUUID().toString(); - private Boolean requireValidMetadata; + private Boolean requireValidMetadata = true; - private Boolean failFastInitialization; + private Boolean failFastInitialization = true; private Integer sortKey; private String criterionPredicateRegistryRef; - private Boolean useDefaultPredicateRegistry; + private Boolean useDefaultPredicateRegistry = true; private Boolean satisfyAnyPredicates; From f940fc07f9e8b1fc5d3759e6cbf8eea494d7c11b Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 11 Jun 2018 11:41:33 -0400 Subject: [PATCH 11/15] SHIBUI-532 --- .../JPAMetadataResolverServiceImpl.groovy | 19 +++++++------------ ...JPAMetadataResolverServiceImplTests.groovy | 10 ++++++++-- ...JPAMetadataResolverServiceImplTests.groovy | 4 +++- 3 files changed, 18 insertions(+), 15 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 610aa2181..72fd0b2e6 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 @@ -90,14 +90,7 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { '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' ) { metadataResolverRepository.findAll().each { edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr -> - MetadataProvider(id: 'HTTPMetadata', - 'xsi:type': 'FileBackedHTTPMetadataProvider', - backingFile: '%{idp.home}/metadata/incommonmd.xml', - metadataURL: 'http://md.incommon.org/InCommon/InCommon-metadata.xml', - minRefreshDelay: 'PT5M', - maxRefreshDelay: 'PT1H', - refreshDelayFactor: '0.75' - ) { + constructXmlNodeForResolver(mr, delegate) { MetadataFilter( 'xsi:type': 'SignatureValidation', 'requireSignedRoot': 'true', @@ -115,7 +108,7 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { //TODO: enhance mr.metadataFilters.each { edu.internet2.tier.shibboleth.admin.ui.domain.MetadataFilter filter -> if (filter instanceof EntityAttributesFilter) { - EntityAttributesFilter entityAttributesFilter = (EntityAttributesFilter)filter + EntityAttributesFilter entityAttributesFilter = (EntityAttributesFilter) filter MetadataFilter('xsi:type': 'EntityAttributes') { // TODO: enhance. currently this does weird things with namespaces entityAttributesFilter.attributes.each { attribute -> @@ -132,12 +125,11 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { } } } - return DOMBuilder.newInstance().parseText(writer.toString()) } } - void constructXmlNodeFor(FileBackedHttpMetadataResolver resolver, def markupBuilderDelegate) { + void constructXmlNodeForResolver(FileBackedHttpMetadataResolver resolver, def markupBuilderDelegate, Closure childNodes) { markupBuilderDelegate.MetadataProvider(id: resolver.name, 'xsi:type': 'FileBackedHTTPMetadataProvider', backingFile: resolver.backingFile, @@ -172,7 +164,10 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { httpCaching: resolver.httpMetadataResolverAttributes?.httpCaching, httpCacheDirectory: resolver.httpMetadataResolverAttributes?.httpCacheDirectory, httpMaxCacheEntries: resolver.httpMetadataResolverAttributes?.httpMaxCacheEntries, - httpMaxCacheEntrySize: resolver.httpMetadataResolverAttributes?.httpMaxCacheEntrySize) + httpMaxCacheEntrySize: resolver.httpMetadataResolverAttributes?.httpMaxCacheEntrySize) { + + 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 7628f30de..ce88779f7 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 @@ -6,6 +6,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository +import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator import edu.internet2.tier.shibboleth.admin.util.AttributeUtility import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver import org.opensaml.saml.metadata.resolver.MetadataResolver @@ -82,6 +83,9 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification { @Autowired MetadataResolverRepository metadataResolverRepository + @Autowired + AttributeUtility attributeUtility + @Bean MetadataResolver metadataResolver() { def resolver = new ChainingMetadataResolver().with { @@ -97,8 +101,10 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification { } if (!metadataResolverRepository.findAll().iterator().hasNext()) { - edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr = new edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver() - mr.setName("incommonmd") + //Generate and test edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver. Add more as + // we implement them + def mr = new TestObjectGenerator(attributeUtility).fileBackedHttpMetadataResolver() + mr.setName("HTTPMetadata") metadataResolverRepository.save(mr) } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy index a20ce8eb9..c6ee49871 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy @@ -134,7 +134,9 @@ class JPAMetadataResolverServiceImplTests extends Specification { def resolver = testObjectGenerator.fileBackedHttpMetadataResolver() when: - genXmlSnippet(markupBuilder) { JPAMetadataResolverServiceImpl.cast(metadataResolverService).constructXmlNodeFor(resolver, it) } + genXmlSnippet(markupBuilder) { + JPAMetadataResolverServiceImpl.cast(metadataResolverService).constructXmlNodeForResolver(resolver, it) {} + } then: assert generatedXmlIsTheSameAsExpectedXml('/conf/532.xml', domBuilder.parseText(writer.toString())) From 8c4221c0ce916f35ca22ba13ea5f27ca33decbf0 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Mon, 11 Jun 2018 10:17:13 -0700 Subject: [PATCH 12/15] [SHIBUI-517] Updated/fixed tests WIP. --- ...HttpMetadataProviderControllerTests.groovy | 8 +++ .../admin/ui/util/TestObjectGenerator.groovy | 50 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy index 1cf30ab69..f70b69e5b 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy @@ -7,8 +7,11 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.repository.FileBackedHttpMetadataResolverRepository 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 @@ -30,14 +33,19 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @EntityScan("edu.internet2.tier.shibboleth.admin.ui") class FileBackedHttpMetadataProviderControllerTests extends Specification { RandomGenerator randomGenerator + TestObjectGenerator testObjectGenerator ObjectMapper mapper + @Autowired + AttributeUtility attributeUtility + def repository = Mock(FileBackedHttpMetadataResolverRepository) def controller def mockMvc def setup() { randomGenerator = new RandomGenerator() + testObjectGenerator = new TestObjectGenerator(attributeUtility) mapper = new ObjectMapper() controller = new FileBackedHttpMetadataProviderController ( 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 b8adc23d0..54d771f5b 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 @@ -35,6 +35,28 @@ class TestObjectGenerator { this.attributeUtility = attributeUtility } + 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 + } + List buildFilterList() { List filterList = new ArrayList<>() (1..generator.randomInt(4, 10)).each { @@ -212,6 +234,34 @@ class TestObjectGenerator { } } + FileBackedHttpMetadataResolver buildFileBackedHttpMetadataResolver() { + def resolver = new FileBackedHttpMetadataResolver() + resolver.name = generator.randomString(10) + resolver.requireValidMetadata = generator.randomBoolean() + resolver.failFastInitialization = generator.randomBoolean() + resolver.sortKey = generator.randomInt(0, 10) + resolver.criterionPredicateRegistryRef = generator.randomString(10) + resolver.useDefaultPredicateRegistry = generator.randomBoolean() + resolver.satisfyAnyPredicates = generator.randomBoolean() + resolver.metadataFilters = buildFilterList() + resolver.reloadableMetadataResolverAttributes = buildReloadableMetadataResolverAttributes() + resolver.httpMetadataResolverAttributes = buildHttpMetadataResolverAttributes() + return resolver + } + + ReloadableMetadataResolverAttributes buildReloadableMetadataResolverAttributes() { + def attributes = new ReloadableMetadataResolverAttributes() + attributes.parserPoolRef = generator.randomString(10) + attributes.taskTimerRef = generator.randomString(10) + attributes.minRefreshDelay = generator.randomString(5) + attributes.maxRefreshDelay = generator.randomString(5) + attributes.refreshDelayFactor = generator.randomInt(0, 5) + attributes.indexesRef = generator.randomString(10) + attributes.resolveViaPredicatesOnly = generator.randomBoolean() + attributes.expirationWarningThreshold = generator.randomString(10) + return attributes + } + /** * This method takes a type and a size and builds a List of that size containing objects of that type. This is * intended to be used with things that extend LocalizedName such as {@link OrganizationName}, {@link OrganizationDisplayName}, From cccd2220ab9e521c792f0df57139a256729cf94f Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Mon, 11 Jun 2018 10:31:51 -0700 Subject: [PATCH 13/15] [SHIBUI-517] Continuing unit tests WIP. Investigating recursion. --- .../HttpMetadataResolverAttributes.java | 2 +- ...HttpMetadataProviderControllerTests.groovy | 45 ++----------------- .../admin/ui/util/TestObjectGenerator.groovy | 6 ++- 3 files changed, 10 insertions(+), 43 deletions(-) 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 f286fca01..706c34e08 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/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy index f70b69e5b..fe7686402 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy @@ -272,48 +272,11 @@ class FileBackedHttpMetadataProviderControllerTests extends Specification { def "GET by resolver name returns the desired persisted resolver"() { given: - def randomResolverName = randomGenerator.randomString(10) - def resolverJson = """{ - "name": "$randomResolverName", - "requireValidMetadata": true, - "failFastInitialization": true, - "sortKey": 7, - "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", - "useDefaultPredicateRegistry": true, - "satisfyAnyPredicates": true, - "metadataFilters": [], - "reloadableMetadataResolverAttributes": { - "parserPoolRef": "parserPoolRef", - "taskTimerRef": "taskTimerRef", - "minRefreshDelay": "minRefreshDelay", - "maxRefreshDelay": "maxRefreshDelay", - "refreshDelayFactor": 1.0, - "indexesRef": "indexesRef", - "resolveViaPredicatesOnly": true, - "expirationWarningThreshold": "expirationWarningThreshold" - }, - "httpMetadataResolverAttributes": { - "httpClientRef": "httpClientRef", - "connectionRequestTimeout": "connectionRequestTimeout", - "requestTimeout": "requestTimeout", - "socketTimeout": "socketTimeout", - "disregardTLSCertificate": true, - "tlsTrustEngineRef": "tlsTrustEngineRef", - "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", - "proxyHost": "proxyHost", - "proxyPort": "proxyPort", - "proxyUser": "proxyUser", - "proxyPassword": "proxyPassword", - "httpCaching": "none", - "httpCacheDirectory": "httpCacheDirectory", - "httpMaxCacheEntries": 1, - "httpMaxCacheEntrySize": 2 - } -}""" + def randomResolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + def randomResolverName = randomResolver.name + def resolverJson = mapper.writeValueAsString(randomResolver) - def resolver = new ObjectMapper().readValue(resolverJson.bytes, FileBackedHttpMetadataResolver) - - 1 * repository.findByName(randomResolverName) >> resolver + 1 * repository.findByName(randomResolverName) >> randomResolver def expectedResponseContentType = APPLICATION_JSON_UTF8 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 54d771f5b..3a3605a90 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 @@ -49,9 +49,9 @@ class TestObjectGenerator { 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.connectionTimeout = generator.randomString(10) it } return attributes @@ -262,6 +262,10 @@ class TestObjectGenerator { return attributes } + HttpMetadataResolverAttributes.HttpCachingType randomHttpCachingType() { + HttpMetadataResolverAttributes.HttpCachingType.values()[generator.randomInt(0, 2)] + } + /** * This method takes a type and a size and builds a List of that size containing objects of that type. This is * intended to be used with things that extend LocalizedName such as {@link OrganizationName}, {@link OrganizationDisplayName}, From 61a524a49ca0bdfcb058ea154cfb9e0d3ff28bbf Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Mon, 11 Jun 2018 11:12:45 -0700 Subject: [PATCH 14/15] [SHIBUI-517] Fixed all tests. --- ...HttpMetadataProviderControllerTests.groovy | 369 ++---------------- ...HttpMetadataResolverRepositoryTests.groovy | 2 +- .../admin/ui/util/TestObjectGenerator.groovy | 2 +- 3 files changed, 43 insertions(+), 330 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy index fe7686402..19975e843 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/FileBackedHttpMetadataProviderControllerTests.groovy @@ -85,44 +85,10 @@ class FileBackedHttpMetadataProviderControllerTests extends Specification { def "POST a new resolver properly persists and returns the new persisted resolver"() { given: - def postedJsonBody = '''{ - "name": "name", - "requireValidMetadata": true, - "failFastInitialization": true, - "sortKey": 7, - "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", - "useDefaultPredicateRegistry": true, - "satisfyAnyPredicates": true, - "metadataFilters": [], - "reloadableMetadataResolverAttributes": { - "parserPoolRef": "parserPoolRef", - "taskTimerRef": "taskTimerRef", - "minRefreshDelay": "minRefreshDelay", - "maxRefreshDelay": "maxRefreshDelay", - "refreshDelayFactor": 1.0, - "indexesRef": "indexesRef", - "resolveViaPredicatesOnly": true, - "expirationWarningThreshold": "expirationWarningThreshold" - }, - "httpMetadataResolverAttributes": { - "httpClientRef": "httpClientRef", - "connectionRequestTimeout": "connectionRequestTimeout", - "requestTimeout": "requestTimeout", - "socketTimeout": "socketTimeout", - "disregardTLSCertificate": true, - "tlsTrustEngineRef": "tlsTrustEngineRef", - "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", - "proxyHost": "proxyHost", - "proxyPort": "proxyPort", - "proxyUser": "proxyUser", - "proxyPassword": "proxyPassword", - "httpCaching": "none", - "httpCacheDirectory": "httpCacheDirectory", - "httpMaxCacheEntries": 1, - "httpMaxCacheEntrySize": 2 - } -}''' - def resolver = new ObjectMapper().readValue(postedJsonBody.bytes, FileBackedHttpMetadataResolver) + def resolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + resolver.version = resolver.hashCode() + def postedJsonBody = mapper.writeValueAsString(resolver) + 1 * repository.findByName(resolver.getName()) >> null 1 * repository.save(_) >> resolver @@ -145,46 +111,13 @@ class FileBackedHttpMetadataProviderControllerTests extends Specification { def "POST a new resolver that has a name of a persisted resolver returns conflict"() { given: - def randomResolverName = randomGenerator.randomString(10) - def postedJsonBody = """{ - "name": "$randomResolverName", - "requireValidMetadata": true, - "failFastInitialization": true, - "sortKey": 7, - "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", - "useDefaultPredicateRegistry": true, - "satisfyAnyPredicates": true, - "metadataFilters": [], - "reloadableMetadataResolverAttributes": { - "parserPoolRef": "parserPoolRef", - "taskTimerRef": "taskTimerRef", - "minRefreshDelay": "minRefreshDelay", - "maxRefreshDelay": "maxRefreshDelay", - "refreshDelayFactor": 1.0, - "indexesRef": "indexesRef", - "resolveViaPredicatesOnly": true, - "expirationWarningThreshold": "expirationWarningThreshold" - }, - "httpMetadataResolverAttributes": { - "httpClientRef": "httpClientRef", - "connectionRequestTimeout": "connectionRequestTimeout", - "requestTimeout": "requestTimeout", - "socketTimeout": "socketTimeout", - "disregardTLSCertificate": true, - "tlsTrustEngineRef": "tlsTrustEngineRef", - "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", - "proxyHost": "proxyHost", - "proxyPort": "proxyPort", - "proxyUser": "proxyUser", - "proxyPassword": "proxyPassword", - "httpCaching": "none", - "httpCacheDirectory": "httpCacheDirectory", - "httpMaxCacheEntries": 1, - "httpMaxCacheEntrySize": 2 - } -}""" - def resolver = new ObjectMapper().readValue(postedJsonBody.bytes, FileBackedHttpMetadataResolver) - 1 * repository.findByName(randomResolverName) >> resolver + def existingResolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + def randomResolverName = existingResolver.name + def newResolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + newResolver.name = randomResolverName + def postedJsonBody = mapper.writeValueAsString(newResolver) + + 1 * repository.findByName(randomResolverName) >> existingResolver 0 * repository.save(_) when: @@ -199,56 +132,18 @@ class FileBackedHttpMetadataProviderControllerTests extends Specification { def "GET by resourceId returns the desired persisted resolver"() { given: - def randomUUID = randomGenerator.randomId() - def resolverJson = """{ - "name": "name", - "resourceId": "$randomUUID", - "requireValidMetadata": true, - "failFastInitialization": true, - "sortKey": 7, - "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", - "useDefaultPredicateRegistry": true, - "satisfyAnyPredicates": true, - "metadataFilters": [], - "reloadableMetadataResolverAttributes": { - "parserPoolRef": "parserPoolRef", - "taskTimerRef": "taskTimerRef", - "minRefreshDelay": "minRefreshDelay", - "maxRefreshDelay": "maxRefreshDelay", - "refreshDelayFactor": 1.0, - "indexesRef": "indexesRef", - "resolveViaPredicatesOnly": true, - "expirationWarningThreshold": "expirationWarningThreshold" - }, - "httpMetadataResolverAttributes": { - "httpClientRef": "httpClientRef", - "connectionRequestTimeout": "connectionRequestTimeout", - "requestTimeout": "requestTimeout", - "socketTimeout": "socketTimeout", - "disregardTLSCertificate": true, - "tlsTrustEngineRef": "tlsTrustEngineRef", - "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", - "proxyHost": "proxyHost", - "proxyPort": "proxyPort", - "proxyUser": "proxyUser", - "proxyPassword": "proxyPassword", - "httpCaching": "none", - "httpCacheDirectory": "httpCacheDirectory", - "httpMaxCacheEntries": 1, - "httpMaxCacheEntrySize": 2 - } -}""" - - def resolver = new ObjectMapper().readValue(resolverJson.bytes, FileBackedHttpMetadataResolver) - resolver.setResourceId(randomUUID) - - 1 * repository.findByResourceId(randomUUID) >> resolver + def existingResolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + existingResolver.version = existingResolver.hashCode() + def randomResourceId = existingResolver.resourceId + def resolverJson = mapper.writeValueAsString(existingResolver) + + 1 * repository.findByResourceId(randomResourceId) >> existingResolver def expectedResponseContentType = APPLICATION_JSON_UTF8 when: def result = mockMvc.perform( - get("/api/MetadataProvider/FileBackedHttp/$randomUUID")) + get("/api/MetadataProvider/FileBackedHttp/$randomResourceId")) then: result.andExpect(status().isOk()) @@ -273,6 +168,7 @@ class FileBackedHttpMetadataProviderControllerTests extends Specification { def "GET by resolver name returns the desired persisted resolver"() { given: def randomResolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + randomResolver.version = randomResolver.hashCode() def randomResolverName = randomResolver.name def resolverJson = mapper.writeValueAsString(randomResolver) @@ -306,89 +202,15 @@ class FileBackedHttpMetadataProviderControllerTests extends Specification { def "PUT allows for a successful update of an already-persisted resolver"() { given: - def randomResourceId = "resourceId" - def existingResolverJson = """{ - "name": "name", - "resourceId": "$randomResourceId", - "requireValidMetadata": true, - "failFastInitialization": true, - "sortKey": 7, - "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", - "useDefaultPredicateRegistry": true, - "satisfyAnyPredicates": true, - "metadataFilters": [], - "reloadableMetadataResolverAttributes": { - "parserPoolRef": "parserPoolRef", - "taskTimerRef": "taskTimerRef", - "minRefreshDelay": "minRefreshDelay", - "maxRefreshDelay": "maxRefreshDelay", - "refreshDelayFactor": 1.0, - "indexesRef": "indexesRef", - "resolveViaPredicatesOnly": true, - "expirationWarningThreshold": "expirationWarningThreshold" - }, - "httpMetadataResolverAttributes": { - "httpClientRef": "httpClientRef", - "connectionRequestTimeout": "connectionRequestTimeout", - "requestTimeout": "requestTimeout", - "socketTimeout": "socketTimeout", - "disregardTLSCertificate": true, - "tlsTrustEngineRef": "tlsTrustEngineRef", - "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", - "proxyHost": "proxyHost", - "proxyPort": "proxyPort", - "proxyUser": "proxyUser", - "proxyPassword": "proxyPassword", - "httpCaching": "none", - "httpCacheDirectory": "httpCacheDirectory", - "httpMaxCacheEntries": 1, - "httpMaxCacheEntrySize": 2 - } -}""" - def existingResolver = new ObjectMapper().readValue(existingResolverJson.bytes, FileBackedHttpMetadataResolver) - def existingResolverVersion = existingResolver.hashCode() - - def randomName = randomGenerator.randomString(10) - def postedJsonBody = """{ - "name": "$randomName", - "resourceId": "$randomResourceId", - "version": "$existingResolverVersion", - "requireValidMetadata": true, - "failFastInitialization": true, - "sortKey": 7, - "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", - "useDefaultPredicateRegistry": true, - "satisfyAnyPredicates": true, - "metadataFilters": [], - "reloadableMetadataResolverAttributes": { - "parserPoolRef": "parserPoolRef", - "taskTimerRef": "taskTimerRef", - "minRefreshDelay": "minRefreshDelay", - "maxRefreshDelay": "maxRefreshDelay", - "refreshDelayFactor": 1.0, - "indexesRef": "indexesRef", - "resolveViaPredicatesOnly": true, - "expirationWarningThreshold": "expirationWarningThreshold" - }, - "httpMetadataResolverAttributes": { - "httpClientRef": "httpClientRef", - "connectionRequestTimeout": "connectionRequestTimeout", - "requestTimeout": "requestTimeout", - "socketTimeout": "socketTimeout", - "disregardTLSCertificate": true, - "tlsTrustEngineRef": "tlsTrustEngineRef", - "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", - "proxyHost": "proxyHost", - "proxyPort": "proxyPort", - "proxyUser": "proxyUser", - "proxyPassword": "proxyPassword", - "httpCaching": "none", - "httpCacheDirectory": "httpCacheDirectory", - "httpMaxCacheEntries": 1, - "httpMaxCacheEntrySize": 2 - } -}""" - def updatedResolver = new ObjectMapper().readValue(postedJsonBody.bytes, FileBackedHttpMetadataResolver) + def existingResolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + existingResolver.version = existingResolver.hashCode() + def randomResourceId = existingResolver.resourceId + def updatedResolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + updatedResolver.version = existingResolver.version + updatedResolver.resourceId = existingResolver.resourceId + def postedJsonBody = mapper.writeValueAsString(updatedResolver) + + 1 * repository.findByResourceId(randomResourceId) >> existingResolver 1 * repository.save(_) >> updatedResolver @@ -410,89 +232,14 @@ class FileBackedHttpMetadataProviderControllerTests extends Specification { def "PUT of an updated resolver with an incorrect version returns a conflict"() { given: - def randomResourceId = "resourceId" - def existingResolverJson = """{ - "name": "name", - "resourceId": "$randomResourceId", - "requireValidMetadata": true, - "failFastInitialization": true, - "sortKey": 7, - "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", - "useDefaultPredicateRegistry": true, - "satisfyAnyPredicates": true, - "metadataFilters": [], - "reloadableMetadataResolverAttributes": { - "parserPoolRef": "parserPoolRef", - "taskTimerRef": "taskTimerRef", - "minRefreshDelay": "minRefreshDelay", - "maxRefreshDelay": "maxRefreshDelay", - "refreshDelayFactor": 1.0, - "indexesRef": "indexesRef", - "resolveViaPredicatesOnly": true, - "expirationWarningThreshold": "expirationWarningThreshold" - }, - "httpMetadataResolverAttributes": { - "httpClientRef": "httpClientRef", - "connectionRequestTimeout": "connectionRequestTimeout", - "requestTimeout": "requestTimeout", - "socketTimeout": "socketTimeout", - "disregardTLSCertificate": true, - "tlsTrustEngineRef": "tlsTrustEngineRef", - "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", - "proxyHost": "proxyHost", - "proxyPort": "proxyPort", - "proxyUser": "proxyUser", - "proxyPassword": "proxyPassword", - "httpCaching": "none", - "httpCacheDirectory": "httpCacheDirectory", - "httpMaxCacheEntries": 1, - "httpMaxCacheEntrySize": 2 - } -}""" - def existingResolver = new ObjectMapper().readValue(existingResolverJson.bytes, FileBackedHttpMetadataResolver) - def existingResolverVersion = existingResolver.hashCode() - - def randomName = randomGenerator.randomString(10) - def randomVersion = randomGenerator.randomInt() - def postedJsonBody = """{ - "name": "$randomName", - "resourceId": "$randomResourceId", - "version": "$randomVersion", - "requireValidMetadata": true, - "failFastInitialization": true, - "sortKey": 7, - "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", - "useDefaultPredicateRegistry": true, - "satisfyAnyPredicates": true, - "metadataFilters": [], - "reloadableMetadataResolverAttributes": { - "parserPoolRef": "parserPoolRef", - "taskTimerRef": "taskTimerRef", - "minRefreshDelay": "minRefreshDelay", - "maxRefreshDelay": "maxRefreshDelay", - "refreshDelayFactor": 1.0, - "indexesRef": "indexesRef", - "resolveViaPredicatesOnly": true, - "expirationWarningThreshold": "expirationWarningThreshold" - }, - "httpMetadataResolverAttributes": { - "httpClientRef": "httpClientRef", - "connectionRequestTimeout": "connectionRequestTimeout", - "requestTimeout": "requestTimeout", - "socketTimeout": "socketTimeout", - "disregardTLSCertificate": true, - "tlsTrustEngineRef": "tlsTrustEngineRef", - "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", - "proxyHost": "proxyHost", - "proxyPort": "proxyPort", - "proxyUser": "proxyUser", - "proxyPassword": "proxyPassword", - "httpCaching": "none", - "httpCacheDirectory": "httpCacheDirectory", - "httpMaxCacheEntries": 1, - "httpMaxCacheEntrySize": 2 - } -}""" + def existingResolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + existingResolver.version = existingResolver.hashCode() + def randomResourceId = existingResolver.resourceId + def updatedResolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + updatedResolver.version = updatedResolver.hashCode() + updatedResolver.resourceId = existingResolver.resourceId + def postedJsonBody = mapper.writeValueAsString(updatedResolver) + 1 * repository.findByResourceId(randomResourceId) >> existingResolver 0 * repository.save(_) @@ -508,45 +255,11 @@ class FileBackedHttpMetadataProviderControllerTests extends Specification { def "PUT of a resolver that is not persisted returns not found"() { given: - def randomResourceId = randomGenerator.randomId() - def postedJsonBody = """{ - "name": "name", - "resourceId": "$randomResourceId", - "requireValidMetadata": true, - "failFastInitialization": true, - "sortKey": 7, - "criterionPredicateRegistryRef": "criterionPredicateRegistryRef", - "useDefaultPredicateRegistry": true, - "satisfyAnyPredicates": true, - "metadataFilters": [], - "reloadableMetadataResolverAttributes": { - "parserPoolRef": "parserPoolRef", - "taskTimerRef": "taskTimerRef", - "minRefreshDelay": "minRefreshDelay", - "maxRefreshDelay": "maxRefreshDelay", - "refreshDelayFactor": 1.0, - "indexesRef": "indexesRef", - "resolveViaPredicatesOnly": true, - "expirationWarningThreshold": "expirationWarningThreshold" - }, - "httpMetadataResolverAttributes": { - "httpClientRef": "httpClientRef", - "connectionRequestTimeout": "connectionRequestTimeout", - "requestTimeout": "requestTimeout", - "socketTimeout": "socketTimeout", - "disregardTLSCertificate": true, - "tlsTrustEngineRef": "tlsTrustEngineRef", - "httpClientSecurityParametersRef": "httpClientSecurityParametersRef", - "proxyHost": "proxyHost", - "proxyPort": "proxyPort", - "proxyUser": "proxyUser", - "proxyPassword": "proxyPassword", - "httpCaching": "none", - "httpCacheDirectory": "httpCacheDirectory", - "httpMaxCacheEntries": 1, - "httpMaxCacheEntrySize": 2 - } -}""" + def randomResolver = testObjectGenerator.buildFileBackedHttpMetadataResolver() + randomResolver.version = randomResolver.hashCode() + def randomResourceId = randomResolver.resourceId + def postedJsonBody = mapper.writeValueAsString(randomResolver) + 1 * repository.findByResourceId(randomResourceId) >> null 0 * repository.save(_) 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 5074750ea..c68667042 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 @@ -97,7 +97,7 @@ class FileBackedHttpMetadataResolverRepositoryTests extends Specification { "httpMetadataResolverAttributes": { "httpClientRef": "httpClientRef", "connectionRequestTimeout": "connectionRequestTimeout", - "requestTimeout": "requestTimeout", + "connectionTimeout": "connectionTimeout", "socketTimeout": "socketTimeout", "disregardTLSCertificate": true, "tlsTrustEngineRef": "tlsTrustEngineRef", 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 3a3605a90..da541f5ed 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 @@ -243,7 +243,7 @@ class TestObjectGenerator { resolver.criterionPredicateRegistryRef = generator.randomString(10) resolver.useDefaultPredicateRegistry = generator.randomBoolean() resolver.satisfyAnyPredicates = generator.randomBoolean() - resolver.metadataFilters = buildFilterList() + resolver.metadataFilters = [] resolver.reloadableMetadataResolverAttributes = buildReloadableMetadataResolverAttributes() resolver.httpMetadataResolverAttributes = buildHttpMetadataResolverAttributes() return resolver From c5a588a924520b444b38b5be4f44e56bc3736b4b Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 11 Jun 2018 14:58:14 -0400 Subject: [PATCH 15/15] Fix master merge --- .../admin/ui/repository/MetadataResolverRepositoryTest.groovy | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy index 414dfa73f..76cb92e68 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy @@ -6,6 +6,9 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects +import edu.internet2.tier.shibboleth.admin.ui.service.JPAEntityDescriptorServiceImpl +import edu.internet2.tier.shibboleth.admin.ui.service.JPAEntityServiceImpl import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest