From 0e5b35c252a8bc5d76f11cf5bc486f224e24c069 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 24 Oct 2018 10:12:42 -0400 Subject: [PATCH] SHIBUI-906: SHIBUI-951 --- ...tadataSourcesUiDefinitionController.groovy | 40 ++++++++++----- ...sonSchemaValidatingControllerAdvice.groovy | 16 +++++- .../JPAMetadataResolverServiceImpl.groovy | 16 +++--- .../JsonSchemaComponentsConfiguration.java | 50 +++++++++++++++++++ ...hemaValidationComponentsConfiguration.java | 30 ----------- ...oryJsonSchemaResourceLocationRegistry.java | 31 ++++++++++++ .../jsonschema/JsonSchemaLocationLookup.java | 24 +++++++++ ...n.java => JsonSchemaResourceLocation.java} | 43 +++++++++++----- .../JsonSchemaResourceLocationRegistry.java | 37 ++++++++++++++ .../src/main/resources/application.properties | 1 + ... entity-attributes-filters-ui-schema.json} | 0 ...efinitionControllerIntegrationTests.groovy | 20 +++++--- ...JPAMetadataResolverServiceImplTests.groovy | 6 ++- 13 files changed, 241 insertions(+), 73 deletions(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java delete mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaValidationComponentsConfiguration.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/InMemoryJsonSchemaResourceLocationRegistry.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java rename backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/{MetadataSourcesJsonSchemaResourceLocation.java => JsonSchemaResourceLocation.java} (55%) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocationRegistry.java rename backend/src/main/resources/{entity-attributes.schema.json => entity-attributes-filters-ui-schema.json} (100%) diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy index 319951144..1425b5af1 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy @@ -2,13 +2,20 @@ package edu.internet2.tier.shibboleth.admin.ui.controller import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.configuration.CustomPropertiesConfiguration -import edu.internet2.tier.shibboleth.admin.ui.jsonschema.MetadataSourcesJsonSchemaResourceLocation +import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup +import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation +import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocationRegistry +import org.springframework.beans.factory.BeanInitializationException import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController +import javax.annotation.PostConstruct + +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.metadataSourcesSchema +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.ShemaType.METADATA_SOURCES import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR /** @@ -23,7 +30,9 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR class MetadataSourcesUiDefinitionController { @Autowired - MetadataSourcesJsonSchemaResourceLocation jsonSchemaLocation + JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry + + JsonSchemaResourceLocation jsonSchemaLocation @Autowired ObjectMapper jacksonObjectMapper @@ -48,6 +57,11 @@ class MetadataSourcesUiDefinitionController { } } + @PostConstruct + void init() { + this.jsonSchemaLocation = metadataSourcesSchema(this.jsonSchemaResourceLocationRegistry); + } + private void addReleaseAttributesToJson(Object json) { json['data'] = customPropertiesConfiguration.getAttributes().collect { [key: it['name'], label: it['displayName']] @@ -63,12 +77,12 @@ class MetadataSourcesUiDefinitionController { property = [$ref: '#/definitions/' + it['name']] } else { property = - [title: it['displayName'], - description: it['helpText'], - type: it['displayType'], - default: it['defaultValue']] + [title : it['displayName'], + description: it['helpText'], + type : it['displayType'], + default : it['defaultValue']] } - properties[(String)it['name']] = property + properties[(String) it['name']] = property } json['properties'] = properties } @@ -77,22 +91,22 @@ class MetadataSourcesUiDefinitionController { customPropertiesConfiguration.getOverrides().stream().filter { it -> it['displayType'] && (it['displayType'] == 'list' || it['displayType'] == 'set') }.each { - def definition = [title: it['displayName'], - description: it['helpText'], - type: 'array', - default: null] + def definition = [title : it['displayName'], + description: it['helpText'], + type : 'array', + default : null] if (it['displayType'] == 'set') { definition['uniqueItems'] = true } else if (it['displayType'] == 'list') { definition['uniqueItems'] = false } - def items = [type: 'string', + def items = [type : 'string', minLength: '1', // TODO: should this be configurable? maxLength: '255'] //TODO: or this? items.widget = [id: 'datalist', data: it['defaultValues']] definition['items'] = items - json[(String)it['name']] = definition + json[(String) it['name']] = definition } } } diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy index 4bc76ce2e..cf342eef9 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy @@ -2,6 +2,7 @@ package edu.internet2.tier.shibboleth.admin.ui.jsonschema import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import mjson.Json +import org.springframework.beans.factory.BeanInitializationException import org.springframework.beans.factory.annotation.Autowired import org.springframework.core.MethodParameter import org.springframework.http.HttpInputMessage @@ -13,8 +14,12 @@ import org.springframework.web.bind.annotation.ExceptionHandler import org.springframework.web.context.request.WebRequest import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter +import javax.annotation.PostConstruct import java.lang.reflect.Type +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.metadataSourcesSchema +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.ShemaType.METADATA_SOURCES + /** * Controller advice implementation for validating relying party overrides payload coming from UI layer * against pre-defined JSON schema. @@ -25,7 +30,9 @@ import java.lang.reflect.Type class RelyingPartyOverridesJsonSchemaValidatingControllerAdvice extends RequestBodyAdviceAdapter { @Autowired - MetadataSourcesJsonSchemaResourceLocation schemaLocation + JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry + + JsonSchemaResourceLocation jsonSchemaLocation @Override boolean supports(MethodParameter methodParameter, Type targetType, Class> converterType) { @@ -36,7 +43,7 @@ class RelyingPartyOverridesJsonSchemaValidatingControllerAdvice extends RequestB Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { def relyingPartyOverrides = EntityDescriptorRepresentation.cast(body).relyingPartyOverrides def relyingPartyOverridesJson = Json.make([relyingPartyOverrides: relyingPartyOverrides]) - def schema = Json.schema(this.schemaLocation.uri) + def schema = Json.schema(this.jsonSchemaLocation.uri) def validationResult = schema.validate(relyingPartyOverridesJson) if (!validationResult.at('ok')) { throw new JsonSchemaValidationFailedException(validationResult.at('errors').asList()) @@ -48,4 +55,9 @@ class RelyingPartyOverridesJsonSchemaValidatingControllerAdvice extends RequestB final ResponseEntity handleUserNotFoundException(JsonSchemaValidationFailedException ex, WebRequest request) { new ResponseEntity<>([errors: ex.errors], HttpStatus.BAD_REQUEST) } + + @PostConstruct + void init() { + this.jsonSchemaLocation = metadataSourcesSchema(this.jsonSchemaResourceLocationRegistry); + } } 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 4e6879d0f..4a95484e8 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 @@ -125,15 +125,15 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { resolversPositionOrderContainerService.allMetadataResolversInDefinedOrderOrUnordered.each { edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr -> - //TODO: We do not currently marshall the internal incommon chaining resolver (with BaseMetadataResolver type) - if ((mr.type != 'BaseMetadataResolver') && (mr.enabled)) { - constructXmlNodeForResolver(mr, delegate) { - //TODO: enhance - mr.metadataFilters.each { edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter filter -> - constructXmlNodeForFilter(filter, delegate) + //TODO: We do not currently marshall the internal incommon chaining resolver (with BaseMetadataResolver type) + if ((mr.type != 'BaseMetadataResolver') && (mr.enabled)) { + constructXmlNodeForResolver(mr, delegate) { + //TODO: enhance + mr.metadataFilters.each { edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter filter -> + constructXmlNodeForFilter(filter, delegate) + } } } - } } } return DOMBuilder.newInstance().parseText(writer.toString()) @@ -407,4 +407,4 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java new file mode 100644 index 000000000..8d70fa410 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java @@ -0,0 +1,50 @@ +package edu.internet2.tier.shibboleth.admin.ui.configuration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation; +import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocationRegistry; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ResourceLoader; + +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.*; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.ShemaType.ENTITY_ATTRIBUTES_FILTERS; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.ShemaType.METADATA_SOURCES; + +/** + * @author Dmitriy Kopylenko + */ +@Configuration +@ConfigurationProperties("shibui") +public class JsonSchemaComponentsConfiguration { + + //Configured via @ConfigurationProperties (using setter method) with 'shibui.metadata-sources-ui-schema-location' property and default + //value set here if that property is not explicitly set in application.properties + @Setter + private String metadataSourcesUiSchemaLocation = "classpath:metadata-sources-ui-schema.json"; + + //Configured via @ConfigurationProperties (using setter method) with 'shibui.entity-attributes-filters-ui-schema-location' property and + // default value set here if that property is not explicitly set in application.properties + @Setter + private String entityAttributesFiltersUiSchemaLocation = "classpath:entity-attributes-filters-ui-schema.json"; + + @Bean + public JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(ResourceLoader resourceLoader, ObjectMapper jacksonMapper) { + return JsonSchemaResourceLocationRegistry.inMemory() + .register(METADATA_SOURCES, JsonSchemaLocationBuilder.with() + .jsonSchemaLocation(metadataSourcesUiSchemaLocation) + .resourceLoader(resourceLoader) + .jacksonMapper(jacksonMapper) + .detectMalformedJson(true) + .build()) + .register(ENTITY_ATTRIBUTES_FILTERS, JsonSchemaLocationBuilder.with() + .jsonSchemaLocation(entityAttributesFiltersUiSchemaLocation) + .resourceLoader(resourceLoader) + .jacksonMapper(jacksonMapper) + .detectMalformedJson(true) + .build()); + + } +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaValidationComponentsConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaValidationComponentsConfiguration.java deleted file mode 100644 index 48fb33ede..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaValidationComponentsConfiguration.java +++ /dev/null @@ -1,30 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.configuration; - -import com.fasterxml.jackson.databind.ObjectMapper; -import edu.internet2.tier.shibboleth.admin.ui.jsonschema.MetadataSourcesJsonSchemaResourceLocation; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.ResourceLoader; - -/** - * @author Dmitriy Kopylenko - */ -@Configuration -@ConfigurationProperties("shibui") -public class JsonSchemaValidationComponentsConfiguration { - - //Configured via @ConfigurationProperties (using setter method) with 'shibui.metadata-sources-ui-schema-location' property and default - //value set here if that property is not explicitly set in application.properties - private String metadataSourcesUiSchemaLocation ="classpath:metadata-sources-ui-schema.json"; - - //This setter is used by Boot's @ConfiguratonProperties binding machinery - public void setMetadataSourcesUiSchemaLocation(String metadataSourcesUiSchemaLocation) { - this.metadataSourcesUiSchemaLocation = metadataSourcesUiSchemaLocation; - } - - @Bean - public MetadataSourcesJsonSchemaResourceLocation metadataSourcesJsonSchemaResourceLocation(ResourceLoader resourceLoader, ObjectMapper jacksonMapper) { - return new MetadataSourcesJsonSchemaResourceLocation(metadataSourcesUiSchemaLocation, resourceLoader, jacksonMapper); - } -} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/InMemoryJsonSchemaResourceLocationRegistry.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/InMemoryJsonSchemaResourceLocationRegistry.java new file mode 100644 index 000000000..56d6985bd --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/InMemoryJsonSchemaResourceLocationRegistry.java @@ -0,0 +1,31 @@ +package edu.internet2.tier.shibboleth.admin.ui.jsonschema; + +import java.util.EnumMap; +import java.util.Map; +import java.util.Optional; + +/** + * Default implementation of {@link JsonSchemaResourceLocationRegistry}. + *

+ * This class has package private visibility as creation of it is delegated to public static factory method + * on the registry interface itself. + * + * @author Dmitriy Kopylenko + */ +class InMemoryJsonSchemaResourceLocationRegistry implements JsonSchemaResourceLocationRegistry { + + private Map schemaLocations = + new EnumMap<>(JsonSchemaResourceLocation.ShemaType.class); + + + @Override + public JsonSchemaResourceLocationRegistry register(JsonSchemaResourceLocation.ShemaType type, JsonSchemaResourceLocation location) { + this.schemaLocations.put(type, location); + return this; + } + + @Override + public Optional lookup(JsonSchemaResourceLocation.ShemaType type) { + return Optional.ofNullable(this.schemaLocations.get(type)); + } +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java new file mode 100644 index 000000000..9208a1630 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java @@ -0,0 +1,24 @@ +package edu.internet2.tier.shibboleth.admin.ui.jsonschema; + +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.ShemaType.METADATA_SOURCES; + +/** + * Utility methods for common JSON schema types lookups. + * + * @author Dmitriy Kopylenko + */ +public abstract class JsonSchemaLocationLookup { + + /** + * Searches metadata sources JSON schema resource location object in the given location registry. + * + * @param resourceLocationRegistry + * @return metadata sources JSON schema resource location object + * @throws IllegalStateException if schema is not found in the given registry + */ + public static JsonSchemaResourceLocation metadataSourcesSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { + return resourceLocationRegistry + .lookup(METADATA_SOURCES) + .orElseThrow(() -> new IllegalStateException("JSON schema resource location for metadata sources is not registered.")); + } +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/MetadataSourcesJsonSchemaResourceLocation.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java similarity index 55% rename from backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/MetadataSourcesJsonSchemaResourceLocation.java rename to backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java index be2651309..0db5984bd 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/MetadataSourcesJsonSchemaResourceLocation.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.jsonschema; import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.Builder; import org.springframework.beans.factory.BeanInitializationException; import org.springframework.core.io.ResourceLoader; @@ -11,13 +12,13 @@ import java.util.Map; /** - * Encapsulates metadata sources JSON schema location. + * Encapsulates arbitrary JSON schema location. * * @author Dmitriy Kopylenko */ -public class MetadataSourcesJsonSchemaResourceLocation { +public class JsonSchemaResourceLocation { - private final String metadataSourcesUiSchemaLocation; + private final String jsonSchemaLocation; private URL jsonSchemaUrl; @@ -27,18 +28,19 @@ public class MetadataSourcesJsonSchemaResourceLocation { private boolean detectMalformedJsonDuringInit = true; - public MetadataSourcesJsonSchemaResourceLocation(String metadataSourcesUiSchemaLocation, ResourceLoader resourceLoader, ObjectMapper jacksonMapper) { - this.metadataSourcesUiSchemaLocation = metadataSourcesUiSchemaLocation; + public JsonSchemaResourceLocation(String jsonSchemaLocation, ResourceLoader resourceLoader, ObjectMapper jacksonMapper) { + this.jsonSchemaLocation = jsonSchemaLocation; this.resourceLoader = resourceLoader; this.jacksonMapper = jacksonMapper; } //This constructor is used in tests - public MetadataSourcesJsonSchemaResourceLocation(String metadataSourcesUiSchemaLocation, - ResourceLoader resourceLoader, - ObjectMapper jacksonMapper, - boolean detectMalformedJsonDuringInit) { - this.metadataSourcesUiSchemaLocation = metadataSourcesUiSchemaLocation; + public JsonSchemaResourceLocation(String jsonSchemaLocation, + ResourceLoader resourceLoader, + ObjectMapper jacksonMapper, + boolean detectMalformedJsonDuringInit) { + + this.jsonSchemaLocation = jsonSchemaLocation; this.resourceLoader = resourceLoader; this.jacksonMapper = jacksonMapper; this.detectMalformedJsonDuringInit = detectMalformedJsonDuringInit; @@ -60,7 +62,7 @@ public URI getUri() { @PostConstruct public void init() { try { - this.jsonSchemaUrl = this.resourceLoader.getResource(this.metadataSourcesUiSchemaLocation).getURL(); + this.jsonSchemaUrl = this.resourceLoader.getResource(this.jsonSchemaLocation).getURL(); if(this.detectMalformedJsonDuringInit) { //Detect malformed JSON schema early, during application start up and fail fast with useful exception message this.jacksonMapper.readValue(this.jsonSchemaUrl, Map.class); @@ -69,9 +71,26 @@ public void init() { catch (Exception ex) { StringBuilder msg = new StringBuilder(String.format("An error is detected during JSON parsing => [%s]", ex.getMessage())); - msg.append(String.format("Offending resource => [%s]", this.metadataSourcesUiSchemaLocation)); + msg.append(String.format("Offending resource => [%s]", this.jsonSchemaLocation)); throw new BeanInitializationException(msg.toString(), ex); } } + + public static class JsonSchemaLocationBuilder { + + @Builder(builderMethodName = "with") + public static JsonSchemaResourceLocation newSchemaLocation(String jsonSchemaLocation, + ResourceLoader resourceLoader, + ObjectMapper jacksonMapper, + boolean detectMalformedJson) { + JsonSchemaResourceLocation location = new JsonSchemaResourceLocation(jsonSchemaLocation, resourceLoader, jacksonMapper, detectMalformedJson); + location.init(); + return location; + } + } + + public enum ShemaType { + METADATA_SOURCES, ENTITY_ATTRIBUTES_FILTERS + } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocationRegistry.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocationRegistry.java new file mode 100644 index 000000000..0882527d8 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocationRegistry.java @@ -0,0 +1,37 @@ +package edu.internet2.tier.shibboleth.admin.ui.jsonschema; + +import java.util.Optional; + +/** + * An API to store and expose JSON schema resource locations for various JSON schema types. Typically configured as a Spring + * bean and injected into Spring-managed components interested in looking up JSON schema locations by particular type. + * + * @author Dmitriy Kopylenko + */ +public interface JsonSchemaResourceLocationRegistry { + + /** + * Register json schema resource location for given schema type. + * + * @param type of JSON schema + * @param location of JSON schema resource + */ + JsonSchemaResourceLocationRegistry register(JsonSchemaResourceLocation.ShemaType type, JsonSchemaResourceLocation location); + + /** + * Look up json schema resource location by given schema type. + * + * @param type type of JSON schema + * @return optional location of JSON schema resource + */ + Optional lookup(JsonSchemaResourceLocation.ShemaType type); + + /** + * Factory method. + * + * @return in-memory implementation + */ + static JsonSchemaResourceLocationRegistry inMemory() { + return new InMemoryJsonSchemaResourceLocationRegistry(); + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index cc5a34059..783f86488 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -50,6 +50,7 @@ shibui.logout-url=/dashboard #shibui.default-password= shibui.metadata-sources-ui-schema-location=classpath:metadata-sources-ui-schema.json +shibui.entity-attributes-filters-ui-schema-location=classpath:entity-attributes-filters-ui-schema.json #Actuator endpoints (info) # Un-comment to get full git details exposed like author, abbreviated SHA-1, commit message diff --git a/backend/src/main/resources/entity-attributes.schema.json b/backend/src/main/resources/entity-attributes-filters-ui-schema.json similarity index 100% rename from backend/src/main/resources/entity-attributes.schema.json rename to backend/src/main/resources/entity-attributes-filters-ui-schema.json diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests.groovy index 9b6a5df54..979f72a63 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests.groovy @@ -1,7 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.controller import com.fasterxml.jackson.databind.ObjectMapper -import edu.internet2.tier.shibboleth.admin.ui.jsonschema.MetadataSourcesJsonSchemaResourceLocation +import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocationRegistry import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.TestConfiguration @@ -11,6 +11,9 @@ import org.springframework.core.io.ResourceLoader import org.springframework.test.context.ActiveProfiles import spock.lang.Specification +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.* +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.ShemaType.METADATA_SOURCES + /** * @author Dmitriy Kopylenko */ @@ -36,11 +39,16 @@ class BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests extends Speci @TestConfiguration static class Config { @Bean - MetadataSourcesJsonSchemaResourceLocation metadataSourcesJsonSchemaResourceLocation(ResourceLoader resourceLoader, - ObjectMapper jacksonMapper) { - - new MetadataSourcesJsonSchemaResourceLocation('classpath:metadata-sources-ui-schema_MALFORMED.json', - resourceLoader, jacksonMapper, false) + JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(ResourceLoader resourceLoader, + ObjectMapper jacksonMapper) { + + JsonSchemaResourceLocationRegistry.inMemory() + .register(METADATA_SOURCES, JsonSchemaLocationBuilder.with() + .jsonSchemaLocation('classpath:metadata-sources-ui-schema_MALFORMED.json') + .resourceLoader(resourceLoader) + .jacksonMapper(jacksonMapper) + .detectMalformedJson(false) + .build()) } } } \ No newline at end of file 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 316bfebbd..8bb9bc7d4 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 @@ -3,6 +3,7 @@ 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.InternationalizationConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.MetadataResolverConverterConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.PlaceholderResolverComponentsConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget @@ -14,6 +15,7 @@ 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 edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers import groovy.xml.DOMBuilder import groovy.xml.MarkupBuilder import net.shibboleth.ext.spring.resource.ResourceHelper @@ -42,7 +44,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.util.TestHelpers.generatedX @SpringBootTest @DataJpaTest -@ContextConfiguration(classes=[CoreShibUiConfiguration, MetadataResolverConverterConfiguration, SearchConfiguration, InternationalizationConfiguration]) +@ContextConfiguration(classes=[CoreShibUiConfiguration, MetadataResolverConverterConfiguration, SearchConfiguration, InternationalizationConfiguration, PlaceholderResolverComponentsConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) @@ -295,7 +297,7 @@ class JPAMetadataResolverServiceImplTests extends Specification { OpenSamlObjects openSamlObjects @Bean - MetadataResolver metadataResolver() { + MetadataResolver metadataResolver(TokenPlaceholderResolvers tokenPlaceholderResolvers) { def resource = ResourceHelper.of(new ClassPathResource("/metadata/aggregate.xml")) def aggregate = new ResourceBackedMetadataResolver(resource){ @Override