Skip to content

Commit

Permalink
SHIBUI-704 Fixed merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
rmathis committed Nov 12, 2018
2 parents 566db33 + 8017969 commit 339c516
Show file tree
Hide file tree
Showing 92 changed files with 2,265 additions and 858 deletions.
3 changes: 3 additions & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ dependencies {
//JSON schema generator
testCompile 'com.kjetland:mbknor-jackson-jsonschema_2.12:1.0.29'
testCompile 'javax.validation:validation-api:2.0.1.Final'

//JSON schema validator
compile 'org.sharegov:mjson:1.4.1'
}

def generatedSrcDir = new File(buildDir, 'generated/src/main/java')
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
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 org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.filesystemMetadataProviderSchema
//import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.localDynamicMetadataProviderSchema
//import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.dynamicHttpMetadataProviderSchema
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType

/**
* Controller implementing REST resource responsible for exposing structure definition for metadata resolvers user
* interface in terms of JSON schema.
*
* @author Dmitriy Kopylenko
* @author Bill Smith (wsmith@unicon.net)
*/
@RestController
@RequestMapping('/api/ui/MetadataResolver')
class MetadataResolverUiDefinitionController {

@Autowired
JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry

JsonSchemaResourceLocation jsonSchemaLocation

@Autowired
ObjectMapper jacksonObjectMapper

@GetMapping(value = "/{resolverType}")
ResponseEntity<?> getUiDefinitionJsonSchema(@PathVariable String resolverType) {
switch (SchemaType.getSchemaType(resolverType)) {
case SchemaType.FILESYSTEM_METADATA_RESOLVER:
jsonSchemaLocation = filesystemMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry)
break
/* case SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER:
jsonSchemaLocation = localDynamicMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry)
break*/
/* case SchemaType.DYNAMIC_HTTP_METADATA_RESOLVER:
jsonSchemaLocation = dynamicHttpMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry)
break*/
default:
throw new UnsupportedOperationException("Json schema for an unsupported metadata resolver (" + resolverType + ") was requested")
}
try {
def parsedJson = jacksonObjectMapper.readValue(this.jsonSchemaLocation.url, Map)
return ResponseEntity.ok(parsedJson)
}
catch (Exception e) {
e.printStackTrace()
return ResponseEntity.status(INTERNAL_SERVER_ERROR)
.body([jsonParseError : e.getMessage(),
sourceUiSchemaDefinitionFile: this.jsonSchemaLocation.url])
}
}

@GetMapping(value = "/types")
ResponseEntity<?> getResolverTypes() {
return ResponseEntity.ok(SchemaType.getResolverTypes())
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package edu.internet2.tier.shibboleth.admin.ui.controller

import com.fasterxml.jackson.databind.ObjectMapper
import edu.internet2.tier.shibboleth.admin.ui.configuration.CustomAttributesConfiguration
import edu.internet2.tier.shibboleth.admin.ui.jsonschema.MetadataSourcesJsonSchemaResourceLocation
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.slf4j.Logger
import org.slf4j.LoggerFactory
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 org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR

/**
Expand All @@ -22,29 +28,38 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR
@RequestMapping('/api/ui/MetadataSources')
class MetadataSourcesUiDefinitionController {

private static final Logger logger = LoggerFactory.getLogger(MetadataSourcesUiDefinitionController.class);

@Autowired
MetadataSourcesJsonSchemaResourceLocation jsonSchemaLocation
JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry

JsonSchemaResourceLocation jsonSchemaLocation

@Autowired
ObjectMapper jacksonObjectMapper

@Autowired
CustomAttributesConfiguration customAttributesConfiguration
JsonSchemaBuilderService jsonSchemaBuilderService

@GetMapping
ResponseEntity<?> getUiDefinitionJsonSchema() {
try {
def parsedJson = jacksonObjectMapper.readValue(this.jsonSchemaLocation.url, Map)
parsedJson['properties']['attributeRelease']['widget']['data'] =
customAttributesConfiguration.getAttributes().collect {
[key: it['name'], label: it['displayName']]
}
jsonSchemaBuilderService.addReleaseAttributesToJson(parsedJson['properties']['attributeRelease']['widget'])
jsonSchemaBuilderService.addRelyingPartyOverridesToJson(parsedJson['properties']['relyingPartyOverrides'])
jsonSchemaBuilderService.addRelyingPartyOverridesCollectionDefinitionsToJson(parsedJson["definitions"])
return ResponseEntity.ok(parsedJson)
}
catch (Exception e) {
catch (IOException e) {
logger.error("An error occurred while attempting to get json schema for metadata sources!", e)
return ResponseEntity.status(INTERNAL_SERVER_ERROR)
.body([jsonParseError : e.getMessage(),
sourceUiSchemaDefinitionFile: this.jsonSchemaLocation.url])
}
}

@PostConstruct
void init() {
this.jsonSchemaLocation = metadataSourcesSchema(this.jsonSchemaResourceLocationRegistry);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
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.annotation.Autowired
import org.springframework.core.MethodParameter
import org.springframework.http.HttpInputMessage
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.http.converter.HttpMessageConverter
import org.springframework.web.bind.annotation.ControllerAdvice
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

/**
* Controller advice implementation for validating relying party overrides payload coming from UI layer
* against pre-defined JSON schema.
*
* @author Dmitriy Kopylenko
*/
@ControllerAdvice
class RelyingPartyOverridesJsonSchemaValidatingControllerAdvice extends RequestBodyAdviceAdapter {

@Autowired
JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry

JsonSchemaResourceLocation jsonSchemaLocation

@Override
boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
targetType.typeName == EntityDescriptorRepresentation.typeName
}

@Override
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.jsonSchemaLocation.uri)
def validationResult = schema.validate(relyingPartyOverridesJson)
if (!validationResult.at('ok')) {
throw new JsonSchemaValidationFailedException(validationResult.at('errors').asList())
}
body
}

@ExceptionHandler(JsonSchemaValidationFailedException)
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,65 @@
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']]
if (it['displayType'] == 'boolean') {
property['default'] = (Boolean)(it['defaultValue'])
} else {
property['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
}
}
}
Loading

0 comments on commit 339c516

Please sign in to comment.