From 3a55e5a45bdf5ecd6e43e7f65274907a104bfd4c Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 26 Nov 2018 16:15:57 -0500 Subject: [PATCH] SHIBUI-979 WIP --- .../ui/domain/filters/NameIdFormatFilter.java | 28 ++++++++++++++ ...ymorphicFiltersJacksonHandlingTests.groovy | 38 +++++++++++++++++++ .../repository/FilterRepositoryTests.groovy | 15 ++++++++ .../admin/ui/util/TestObjectGenerator.groovy | 25 ++++++++++-- 4 files changed, 102 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilter.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilter.java index 4c15f3040..0817d338c 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilter.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilter.java @@ -1,11 +1,17 @@ package edu.internet2.tier.shibboleth.admin.ui.domain.filters; +import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; +import javax.persistence.ElementCollection; +import javax.persistence.Embeddable; import javax.persistence.Entity; +import javax.persistence.OrderColumn; +import java.util.List; @Entity @EqualsAndHashCode(callSuper = true) @@ -17,4 +23,26 @@ public class NameIdFormatFilter extends MetadataFilter { public NameIdFormatFilter() { type = "NameIDFormat"; } + + private Boolean removeExistingFormats = false; + + @ElementCollection + @OrderColumn + private List formats; + + @Embeddable + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Setter + @EqualsAndHashCode + public static class FormatAndTarget { + private String format; + private String value; + private Type type; + + private enum Type { + ENTITY, CONDITION_REF, CONDITION_SCRIPT + } + } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/filters/PolymorphicFiltersJacksonHandlingTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/filters/PolymorphicFiltersJacksonHandlingTests.groovy index e5aa4380d..adff06db3 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/filters/PolymorphicFiltersJacksonHandlingTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/filters/PolymorphicFiltersJacksonHandlingTests.groovy @@ -175,4 +175,42 @@ class PolymorphicFiltersJacksonHandlingTests extends Specification { EntityAttributesFilter.class.cast(filter).entityAttributesFilterTarget.entityAttributesFilterTargetType.name() == 'ENTITY' EntityAttributesFilter.class.cast(filter).entityAttributesFilterTarget.value == ['GATCCLk32V'] } + + def "Correct polymorphic serialization of NameIdFormatFilter"() { + given: + def givenFilterJson = """ + { + "@type" : "NameIDFormat", + "name" : "NameIDFormat", + "resourceId" : "20147f53-e368-4911-921a-2e24598e37f8", + "filterEnabled" : true, + "removeExistingFormats" : false, + "formats" : [ { + "format" : "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", + "value" : "https://sp1.example.org", + "type" : "ENTITY" + }, { + "format" : "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", + "value" : "https://sp2.example.org", + "type" : "ENTITY" + }, { + "format" : "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", + "value" : "input.getEntityID().equals(\\"https://sp1.example.org\\");", + "type" : "CONDITION_SCRIPT" + } ] + }""" + + when: + def deSerializedFilter = mapper.readValue(givenFilterJson, MetadataFilter) + def json = mapper.writeValueAsString(deSerializedFilter) + println(json) + def roundTripFilter = mapper.readValue(json, MetadataFilter) + + then: + roundTripFilter == deSerializedFilter + + and: + deSerializedFilter instanceof NameIdFormatFilter + roundTripFilter instanceof NameIdFormatFilter + } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/FilterRepositoryTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/FilterRepositoryTests.groovy index d7b59df55..5d9829ad9 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/FilterRepositoryTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/FilterRepositoryTests.groovy @@ -6,6 +6,7 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.Internationalization import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter +import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest @@ -15,6 +16,8 @@ import spock.lang.Specification import javax.persistence.EntityManager +import static edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator.* + @DataJpaTest @ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration, TestConfiguration, InternationalizationConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @@ -70,4 +73,16 @@ class FilterRepositoryTests extends Specification { item1.hashCode() == item2.hashCode() } + + def "NameIdFormatFilter is able to be persisted to RDBMS"() { + given: + def nameIdFormatFilter = TestObjectGenerator.nameIdFormatFilter() + + when: + def persistedFilter = repositoryUnderTest.save(nameIdFormatFilter) + + then: + persistedFilter.audId > 0L + persistedFilter.formats.size() == 3 + } } 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 f726bde01..f07dd212b 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 @@ -15,6 +15,11 @@ import org.opensaml.saml.saml2.metadata.Organization import java.nio.file.Files import java.util.function.Supplier +import static edu.internet2.tier.shibboleth.admin.ui.domain.filters.NameIdFormatFilter.* +import static edu.internet2.tier.shibboleth.admin.ui.domain.filters.NameIdFormatFilter.FormatAndTarget.* +import static edu.internet2.tier.shibboleth.admin.ui.domain.filters.NameIdFormatFilter.FormatAndTarget.Type.* +import static edu.internet2.tier.shibboleth.admin.ui.domain.filters.NameIdFormatFilter.FormatAndTarget.Type.* + /** * @author Bill Smith (wsmith@unicon.net) */ @@ -169,6 +174,7 @@ class TestObjectGenerator { it } } + EntityRoleWhiteListFilter entityRoleWhitelistFilter() { new EntityRoleWhiteListFilter().with { it.name = 'EntityRoleWhiteList' @@ -213,9 +219,20 @@ class TestObjectGenerator { } } - NameIdFormatFilter nameIdFormatFilter() { + static NameIdFormatFilter nameIdFormatFilter() { return new NameIdFormatFilter().with { it.name = "NameIDFormat" + it.formats = [ + new FormatAndTarget( + format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', + type: Type.ENTITY, value: 'https://sp1.example.org'), + new FormatAndTarget( + format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', + type: Type.ENTITY, value: 'https://sp2.example.org'), + new FormatAndTarget( + format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', + type: Type.CONDITION_SCRIPT, value: 'input.getEntityID().equals("https://sp1.example.org");') + ] it } } @@ -276,12 +293,12 @@ class TestObjectGenerator { List buildAttributesList() { List attributes = new ArrayList<>() - customPropertiesConfiguration.getOverrides().each {override -> + customPropertiesConfiguration.getOverrides().each { override -> if (generator.randomBoolean()) { switch (ModelRepresentationConversions.AttributeTypes.valueOf(override.getDisplayType().toUpperCase())) { case ModelRepresentationConversions.AttributeTypes.BOOLEAN: if (override.getPersistType() != null && - override.getPersistType() != override.getDisplayType()) { + override.getPersistType() != override.getDisplayType()) { attributes.add(attributeUtility.createAttributeWithStringValues(override.getAttributeName(), override.getAttributeFriendlyName(), generator.randomString(30))) } else { attributes.add(attributeUtility.createAttributeWithBooleanValue(override.getAttributeName(), override.getAttributeFriendlyName(), generator.randomBoolean())) @@ -326,7 +343,7 @@ class TestObjectGenerator { switch (ModelRepresentationConversions.AttributeTypes.valueOf(override.getDisplayType().toUpperCase())) { case ModelRepresentationConversions.AttributeTypes.BOOLEAN: if (override.getPersistType() != null && - override.getPersistType() != override.getDisplayType()) { + override.getPersistType() != override.getDisplayType()) { representation.put(override.getName(), generator.randomString(30)) } else { representation.put(override.getName(), generator.randomBoolean())