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 934d7b1a7..e77097af6 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 @@ -1,5 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.jsonschema +import edu.internet2.tier.shibboleth.admin.ui.controller.ErrorResponse import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import mjson.Json import org.springframework.beans.factory.annotation.Autowired @@ -10,7 +11,6 @@ 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 @@ -56,8 +56,8 @@ class RelyingPartyOverridesJsonSchemaValidatingControllerAdvice extends RequestB } @ExceptionHandler(JsonSchemaValidationFailedException) - final ResponseEntity handleUserNotFoundException(JsonSchemaValidationFailedException ex, WebRequest request) { - new ResponseEntity<>([errors: ex.errors], HttpStatus.BAD_REQUEST) + final ResponseEntity handleJsonSchemaValidationFailedException(JsonSchemaValidationFailedException ex) { + ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorResponse("400", String.join('\n', ex.errors))) } @PostConstruct diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java index afde9d244..c3e76983e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java @@ -160,7 +160,7 @@ private ResponseEntity existingEntityDescriptorCheck(String entityId) { return ResponseEntity .status(HttpStatus.CONFLICT) .headers(headers) - .body(String.format("The entity descriptor with entity id [%s] already exists.", entityId)); + .body(new ErrorResponse(String.valueOf(HttpStatus.CONFLICT.value()), String.format("The entity descriptor with entity id [%s] already exists.", entityId))); } //No existing entity descriptor, which is an OK condition indicated by returning a null conflict response return null; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java index 4593d8bbf..b9a7ab3f0 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; import com.fasterxml.jackson.databind.exc.InvalidTypeIdException; +import edu.internet2.tier.shibboleth.admin.ui.domain.exceptions.MetadataFileNotFoundException; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolverValidationService; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver; @@ -105,32 +106,26 @@ public ResponseEntity getOne(@PathVariable String resourceId) { } @PostMapping("/MetadataResolvers") - @Transactional + @Transactional(rollbackFor = Exception.class) public ResponseEntity create(@RequestBody MetadataResolver newResolver) throws IOException, ResolverException, ComponentInitializationException { if (resolverRepository.findByName(newResolver.getName()) != null) { return ResponseEntity.status(HttpStatus.CONFLICT).build(); } ResponseEntity validationErrorResponse = validate(newResolver); - if(validationErrorResponse != null) { + if (validationErrorResponse != null) { return validationErrorResponse; } MetadataResolver persistedResolver = resolverRepository.save(newResolver); positionOrderContainerService.appendPositionOrderForNew(persistedResolver); - - //TODO: currently, the update call might explode, but the save works.. in which case, the UI never gets - // n valid response. This operation is not atomic. Should we return an error here? - if (persistedResolver.getDoInitialization()) { - org.opensaml.saml.metadata.resolver.MetadataResolver openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver); - OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation); - } + doResolverInitialization(persistedResolver); return ResponseEntity.created(getResourceUriFor(persistedResolver)).body(persistedResolver); } @PutMapping("/MetadataResolvers/{resourceId}") - @Transactional + @Transactional(rollbackFor = Exception.class) public ResponseEntity update(@PathVariable String resourceId, @RequestBody MetadataResolver updatedResolver) throws IOException, ResolverException, ComponentInitializationException { MetadataResolver existingResolver = resolverRepository.findByResourceId(resourceId); if (existingResolver == null) { @@ -143,24 +138,13 @@ public ResponseEntity update(@PathVariable String resourceId, @RequestBody Me } ResponseEntity validationErrorResponse = validate(updatedResolver); - if(validationErrorResponse != null) { + if (validationErrorResponse != null) { return validationErrorResponse; } updatedResolver.setAudId(existingResolver.getAudId()); - MetadataResolver persistedResolver = resolverRepository.save(updatedResolver); - - if (persistedResolver.getDoInitialization()) { - org.opensaml.saml.metadata.resolver.MetadataResolver openSamlRepresentation = null; - try { - openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver); - } catch (FileNotFoundException e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.toString(), "label.file-doesnt-exist")); - } - OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation); - } + doResolverInitialization(persistedResolver); return ResponseEntity.ok(persistedResolver); } @@ -168,7 +152,7 @@ public ResponseEntity update(@PathVariable String resourceId, @RequestBody Me @SuppressWarnings("Unchecked") private ResponseEntity validate(MetadataResolver metadataResolver) { ValidationResult validationResult = metadataResolverValidationService.validateIfNecessary(metadataResolver); - if(!validationResult.isValid()) { + if (!validationResult.isValid()) { return ResponseEntity.badRequest().body(validationResult.getErrorMessage()); } return null; @@ -181,4 +165,17 @@ private static URI getResourceUriFor(MetadataResolver resolver) { .build() .toUri(); } + + private void doResolverInitialization(MetadataResolver persistedResolver) throws + ComponentInitializationException, ResolverException, IOException { + if (persistedResolver.getDoInitialization()) { + org.opensaml.saml.metadata.resolver.MetadataResolver openSamlRepresentation = null; + try { + openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver); + } catch (FileNotFoundException e) { + throw new MetadataFileNotFoundException("message.file-doesnt-exist"); + } + OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation); + } + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/support/RestControllersSupport.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/support/RestControllersSupport.java index 6a035d9e2..e210adc94 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/support/RestControllersSupport.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/support/RestControllersSupport.java @@ -1,7 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.controller.support; -import com.google.common.collect.ImmutableMap; import edu.internet2.tier.shibboleth.admin.ui.controller.ErrorResponse; +import edu.internet2.tier.shibboleth.admin.ui.domain.exceptions.MetadataFileNotFoundException; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; import org.hibernate.exception.ConstraintViolationException; @@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.client.HttpClientErrorException; +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.NOT_FOUND; @@ -53,4 +54,10 @@ public final ResponseEntity handleAllOtherExceptions(Exception ex ErrorResponse errorResponse = new ErrorResponse("400", ex.getLocalizedMessage()); return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); } + + @ExceptionHandler(MetadataFileNotFoundException.class) + public final ResponseEntity metadataFileNotFoundHandler(MetadataFileNotFoundException ex) { + ErrorResponse errorResponse = new ErrorResponse(INTERNAL_SERVER_ERROR.toString(), ex.getLocalizedMessage()); + return new ResponseEntity<>(errorResponse, INTERNAL_SERVER_ERROR); + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/exceptions/MetadataFileNotFoundException.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/exceptions/MetadataFileNotFoundException.java new file mode 100644 index 000000000..bc3dd1493 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/exceptions/MetadataFileNotFoundException.java @@ -0,0 +1,14 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.exceptions; + +/** + * Indicates that provided metadata file is not found. Thrown during opensaml API initialization code path, if there is + * such. Throwing such exception is useful in @Transactional context for atomic transaction rollbacks, etc. + * + * @author Dmitriy Kopylenko + */ +public class MetadataFileNotFoundException extends RuntimeException { + + public MetadataFileNotFoundException(String message) { + super(message); + } +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java index ccb77164c..8088793a9 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java @@ -64,7 +64,7 @@ private OpenSamlFilesystemMetadataResolver convertToOpenSamlRepresentation(Files IndexWriter indexWriter = indexWriterService.getIndexWriter(resolver.getResourceId()); File metadataFile = new File(resolver.getMetadataFile()); if (resolver.getDoInitialization() && !metadataFile.exists()) { - throw new FileNotFoundException("No file was found on the fileysystem for provided filename: " + resolver.getMetadataFile()); + throw new FileNotFoundException("No file was found on the file system for provided filename: " + resolver.getMetadataFile()); } OpenSamlFilesystemMetadataResolver openSamlResolver = new OpenSamlFilesystemMetadataResolver(openSamlObjects.getParserPool(), diff --git a/backend/src/main/resources/dynamic-http-metadata-provider.schema.json b/backend/src/main/resources/dynamic-http-metadata-provider.schema.json index f9dec02b8..887508b7f 100644 --- a/backend/src/main/resources/dynamic-http-metadata-provider.schema.json +++ b/backend/src/main/resources/dynamic-http-metadata-provider.schema.json @@ -152,8 +152,8 @@ "step": 0.01 }, "placeholder": "label.real-number", - "minimum": 0, - "maximum": 1, + "minimum": 0.01, + "maximum": 0.99, "default": null }, "minCacheDuration": { @@ -222,6 +222,29 @@ "default": null, "pattern": "^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" }, + "removeIdleEntityData": { + "title": "label.remove-idle-entity-data", + "description": "tooltip.remove-idle-entity-data", + "type": "boolean", + "widget": { + "id": "boolean-radio" + }, + "oneOf": [ + { + "enum": [ + true + ], + "description": "value.true" + }, + { + "enum": [ + false + ], + "description": "value.false" + } + ], + "default": true + }, "cleanupTaskInterval": { "title": "label.cleanup-task-interval", "description": "tooltip.cleanup-task-interval", diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index 274d61981..25e82fa86 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -299,7 +299,7 @@ label.metadata-provider-type=Metadata Provider Type label.metadata-provider-name=Metadata Provider Name label.select-metadata-type=Select a metadata provider type label.metadata-provider-status=Metadata Provider Status -label.enable-provider-upon-saving=Enable Metadata Provider upon saving? +label.enable-provider-upon-saving=Enable Metadata Provider? label.certificate-type=Type label.metadata-file=Metadata File @@ -319,6 +319,7 @@ label.select-metadata-provider-type=Select Metadata Provider Type label.filter-list=Filter List label.common-attributes=Common Attributes label.reloading-attributes=Reloading Attributes +label.dynamic-attributes=Dynamic Attributes label.metadata-filter-plugins=Metadata Filter Plugins label.advanced-settings=Advanced Settings label.edit-metadata-provider=Edit Metadata Provider @@ -397,6 +398,7 @@ message.wizard-status=Step { index } of { length } message.entity-id-min-unique=You must add at least one entity id target and they must each be unique. message.required-for-scripts=Required for Scripts message.required-for-regex=Required for Regex +message.file-doesnt-exist=The requested file to be processed does not exist on the server. message.database-constraint=There was a database constraint problem processing the request. Check the request to ensure that fields that must be unique are truly unique. tooltip.entity-id=Entity ID @@ -458,7 +460,7 @@ tooltip.http-caching-directory=If httpCaching='file', this attribute specifies w tooltip.http-max-cache-entries=The maximum number of responses written to cache. This attribute is incompatible with httpClientRef. tooltip.max-cache-entry-size=The maximum response body size that may be cached, in bytes. This attribute is incompatible with httpClientRef. -tooltip.metadata-provider-name=Metadata Provider Name +tooltip.metadata-provider-name=Metadata Provider Name (for display on the Dashboard only) tooltip.metadata-provider-type=Metadata Provider Type tooltip.xml-id=Identifier for logging, identification for command line reload, etc. tooltip.metadata-url=Identifier for logging, identification for command line reload, etc. @@ -470,7 +472,7 @@ tooltip.require-valid-metadata=Whether candidate metadata found by the resolver tooltip.fail-fast-init=Whether to fail initialization of the underlying MetadataResolverService (and possibly the IdP as a whole) if the initialization of a metadata provider fails. When false, the IdP may start, and will continue to attempt to reload valid metadata if configured to do so, but operations that require valid metadata will fail until it does. tooltip.use-default-predicate-reg=Flag which determines whether the default CriterionPredicateRegistry will be used if a custom one is not supplied explicitly. tooltip.satisfy-any-predicates=Flag which determines whether predicates used in filtering are connected by a logical 'OR' (true) or by logical 'AND' (false). -tooltip.enable-provider-upon-saving=Enable Metadata Provider upon saving? +tooltip.enable-provider-upon-saving=If checkbox is clicked, the metadata provider is enabled for integration with the IdP tooltip.max-validity-interval=Defines the window within which the metadata is valid. tooltip.require-signed-root=If true, this fails to load metadata with no signature on the root XML element. diff --git a/backend/src/main/resources/i18n/messages_en.properties b/backend/src/main/resources/i18n/messages_en.properties index 050c5fc32..f569ce012 100644 --- a/backend/src/main/resources/i18n/messages_en.properties +++ b/backend/src/main/resources/i18n/messages_en.properties @@ -304,7 +304,7 @@ label.metadata-provider-type=Metadata Provider Type label.metadata-provider-name=Metadata Provider Name label.select-metadata-type=Select a metadata provider type label.metadata-provider-status=Metadata Provider Status -label.enable-provider-upon-saving=Enable Metadata Provider upon saving? +label.enable-provider-upon-saving=Enable Metadata Provider? label.certificate-type=Type label.metadata-file=Metadata File @@ -324,6 +324,7 @@ label.select-metadata-provider-type=Select Metadata Provider Type label.filter-list=Filter List label.common-attributes=Common Attributes label.reloading-attributes=Reloading Attributes +label.dynamic-attributes=Dynamic Attributes label.metadata-filter-plugins=Metadata Filter Plugins label.advanced-settings=Advanced Settings label.edit-metadata-provider=Edit Metadata Provider @@ -414,6 +415,7 @@ message.wizard-status=Step { index } of { length } message.entity-id-min-unique=You must add at least one entity id target and they must each be unique. message.required-for-scripts=Required for Scripts message.required-for-regex=Required for Regex +message.file-doesnt-exist=The requested file to be processed does not exist on the server. message.database-constraint=There was a database constraint problem processing the request. Check the request to ensure that fields that must be unique are truly unique. tooltip.entity-id=Entity ID @@ -475,7 +477,7 @@ tooltip.http-caching-directory=If httpCaching='file', this attribute specifies w tooltip.http-max-cache-entries=The maximum number of responses written to cache. This attribute is incompatible with httpClientRef. tooltip.max-cache-entry-size=The maximum response body size that may be cached, in bytes. This attribute is incompatible with httpClientRef. -tooltip.metadata-provider-name=Metadata Provider Name +tooltip.metadata-provider-name=Metadata Provider Name (for display on the Dashboard only) tooltip.metadata-provider-type=Metadata Provider Type tooltip.xml-id=Identifier for logging, identification for command line reload, etc. tooltip.metadata-url=Identifier for logging, identification for command line reload, etc. @@ -487,14 +489,14 @@ tooltip.require-valid-metadata=Whether candidate metadata found by the resolver tooltip.fail-fast-init=Whether to fail initialization of the underlying MetadataResolverService (and possibly the IdP as a whole) if the initialization of a metadata provider fails. When false, the IdP may start, and will continue to attempt to reload valid metadata if configured to do so, but operations that require valid metadata will fail until it does. tooltip.use-default-predicate-reg=Flag which determines whether the default CriterionPredicateRegistry will be used if a custom one is not supplied explicitly. tooltip.satisfy-any-predicates=Flag which determines whether predicates used in filtering are connected by a logical 'OR' (true) or by logical 'AND' (false). -tooltip.enable-provider-upon-saving=Enable Metadata Provider upon saving? +tooltip.enable-provider-upon-saving=If checkbox is clicked, the metadata provider is enabled for integration with the IdP tooltip.max-validity-interval=Defines the window within which the metadata is valid. tooltip.require-signed-root=If true, this fails to load metadata with no signature on the root XML element. tooltip.certificate-file=A key used to verify the signature. Conflicts with trustEngineRef and both of the child elements. -tooltip.retained-roles=Controls whether to keep entity descriptors that contain no roles -tooltip.remove-roleless-entity-descriptors=Controls whether to keep entity descriptors that contain no roles. -tooltip.remove-empty-entities-descriptors=Controls whether to keep entities descriptors that contain no entity descriptors. +tooltip.retained-roles=Note that property replacement cannot be used on this element. +tooltip.remove-roleless-entity-descriptors=Controls whether to keep entity descriptors that contain no roles. Note: If this attribute is set to false, the resulting output may not be schema-valid since an element must include at least one role descriptor. +tooltip.remove-empty-entities-descriptors=Controls whether to keep entities descriptors that contain no entity descriptors. Note: If this attribute is set to false, the resulting output may not be schema-valid since an element must include at least one child element, either an element or an element. tooltip.min-refresh-delay=Lower bound on the next refresh from the time calculated based on the metadata\u0027s expiration. tooltip.max-refresh-delay=Upper bound on the next refresh from the time calculated based on the metadata\u0027s expiration. diff --git a/backend/src/main/resources/local-dynamic-metadata-provider.schema.json b/backend/src/main/resources/local-dynamic-metadata-provider.schema.json index 04aa496f9..c76434258 100644 --- a/backend/src/main/resources/local-dynamic-metadata-provider.schema.json +++ b/backend/src/main/resources/local-dynamic-metadata-provider.schema.json @@ -8,8 +8,8 @@ ], "properties": { "name": { - "title": "label.metadata-provider-name", - "description": "tooltip.metadata-provider-name", + "title": "label.metadata-provider-name-display-only", + "description": "tooltip.metadata-provider-name-display-only", "type": "string", "widget": { "id": "string", diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy index 122a349ae..b38941b74 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy @@ -505,7 +505,7 @@ class EntityDescriptorControllerTests extends Specification { then: result.andExpect(status().isConflict()) - .andExpect(content().string("The entity descriptor with entity id [http://test.scaldingspoon.org/test1] already exists.")) + .andExpect(content().string("{\"errorCode\":\"409\",\"errorMessage\":\"The entity descriptor with entity id [http://test.scaldingspoon.org/test1] already exists.\"}")) } def "POST /EntityDescriptor handles x-www-form-urlencoded happily"() { diff --git a/backend/src/test/resources/i18n/messages_es.properties b/backend/src/test/resources/i18n/messages_es.properties index 241aa5c49..7899789c6 100644 --- a/backend/src/test/resources/i18n/messages_es.properties +++ b/backend/src/test/resources/i18n/messages_es.properties @@ -282,7 +282,7 @@ label.metadata-provider-type=(es) Metadata Provider Type label.metadata-provider-name=(es) Metadata Provider Name label.select-metadata-type=(es) Select a metadata provider type label.metadata-provider-status=(es) Metadata Provider Status -label.enable-provider-upon-saving=(es) Enable Metadata Provider upon saving? +label.enable-provider-upon-saving=(es) Enable Metadata Provider? label.enable-filter=(es) Enable Filter? label.required-valid-until=(es) Required Valid Until Filter @@ -299,6 +299,7 @@ label.select-metadata-provider-type=(es) Select Metadata Provider Type label.filter-list=(es) Filter List label.common-attributes=(es) Common Attributes label.reloading-attributes=(es) Reloading Attributes +label.dynamic-attributes=(es) Dynamic Attributes label.metadata-filter-plugins=(es) Metadata Filter Plugins label.advanced-settings=(es) Advanced Settings label.edit-metadata-provider=(es) Edit Metadata Provider @@ -417,7 +418,7 @@ tooltip.http-caching-directory=(es) If httpCaching=(es) 'file', this attribute s tooltip.http-max-cache-entries=(es) The maximum number of responses written to cache. This attribute is incompatible with httpClientRef. tooltip.max-cache-entry-size=(es) The maximum response body size that may be cached, in bytes. This attribute is incompatible with httpClientRef. -tooltip.metadata-provider-name=(es) Metadata Provider Name +tooltip.metadata-provider-name=(es) Metadata Provider Name (for display on the Dashboard only) tooltip.metadata-provider-type=(es) Metadata Provider Type tooltip.xml-id=(es) Identifier for logging, identification for command line reload, etc. tooltip.metadata-url=(es) Identifier for logging, identification for command line reload, etc. @@ -428,7 +429,7 @@ tooltip.require-valid-metadata=(es) Whether candidate metadata found by the reso tooltip.fail-fast-init=(es) Whether to fail initialization of the underlying MetadataResolverService (and possibly the IdP as a whole) if the initialization of a metadata provider fails. When false, the IdP may start, and will continue to attempt to reload valid metadata if configured to do so, but operations that require valid metadata will fail until it does. tooltip.use-default-predicate-reg=(es) Whether to fail initialization of the underlying MetadataResolverService (and possibly the IdP as a whole) if the initialization of a metadata provider fails. When false, the IdP may start, and will continue to attempt to reload valid metadata if configured to do so, but operations that require valid metadata will fail until it does. tooltip.satisfy-any-predicates=(es) Flag which determines whether predicates used in filtering are connected by a logical 'OR' (true) or by logical 'AND' (false). -tooltip.enable-provider-upon-saving=(es) Enable Metadata Provider upon saving? +tooltip.enable-provider-upon-saving=(es) If checkbox is clicked, the metadata provider is enabled for integration with the IdP tooltip.max-validity-interval=(es) Defines the window within which the metadata is valid. tooltip.require-signed-root=(es) If true, this fails to load metadata with no signature on the root XML element. diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html index f09ae298a..b7adb997b 100644 --- a/ui/src/app/app.component.html +++ b/ui/src/app/app.component.html @@ -14,7 +14,6 @@ - + diff --git a/ui/src/app/metadata/domain/service/resolver.service.ts b/ui/src/app/metadata/domain/service/resolver.service.ts index f0c9f4b3c..4012f9f23 100644 --- a/ui/src/app/metadata/domain/service/resolver.service.ts +++ b/ui/src/app/metadata/domain/service/resolver.service.ts @@ -45,7 +45,9 @@ export class ResolverService { return this.http.post(`${this.base}${this.endpoint}`, xml, { headers: new HttpHeaders().set('Content-Type', 'application/xml'), params: new HttpParams().set('spName', name) - }); + }).pipe(catchError(error => { + return throwError({ errorCode: error.status, errorMessage: `Unable to upload file ... ${error.error}` }); + })); } createFromUrl(name: string, url: string): Observable { @@ -53,7 +55,9 @@ export class ResolverService { return this.http.post(`${this.base}${this.endpoint}`, body, { headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded'), params: new HttpParams().set('spName', name) - }); + }).pipe(catchError(error => { + return throwError({ errorCode: error.status, errorMessage: `Unable to upload file ... ${error.error}` }); + })); } preview(id: string): Observable { diff --git a/ui/src/app/metadata/filter/container/edit-filter.component.html b/ui/src/app/metadata/filter/container/edit-filter.component.html index 0cf1e5129..f0eea6d90 100644 --- a/ui/src/app/metadata/filter/container/edit-filter.component.html +++ b/ui/src/app/metadata/filter/container/edit-filter.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/ui/src/app/metadata/filter/container/new-filter.component.html b/ui/src/app/metadata/filter/container/new-filter.component.html index 58b46be99..47f622e3b 100644 --- a/ui/src/app/metadata/filter/container/new-filter.component.html +++ b/ui/src/app/metadata/filter/container/new-filter.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/ui/src/app/metadata/manager/component/provider-search.component.html b/ui/src/app/metadata/manager/component/provider-search.component.html index bedc6ad7d..29479de5d 100644 --- a/ui/src/app/metadata/manager/component/provider-search.component.html +++ b/ui/src/app/metadata/manager/component/provider-search.component.html @@ -1,6 +1,6 @@
-
+
-
+
+ (onSave)="save()" + role="navigation">
diff --git a/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts b/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts index 4485409bc..d2c16cb6b 100644 --- a/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts +++ b/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts @@ -42,8 +42,8 @@ export const LocalDynamicMetadataProviderWizard: Wizard