From 10ec71c3902b550baed0586896df7e05af99e534 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 6 Nov 2018 16:50:14 -0700 Subject: [PATCH] [SHIBUI-906] Fixed a typo: Shematype -> SchemaType Pulled json generation out of controllers and in to a service. Added new controller for building Entity Attributes Filter schema. Added a "definition" block to the EAF schema json. Not sure we're keeping it though. Need to check with Ryan. --- ...ibutesFiltersUiDefinitionController.groovy | 61 +++++++++++++++++++ ...tadataSourcesUiDefinitionController.groovy | 61 ++----------------- ...sonSchemaValidatingControllerAdvice.groovy | 2 - .../service/JsonSchemaBuilderService.groovy | 61 +++++++++++++++++++ .../JsonSchemaComponentsConfiguration.java | 11 +++- ...oryJsonSchemaResourceLocationRegistry.java | 8 +-- .../jsonschema/JsonSchemaLocationLookup.java | 16 ++++- .../JsonSchemaResourceLocation.java | 2 +- .../JsonSchemaResourceLocationRegistry.java | 4 +- .../entity-attributes-filters-ui-schema.json | 4 +- ...efinitionControllerIntegrationTests.groovy | 2 +- 11 files changed, 161 insertions(+), 71 deletions(-) create mode 100644 backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityAttributesFiltersUiDefinitionController.groovy create mode 100644 backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JsonSchemaBuilderService.groovy diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityAttributesFiltersUiDefinitionController.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityAttributesFiltersUiDefinitionController.groovy new file mode 100644 index 000000000..ffd3ee3ab --- /dev/null +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityAttributesFiltersUiDefinitionController.groovy @@ -0,0 +1,61 @@ +package edu.internet2.tier.shibboleth.admin.ui.controller + +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 edu.internet2.tier.shibboleth.admin.ui.service.JsonSchemaBuilderService +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.entityAttributesFiltersSchema +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR + +/** + * Controller implementing REST resource responsible for exposing structure definition for metadata sources user + * interface in terms of JSON schema. + * + * @author Dmitriy Kopylenko + * @author Bill Smith (wsmith@unicon.net) + */ +@RestController +@RequestMapping('/api/ui/EntityAttributesFilters') +class EntityAttributesFiltersUiDefinitionController { + + @Autowired + JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry + + JsonSchemaResourceLocation jsonSchemaLocation + + @Autowired + ObjectMapper jacksonObjectMapper + + @Autowired + JsonSchemaBuilderService jsonSchemaBuilderService + + @GetMapping + ResponseEntity getUiDefinitionJsonSchema() { + try { + def parsedJson = jacksonObjectMapper.readValue(this.jsonSchemaLocation.url, Map) + jsonSchemaBuilderService.addReleaseAttributesToJson(parsedJson['properties']['attributeRelease']['widget']) + jsonSchemaBuilderService.addRelyingPartyOverridesToJson(parsedJson['properties']['relyingPartyOverrides']) + jsonSchemaBuilderService.addRelyingPartyOverridesCollectionDefinitionsToJson(parsedJson["definitions"]) + return ResponseEntity.ok(parsedJson) + } + catch (Exception e) { + e.printStackTrace() + return ResponseEntity.status(INTERNAL_SERVER_ERROR) + .body([jsonParseError : e.getMessage(), + sourceUiSchemaDefinitionFile: this.jsonSchemaLocation.url]) + } + } + + @PostConstruct + void init() { + this.jsonSchemaLocation = entityAttributesFiltersSchema(this.jsonSchemaResourceLocationRegistry); + } +} 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 1425b5af1..5e8710220 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 @@ -1,11 +1,9 @@ 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.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 edu.internet2.tier.shibboleth.admin.ui.service.JsonSchemaBuilderService import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping @@ -15,7 +13,6 @@ 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 /** @@ -38,15 +35,15 @@ class MetadataSourcesUiDefinitionController { ObjectMapper jacksonObjectMapper @Autowired - CustomPropertiesConfiguration customPropertiesConfiguration + JsonSchemaBuilderService jsonSchemaBuilderService @GetMapping ResponseEntity getUiDefinitionJsonSchema() { try { def parsedJson = jacksonObjectMapper.readValue(this.jsonSchemaLocation.url, Map) - addReleaseAttributesToJson(parsedJson['properties']['attributeRelease']['widget']) - addRelyingPartyOverridesToJson(parsedJson['properties']['relyingPartyOverrides']) - addRelyingPartyOverridesCollectionDefinitions(parsedJson["definitions"]) + jsonSchemaBuilderService.addReleaseAttributesToJson(parsedJson['properties']['attributeRelease']['widget']) + jsonSchemaBuilderService.addRelyingPartyOverridesToJson(parsedJson['properties']['relyingPartyOverrides']) + jsonSchemaBuilderService.addRelyingPartyOverridesCollectionDefinitionsToJson(parsedJson["definitions"]) return ResponseEntity.ok(parsedJson) } catch (Exception e) { @@ -61,52 +58,4 @@ class MetadataSourcesUiDefinitionController { void init() { this.jsonSchemaLocation = metadataSourcesSchema(this.jsonSchemaResourceLocationRegistry); } - - private void addReleaseAttributesToJson(Object json) { - json['data'] = customPropertiesConfiguration.getAttributes().collect { - [key: it['name'], label: it['displayName']] - } - } - - private void addRelyingPartyOverridesToJson(Object json) { - def properties = [:] - customPropertiesConfiguration.getOverrides().each { - def property - if (it['displayType'] == 'list' - || it['displayType'] == 'set') { - property = [$ref: '#/definitions/' + it['name']] - } else { - property = - [title : it['displayName'], - description: it['helpText'], - type : it['displayType'], - default : it['defaultValue']] - } - properties[(String) it['name']] = property - } - json['properties'] = properties - } - - private void addRelyingPartyOverridesCollectionDefinitions(Object json) { - 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] - if (it['displayType'] == 'set') { - definition['uniqueItems'] = true - } else if (it['displayType'] == 'list') { - definition['uniqueItems'] = false - } - 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 - } - } } 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 cf342eef9..712142172 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,7 +2,6 @@ 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 @@ -18,7 +17,6 @@ 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 diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JsonSchemaBuilderService.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JsonSchemaBuilderService.groovy new file mode 100644 index 000000000..8af0be7d3 --- /dev/null +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JsonSchemaBuilderService.groovy @@ -0,0 +1,61 @@ +package edu.internet2.tier.shibboleth.admin.ui.service + +import edu.internet2.tier.shibboleth.admin.ui.configuration.CustomPropertiesConfiguration +import org.springframework.beans.factory.annotation.Autowired + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +class JsonSchemaBuilderService { + + @Autowired + CustomPropertiesConfiguration customPropertiesConfiguration + + void addReleaseAttributesToJson(Object json) { + json['data'] = customPropertiesConfiguration.getAttributes().collect { + [key: it['name'], label: it['displayName']] + } + } + + void addRelyingPartyOverridesToJson(Object json) { + def properties = [:] + customPropertiesConfiguration.getOverrides().each { + def property + if (it['displayType'] == 'list' + || it['displayType'] == 'set') { + property = [$ref: '#/definitions/' + it['name']] + } else { + property = + [title : it['displayName'], + description: it['helpText'], + type : it['displayType'], + default : it['defaultValue']] + } + properties[(String) it['name']] = property + } + json['properties'] = properties + } + + void addRelyingPartyOverridesCollectionDefinitionsToJson(Object json) { + 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] + if (it['displayType'] == 'set') { + definition['uniqueItems'] = true + } else if (it['displayType'] == 'list') { + definition['uniqueItems'] = false + } + 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 + } + } +} 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 index 8d70fa410..1bf2745c6 100644 --- 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 @@ -1,8 +1,8 @@ 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 edu.internet2.tier.shibboleth.admin.ui.service.JsonSchemaBuilderService; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -10,8 +10,8 @@ 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; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.ENTITY_ATTRIBUTES_FILTERS; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES; /** * @author Dmitriy Kopylenko @@ -47,4 +47,9 @@ public JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(Res .build()); } + + @Bean + public JsonSchemaBuilderService jsonSchemaBuilderService() { + return new JsonSchemaBuilderService(); + } } 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 index 56d6985bd..2840619b2 100644 --- 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 @@ -14,18 +14,18 @@ */ class InMemoryJsonSchemaResourceLocationRegistry implements JsonSchemaResourceLocationRegistry { - private Map schemaLocations = - new EnumMap<>(JsonSchemaResourceLocation.ShemaType.class); + private Map schemaLocations = + new EnumMap<>(JsonSchemaResourceLocation.SchemaType.class); @Override - public JsonSchemaResourceLocationRegistry register(JsonSchemaResourceLocation.ShemaType type, JsonSchemaResourceLocation location) { + public JsonSchemaResourceLocationRegistry register(JsonSchemaResourceLocation.SchemaType type, JsonSchemaResourceLocation location) { this.schemaLocations.put(type, location); return this; } @Override - public Optional lookup(JsonSchemaResourceLocation.ShemaType type) { + public Optional lookup(JsonSchemaResourceLocation.SchemaType 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 index 9208a1630..b9d9ac1f1 100644 --- 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 @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.jsonschema; -import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.ShemaType.METADATA_SOURCES; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.ENTITY_ATTRIBUTES_FILTERS; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES; /** * Utility methods for common JSON schema types lookups. @@ -21,4 +22,17 @@ public static JsonSchemaResourceLocation metadataSourcesSchema(JsonSchemaResourc .lookup(METADATA_SOURCES) .orElseThrow(() -> new IllegalStateException("JSON schema resource location for metadata sources is not registered.")); } + + /** + * Searches entity attributes filters JSON schema resource location object in the given location registry. + * + * @param resourceLocationRegistry + * @returnentity attributes filters JSON schema resource location object + * @throws IllegalStateException if schema is not found in the given registry + */ + public static JsonSchemaResourceLocation entityAttributesFiltersSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { + return resourceLocationRegistry + .lookup(ENTITY_ATTRIBUTES_FILTERS) + .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/JsonSchemaResourceLocation.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java index 0db5984bd..f08ac6069 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java @@ -90,7 +90,7 @@ public static JsonSchemaResourceLocation newSchemaLocation(String jsonSchemaLoca } } - public enum ShemaType { + public enum SchemaType { 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 index 0882527d8..e5a6e88c5 100644 --- 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 @@ -16,7 +16,7 @@ public interface JsonSchemaResourceLocationRegistry { * @param type of JSON schema * @param location of JSON schema resource */ - JsonSchemaResourceLocationRegistry register(JsonSchemaResourceLocation.ShemaType type, JsonSchemaResourceLocation location); + JsonSchemaResourceLocationRegistry register(JsonSchemaResourceLocation.SchemaType type, JsonSchemaResourceLocation location); /** * Look up json schema resource location by given schema type. @@ -24,7 +24,7 @@ public interface JsonSchemaResourceLocationRegistry { * @param type type of JSON schema * @return optional location of JSON schema resource */ - Optional lookup(JsonSchemaResourceLocation.ShemaType type); + Optional lookup(JsonSchemaResourceLocation.SchemaType type); /** * Factory method. diff --git a/backend/src/main/resources/entity-attributes-filters-ui-schema.json b/backend/src/main/resources/entity-attributes-filters-ui-schema.json index 2350a345c..5d71f0ba8 100644 --- a/backend/src/main/resources/entity-attributes-filters-ui-schema.json +++ b/backend/src/main/resources/entity-attributes-filters-ui-schema.json @@ -222,5 +222,7 @@ "attributeRelease" ] } - ] + ], + "definitions": { + } } \ No newline at end of file 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 979f72a63..1da336ff2 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 @@ -12,7 +12,7 @@ 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 +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES /** * @author Dmitriy Kopylenko