Skip to content

Commit

Permalink
SHIBUI-906: SHIBUI-951
Browse files Browse the repository at this point in the history
  • Loading branch information
dima767 committed Oct 24, 2018
1 parent 9e0aff2 commit 0e5b35c
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand All @@ -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
Expand All @@ -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']]
Expand All @@ -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
}
Expand All @@ -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
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand All @@ -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<? extends HttpMessageConverter<?>> converterType) {
Expand All @@ -36,7 +43,7 @@ class RelyingPartyOverridesJsonSchemaValidatingControllerAdvice extends RequestB
Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> 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())
Expand All @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -407,4 +407,4 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService {
}

}
}
}
Original file line number Diff line number Diff line change
@@ -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());

}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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}.
* <p>
* 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<JsonSchemaResourceLocation.ShemaType, JsonSchemaResourceLocation> 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<JsonSchemaResourceLocation> lookup(JsonSchemaResourceLocation.ShemaType type) {
return Optional.ofNullable(this.schemaLocations.get(type));
}
}
Original file line number Diff line number Diff line change
@@ -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."));
}
}
Loading

0 comments on commit 0e5b35c

Please sign in to comment.