diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolverUiDefinitionController.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolverUiDefinitionController.groovy index 4da9b949f..8232c687d 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolverUiDefinitionController.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolverUiDefinitionController.groovy @@ -11,7 +11,7 @@ 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.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 @@ -41,9 +41,9 @@ class MetadataResolverUiDefinitionController { case SchemaType.FILESYSTEM_METADATA_RESOLVER: jsonSchemaLocation = filesystemMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry) break -/* case SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER: + case SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER: jsonSchemaLocation = localDynamicMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry) - break*/ + break /* case SchemaType.DYNAMIC_HTTP_METADATA_RESOLVER: jsonSchemaLocation = dynamicHttpMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry) break*/ 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 4c4ad86db..1f58fb3cc 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 @@ -13,7 +13,7 @@ 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; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.FILESYSTEM_METADATA_RESOLVER; -//import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER; //import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.DYNAMIC_HTTP_METADATA_RESOLVER; /** @@ -38,10 +38,10 @@ public class JsonSchemaComponentsConfiguration { @Setter private String filesystemMetadataResolverUiSchemaLocation = "classpath:file-system-metadata-provider.schema.json"; -/* TODO: Will be added as part of SHIBUI-703 + //Configured via @ConfigurationProperties (using setter method) with 'shibui.local-dynamic-metadata-provider-ui-schema-location' property and + // default value set here if that property is not explicitly set in application.properties @Setter private String localDynamicMetadataResolverUiSchemaLocation = "classpath:local-dynamic-metadata-provider.schema.json"; -*/ /* TODO: Will be added as part of SHIBUI-704 @Setter @@ -68,20 +68,19 @@ public JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(Res .resourceLoader(resourceLoader) .jacksonMapper(jacksonMapper) .detectMalformedJson(true) - .build()); - /*.register(DYNAMIC_HTTP_METADATA_RESOLVER, JsonSchemaLocationBuilder.with() - .jsonSchemaLocation(dynamicHttpMetadataResolverUiSchemaLocation) - .resourceLoader(resourceLoader) - .jacksonMapper(jacksonMapper) - .detectMalformedJson(true) .build()) .register(LOCAL_DYNAMIC_METADATA_RESOLVER, JsonSchemaLocationBuilder.with() .jsonSchemaLocation(localDynamicMetadataResolverUiSchemaLocation) .resourceLoader(resourceLoader) .jacksonMapper(jacksonMapper) .detectMalformedJson(true) - .build());*/ - + .build()); + /*.register(DYNAMIC_HTTP_METADATA_RESOLVER, JsonSchemaLocationBuilder.with() + .jsonSchemaLocation(dynamicHttpMetadataResolverUiSchemaLocation) + .resourceLoader(resourceLoader) + .jacksonMapper(jacksonMapper) + .detectMalformedJson(true) + .build())*/ } @Bean diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java index 20ca36251..6b722803a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/LocalDynamicMetadataResolver.java @@ -16,6 +16,7 @@ public class LocalDynamicMetadataResolver extends MetadataResolver { public LocalDynamicMetadataResolver() { type = "LocalDynamicMetadataResolver"; + setDoInitialization(false); } private String sourceDirectory; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlLocalDynamicMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlLocalDynamicMetadataResolver.java index be6adb54d..bca96b876 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlLocalDynamicMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlLocalDynamicMetadataResolver.java @@ -38,11 +38,13 @@ public OpenSamlLocalDynamicMetadataResolver(ParserPool parserPool, @Override protected void initMetadataResolver() throws ComponentInitializationException { - super.initMetadataResolver(); + if (sourceResolver.getDoInitialization()) { + super.initMetadataResolver(); - delegate.addIndexedDescriptorsFromBackingStore(this.getBackingStore(), - this.sourceResolver.getResourceId(), - indexWriter); + delegate.addIndexedDescriptorsFromBackingStore(this.getBackingStore(), + this.sourceResolver.getResourceId(), + indexWriter); + } } public void refresh() throws ComponentInitializationException { 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 0083450b3..344a6efcf 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 @@ -3,7 +3,7 @@ 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; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.FILESYSTEM_METADATA_RESOLVER; -//import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER; //import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.DYNAMIC_HTTP_METADATA_RESOLVER; /** @@ -52,11 +52,18 @@ public static JsonSchemaResourceLocation filesystemMetadataProviderSchema(JsonSc .orElseThrow(() -> new IllegalStateException("JSON schema resource location for filesystem metadata resolver is not registered.")); } -/* public static JsonSchemaResourceLocation localDynamicMetadataProviderSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { + /** + * Searches local dynamic metadata resolver JSON schema resource location object in the given location registry. + * + * @param resourceLocationRegistry + * @return local dynamic metadata resolver JSON schema resource location object + * @throws IllegalStateException if schema is not found in the given registry + */ + public static JsonSchemaResourceLocation localDynamicMetadataProviderSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { return resourceLocationRegistry .lookup(LOCAL_DYNAMIC_METADATA_RESOLVER) .orElseThrow(() -> new IllegalStateException("JSON schema resource location for local dynamic metadata resolver is not registered.")); - }*/ + } /* public static JsonSchemaResourceLocation dynamicHttpMetadataProviderSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { return resourceLocationRegistry 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 05280d45e..11c03006a 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 @@ -102,8 +102,8 @@ public enum SchemaType { // resolver types FILE_BACKED_HTTP_METADATA_RESOLVER("FileBackedHttpMetadataResolver"), - FILESYSTEM_METADATA_RESOLVER("FilesystemMetadataResolver"); -// LOCAL_DYNAMIC_METADATA_RESOLVER, + FILESYSTEM_METADATA_RESOLVER("FilesystemMetadataResolver"), + LOCAL_DYNAMIC_METADATA_RESOLVER("LocalDynamicMetadataResolver"); // DYNAMIC_HTTP_METADATA_RESOLVER; String jsonType; 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 638a6307f..ccb77164c 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 @@ -79,12 +79,15 @@ private OpenSamlLocalDynamicMetadataResolver convertToOpenSamlRepresentation(Loc IndexWriter indexWriter = indexWriterService.getIndexWriter(resolver.getResourceId()); XMLObjectLoadSaveManager manager = null; - try { - manager = new FilesystemLoadSaveManager(placeholderResolverService() - .resolveValueFromPossibleTokenPlaceholder(resolver.getSourceDirectory())); - } catch (ConstraintViolationException e) { - // the base directory string instance was null or empty - //TODO: What should we do here? Currently, this causes a test to fail. + if (resolver.getDoInitialization()) { + try { + manager = new FilesystemLoadSaveManager(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(resolver.getSourceDirectory())); + } catch (ConstraintViolationException e) { + // the base directory string instance was null or empty + //TODO: What should we do here? Currently, this causes a test to fail. + throw new RuntimeException("An exception occurred while attempting to instantiate a FilesystemLoadSaveManger for the path: " + resolver.getSourceDirectory(), e); + } } OpenSamlLocalDynamicMetadataResolver openSamlResolver = new OpenSamlLocalDynamicMetadataResolver(openSamlObjects.getParserPool(), indexWriter, resolver, manager); diff --git a/backend/src/main/resources/i18n/messages_en.properties b/backend/src/main/resources/i18n/messages_en.properties index e156a803d..f8d5e4c8c 100644 --- a/backend/src/main/resources/i18n/messages_en.properties +++ b/backend/src/main/resources/i18n/messages_en.properties @@ -77,6 +77,8 @@ value.entity-attributes-filter=EntityAttributes Filter value.spdescriptor=SPSSODescriptor value.attr-auth-descriptor=AttributeAuthorityDescriptor +value.local-dynamic-metadata-provider=LocalDynamicMetadataProvider + brand.header.title=Source Management brand.logo-link-label=Shibboleth brand.logo-link-description=Link to Shibboleth Website @@ -338,6 +340,12 @@ label.attribute-eduPersonUniqueId=eduPersonUniqueId label.attribute-employeeNumber=employeeNumber label.force-authn=Force AuthN +label.source-directory=Source Directory +label.min-cache-duration=Min Cache Duration +label.max-cache-duration=Max Cache Duration +label.max-idle-entity-data=Max Idle Entity Data +label.remove-idle-entity-data=Remove Idle Entity Data? +label.cleanup-task-interval=Cleanup Task Interval label.do-resolver-initialization=Initialize label.file-doesnt-exist=The file specified in the resolver does not exist on the file system. Therefore, the resolver cannot be initialized. @@ -464,4 +472,10 @@ tooltip.filter-name=Filter Name tooltip.enable-filter=Enable Filter? tooltip.enable-service=Enable Service? +tooltip.source-directory=Convenience mechanism for wiring a FilesystemLoadSaveManager, loading from the specified source directory in the local filesystem. This attribute will be ignored if sourceManagerRef is also specified. Either this attribute or sourceManagerRef is required. +tooltip.min-cache-duration=The minimum duration for which metadata will be cached before it is refreshed. +tooltip.max-cache-duration=The maximum duration for which metadata will be cached before it is refreshed. +tooltip.max-idle-entity-data=The maximum duration for which metadata will be allowed to be idle (no requests for it) before it is removed from the cache. +tooltip.remove-idle-entity-data=Flag indicating whether idle metadata should be removed. +tooltip.cleanup-task-interval=The interval at which the internal cleanup task should run. This task performs background maintenance tasks, such as the removal of expired and idle metadata. tooltip.do-resolver-initialization=Initialize this resolver? In the case of Filesystem resolvers, this will cause the system to read the file and index the resolver. diff --git a/backend/src/main/resources/local-dynamic-metadata-provider.schema.json b/backend/src/main/resources/local-dynamic-metadata-provider.schema.json new file mode 100644 index 000000000..04aa496f9 --- /dev/null +++ b/backend/src/main/resources/local-dynamic-metadata-provider.schema.json @@ -0,0 +1,188 @@ +{ + "type": "object", + "required": [ + "name", + "@type", + "xmlId", + "sourceDirectory" + ], + "properties": { + "name": { + "title": "label.metadata-provider-name", + "description": "tooltip.metadata-provider-name", + "type": "string", + "widget": { + "id": "string", + "help": "message.must-be-unique" + } + }, + "@type": { + "title": "label.metadata-provider-type", + "description": "tooltip.metadata-provider-type", + "placeholder": "label.select-metadata-type", + "type": "string", + "readOnly": true, + "widget": { + "id": "select", + "disabled": true + }, + "oneOf": [ + { + "enum": [ + "FileSystemMetadataResolver" + ], + "description": "value.file-system-metadata-provider" + } + ] + }, + "xmlId": { + "title": "label.xml-id", + "description": "tooltip.xml-id", + "type": "string", + "default": "", + "minLength": 1 + }, + "sourceDirectory": { + "title": "label.source-directory", + "description": "tooltip.source-directory", + "type": "string", + "default": "", + "minLength": 1 + }, + "enabled": { + "title": "label.enable-provider-upon-saving", + "description": "tooltip.enable-provider-upon-saving", + "type": "boolean", + "default": false + }, + "dynamicMetadataResolverAttributes": { + "type": "object", + "properties": { + "refreshDelayFactor": { + "title": "label.refresh-delay-factor", + "description": "tooltip.refresh-delay-factor", + "type": "number", + "widget": { + "id": "number", + "step": 0.01 + }, + "placeholder": "label.real-number", + "minimum": 0, + "maximum": 0.99, + "default": null + }, + "minCacheDuration": { + "title": "label.min-cache-duration", + "description": "tooltip.min-cache-duration", + "type": "string", + "placeholder": "label.duration", + "widget": { + "id": "datalist", + "data": [ + "PT0S", + "PT30S", + "PT1M", + "PT10M", + "PT30M", + "PT1H", + "PT4H", + "PT12H", + "PT24H" + ] + }, + "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)?)?$" + }, + "maxCacheDuration": { + "title": "label.max-cache-duration", + "description": "tooltip.max-cache-duration", + "type": "string", + "placeholder": "label.duration", + "widget": { + "id": "datalist", + "data": [ + "PT0S", + "PT30S", + "PT1M", + "PT10M", + "PT30M", + "PT1H", + "PT4H", + "PT12H", + "PT24H" + ] + }, + "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)?)?$" + }, + "maxIdleEntityData": { + "title": "label.max-idle-entity-data", + "description": "tooltip.max-idle-entity-data", + "type": "string", + "placeholder": "label.duration", + "widget": { + "id": "datalist", + "data": [ + "PT0S", + "PT30S", + "PT1M", + "PT10M", + "PT30M", + "PT1H", + "PT4H", + "PT12H", + "PT24H" + ] + }, + "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", + "type": "string", + "placeholder": "label.duration", + "widget": { + "id": "datalist", + "data": [ + "PT0S", + "PT30S", + "PT1M", + "PT10M", + "PT30M", + "PT1H", + "PT4H", + "PT12H", + "PT24H" + ] + }, + "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)?)?$" + } + } + } + } +} \ 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 5c4efc0b6..3624f6ce3 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 @@ -14,6 +14,7 @@ import spock.lang.Specification import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.* 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.FILESYSTEM_METADATA_RESOLVER +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES /** @@ -64,6 +65,12 @@ class BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests extends Speci .jacksonMapper(jacksonMapper) .detectMalformedJson(false) .build()) + .register(LOCAL_DYNAMIC_METADATA_RESOLVER, JsonSchemaLocationBuilder.with() + .jsonSchemaLocation('classpath:local-dynamic-metadata-provider.schema.json') + .resourceLoader(resourceLoader) + .jacksonMapper(jacksonMapper) + .detectMalformedJson(false) + .build()) } } } \ No newline at end of file diff --git a/ui/src/app/metadata/domain/model/providers/local-dynamic-metadata-provider.ts b/ui/src/app/metadata/domain/model/providers/local-dynamic-metadata-provider.ts new file mode 100644 index 000000000..b56f9237b --- /dev/null +++ b/ui/src/app/metadata/domain/model/providers/local-dynamic-metadata-provider.ts @@ -0,0 +1,7 @@ +import { BaseMetadataProvider } from './base-metadata-provider'; + +export interface LocalDynamicMetadataProvider extends BaseMetadataProvider { + id: string; + sourceDirectory: string; + reloadableMetadataResolverAttributes: any; +} diff --git a/ui/src/app/metadata/provider/model/index.ts b/ui/src/app/metadata/provider/model/index.ts index 278652334..2ccf25aea 100644 --- a/ui/src/app/metadata/provider/model/index.ts +++ b/ui/src/app/metadata/provider/model/index.ts @@ -1,19 +1,23 @@ import { FileBackedHttpMetadataProviderWizard } from './file-backed-http.provider.form'; import { FileBackedHttpMetadataProviderEditor } from './file-backed-http.provider.form'; +import { LocalDynamicMetadataProviderWizard, LocalDynamicMetadataProviderEditor } from './local-dynamic.provider.form'; import { FileSystemMetadataProviderWizard, FileSystemMetadataProviderEditor } from './file-system.provider.form'; export const MetadataProviderWizardTypes = [ FileBackedHttpMetadataProviderWizard, - FileSystemMetadataProviderWizard + FileSystemMetadataProviderWizard, + LocalDynamicMetadataProviderWizard ]; export const MetadataProviderEditorTypes = [ FileBackedHttpMetadataProviderEditor, + LocalDynamicMetadataProviderEditor, FileSystemMetadataProviderEditor ]; export const FilterableProviders = [ - FileBackedHttpMetadataProviderEditor.type + FileBackedHttpMetadataProviderEditor.type, + LocalDynamicMetadataProviderEditor.type ]; export * from './file-backed-http.provider.form'; 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 new file mode 100644 index 000000000..e04bc917c --- /dev/null +++ b/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts @@ -0,0 +1,112 @@ +import { Wizard } from '../../../wizard/model'; +import { LocalDynamicMetadataProvider } from '../../domain/model/providers/local-dynamic-metadata-provider'; +import { BaseMetadataProviderEditor } from './base.provider.form'; + +export const LocalDynamicMetadataProviderWizard: Wizard = { + ...BaseMetadataProviderEditor, + label: 'LocalDynamicMetadataProvider', + type: 'LocalDynamicMetadataResolver', + getValidators(namesList: string[] = [], xmlIdList: string[] = []): any { + const validators = BaseMetadataProviderEditor.getValidators(namesList); + validators['/xmlId'] = (value, property, form) => { + const err = xmlIdList.indexOf(value) > -1 ? { + code: 'INVALID_ID', + path: `#${property.path}`, + message: 'message.id-unique', + params: [value] + } : null; + return err; + }; + return validators; + }, + steps: [ + { + id: 'common', + label: 'label.common-attributes', + index: 2, + initialValues: [], + schema: '/api/ui/MetadataResolver/LocalDynamicMetadataResolver', + fields: [ + 'xmlId', + 'sourceDirectory' + ], + fieldsets: [ + { + type: 'group-lg', + class: ['col-12'], + fields: [ + 'xmlId', + 'sourceDirectory' + ] + } + ] + }, + { + id: 'reloading', + label: 'label.reloading-attributes', + index: 3, + initialValues: [], + schema: '/api/ui/MetadataResolver/LocalDynamicMetadataResolver', + fields: [ + 'dynamicMetadataResolverAttributes' + ], + fieldsets: [ + { + type: 'group-lg', + class: ['col-12'], + fields: [ + 'dynamicMetadataResolverAttributes' + ] + } + ] + }, + { + id: 'summary', + label: 'label.finished', + index: 4, + initialValues: [], + schema: '/api/ui/MetadataResolver/LocalDynamicMetadataResolver', + fields: [ + 'enabled' + ], + fieldsets: [ + { + type: 'group-lg', + class: ['col-12'], + fields: [ + 'enabled' + ] + } + ] + } + ] +}; + + +export const LocalDynamicMetadataProviderEditor: Wizard = { + ...LocalDynamicMetadataProviderWizard, + steps: [ + { + id: 'common', + label: 'label.common-attributes', + index: 1, + initialValues: [], + schema: '/api/ui/MetadataResolver/LocalDynamicMetadataResolver', + fields: [ + 'enabled', + 'xmlId', + 'sourceDirectory', + ] + }, + { + id: 'reloading', + label: 'label.reloading-attributes', + index: 2, + initialValues: [], + schema: '/api/ui/MetadataResolver/LocalDynamicMetadataResolver', + fields: [ + 'dynamicMetadataResolverAttributes' + ] + } + ] +}; diff --git a/ui/src/assets/schema/provider/local-dynamic.schema.json b/ui/src/assets/schema/provider/local-dynamic.schema.json new file mode 100644 index 000000000..7f465221c --- /dev/null +++ b/ui/src/assets/schema/provider/local-dynamic.schema.json @@ -0,0 +1,188 @@ +{ + "type": "object", + "required": [ + "name", + "@type", + "xmlId", + "sourceDirectory" + ], + "properties": { + "name": { + "title": "label.metadata-provider-name", + "description": "tooltip.metadata-provider-name", + "type": "string", + "widget": { + "id": "string", + "help": "message.must-be-unique" + } + }, + "@type": { + "title": "label.metadata-provider-type", + "description": "tooltip.metadata-provider-type", + "placeholder": "label.select-metadata-type", + "type": "string", + "readOnly": true, + "widget": { + "id": "select", + "disabled": true + }, + "oneOf": [ + { + "enum": [ + "FileSystemMetadataResolver" + ], + "description": "value.file-system-metadata-provider" + } + ] + }, + "xmlId": { + "title": "label.xml-id", + "description": "tooltip.xml-id", + "type": "string", + "default": "", + "minLength": 1 + }, + "sourceDirectory": { + "title": "label.source-directory", + "description": "tooltip.source-directory", + "type": "string", + "default": "", + "minLength": 1 + }, + "enabled": { + "title": "label.enable-provider-upon-saving", + "description": "tooltip.enable-provider-upon-saving", + "type": "boolean", + "default": false + }, + "reloadableMetadataResolverAttributes": { + "type": "object", + "properties": { + "refreshDelayFactor": { + "title": "label.refresh-delay-factor", + "description": "tooltip.refresh-delay-factor", + "type": "number", + "widget": { + "id": "number", + "step": 0.01 + }, + "placeholder": "label.real-number", + "minimum": 0, + "maximum": 1, + "default": null + }, + "minCacheDuration": { + "title": "label.min-cache-duration", + "description": "tooltip.min-cache-duration", + "type": "string", + "placeholder": "label.duration", + "widget": { + "id": "datalist", + "data": [ + "PT0S", + "PT30S", + "PT1M", + "PT10M", + "PT30M", + "PT1H", + "PT4H", + "PT12H", + "PT24H" + ] + }, + "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)?)?$" + }, + "maxCacheDuration": { + "title": "label.max-cache-duration", + "description": "tooltip.max-cache-duration", + "type": "string", + "placeholder": "label.duration", + "widget": { + "id": "datalist", + "data": [ + "PT0S", + "PT30S", + "PT1M", + "PT10M", + "PT30M", + "PT1H", + "PT4H", + "PT12H", + "PT24H" + ] + }, + "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)?)?$" + }, + "maxIdleEntityData": { + "title": "label.max-idle-entity-data", + "description": "tooltip.max-idle-entity-data", + "type": "string", + "placeholder": "label.duration", + "widget": { + "id": "datalist", + "data": [ + "PT0S", + "PT30S", + "PT1M", + "PT10M", + "PT30M", + "PT1H", + "PT4H", + "PT12H", + "PT24H" + ] + }, + "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", + "type": "string", + "placeholder": "label.duration", + "widget": { + "id": "datalist", + "data": [ + "PT0S", + "PT30S", + "PT1M", + "PT10M", + "PT30M", + "PT1H", + "PT4H", + "PT12H", + "PT24H" + ] + }, + "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)?)?$" + } + } + } + } +} \ No newline at end of file