diff --git a/backend/src/main/resources/i18n/messages_en.properties b/backend/src/main/resources/i18n/messages_en.properties index 3d4670252..d666ef6c9 100644 --- a/backend/src/main/resources/i18n/messages_en.properties +++ b/backend/src/main/resources/i18n/messages_en.properties @@ -70,6 +70,9 @@ value.encryption=Encryption value.both=Both value.file-backed-http-metadata-provider=FileBackedHttpMetadataProvider +value.file-system-metadata-provider=FileSystemMetadataProvider +value.local-dynamic-metadata-provider=LocalDynamicMetadataProvider +value.dynamic-http-metadata-provider=DynamicHttpMetadataProvider value.entity-attributes-filter=EntityAttributes Filter value.spdescriptor=SPSSODescriptor value.attr-auth-descriptor=AttributeAuthorityDescriptor @@ -293,6 +296,8 @@ label.metadata-provider-status=Metadata Provider Status label.enable-provider-upon-saving=Enable Metadata Provider upon saving? label.certificate-type=Type +label.metadata-file=Metadata File + label.enable-filter=Enable Filter? label.required-valid-until=Required Valid Until Filter label.max-validity-interval=Max Validity Interval diff --git a/ui/src/app/metadata/domain/model/providers/file-system-metadata-provider.ts b/ui/src/app/metadata/domain/model/providers/file-system-metadata-provider.ts new file mode 100644 index 000000000..e884151c1 --- /dev/null +++ b/ui/src/app/metadata/domain/model/providers/file-system-metadata-provider.ts @@ -0,0 +1,7 @@ +import { BaseMetadataProvider } from './base-metadata-provider'; + +export interface FileSystemMetadataProvider extends BaseMetadataProvider { + id: string; + metadataFile: string; + reloadableMetadataResolverAttributes: any; +} diff --git a/ui/src/app/metadata/provider/container/provider-wizard-step.component.ts b/ui/src/app/metadata/provider/container/provider-wizard-step.component.ts index 05d121bba..9ff4ded23 100644 --- a/ui/src/app/metadata/provider/container/provider-wizard-step.component.ts +++ b/ui/src/app/metadata/provider/container/provider-wizard-step.component.ts @@ -1,6 +1,6 @@ import { Component, OnDestroy } from '@angular/core'; import { Observable, Subject } from 'rxjs'; -import { withLatestFrom, map, distinctUntilChanged, skipWhile } from 'rxjs/operators'; +import { withLatestFrom, map, distinctUntilChanged, skipWhile, filter } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import * as fromProvider from '../reducer'; @@ -42,7 +42,9 @@ export class ProviderWizardStepComponent implements OnDestroy { constructor( private store: Store, ) { - this.schema$ = this.store.select(fromWizard.getParsedSchema); + this.schema$ = this.store.select(fromWizard.getSchema).pipe( + filter(s => s && Object.keys(s.properties).length > 0) + ); this.definition$ = this.store.select(fromWizard.getWizardDefinition); this.changes$ = this.store.select(fromProvider.getEntityChanges); diff --git a/ui/src/app/metadata/provider/model/base.provider.form.ts b/ui/src/app/metadata/provider/model/base.provider.form.ts index 459eaa956..ecbcab666 100644 --- a/ui/src/app/metadata/provider/model/base.provider.form.ts +++ b/ui/src/app/metadata/provider/model/base.provider.form.ts @@ -1,6 +1,5 @@ import { Wizard } from '../../../wizard/model'; import { BaseMetadataProvider } from '../../domain/model/providers'; -import { UriValidator } from '../../../shared/validation/uri.validator'; export const BaseMetadataProviderEditor: Wizard = { label: 'BaseMetadataProvider', @@ -30,14 +29,6 @@ export const BaseMetadataProviderEditor: Wizard = { params: [value] } : null; return err; - }, - '/metadataURL': (value, property, form) => { - return !UriValidator.isUri(value) ? { - code: 'INVALID_URI', - path: `#${property.path}`, - message: 'message.uri-valid-format', - params: [value] - } : null; } }; return validators; diff --git a/ui/src/app/metadata/provider/model/file-backed-http.provider.form.ts b/ui/src/app/metadata/provider/model/file-backed-http.provider.form.ts index 2c8103438..f6bd3796f 100644 --- a/ui/src/app/metadata/provider/model/file-backed-http.provider.form.ts +++ b/ui/src/app/metadata/provider/model/file-backed-http.provider.form.ts @@ -1,6 +1,7 @@ import { Wizard } from '../../../wizard/model'; import { FileBackedHttpMetadataProvider } from '../../domain/model/providers/file-backed-http-metadata-provider'; import { BaseMetadataProviderEditor } from './base.provider.form'; +import { UriValidator } from '../../../shared/validation/uri.validator'; export const FileBackedHttpMetadataProviderWizard: Wizard = { ...BaseMetadataProviderEditor, @@ -17,6 +18,14 @@ export const FileBackedHttpMetadataProviderWizard: Wizard { + return !UriValidator.isUri(value) ? { + code: 'INVALID_URI', + path: `#${property.path}`, + message: 'message.uri-valid-format', + params: [value] + } : null; + }; return validators; }, steps: [ diff --git a/ui/src/app/metadata/provider/model/file-system.provider.form.ts b/ui/src/app/metadata/provider/model/file-system.provider.form.ts new file mode 100644 index 000000000..e84e79aa4 --- /dev/null +++ b/ui/src/app/metadata/provider/model/file-system.provider.form.ts @@ -0,0 +1,112 @@ +import { Wizard } from '../../../wizard/model'; +import { FileSystemMetadataProvider } from '../../domain/model/providers/file-system-metadata-provider'; +import { BaseMetadataProviderEditor } from './base.provider.form'; + +export const FileSystemMetadataProviderWizard: Wizard = { + ...BaseMetadataProviderEditor, + label: 'FileSystemMetadataProvider', + type: 'FileSystemMetadataResolver', + 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: 'assets/schema/provider/file-system.schema.json', + fields: [ + 'xmlId', + 'metadataFile' + ], + fieldsets: [ + { + type: 'group-lg', + class: ['col-12'], + fields: [ + 'xmlId', + 'metadataFile' + ] + } + ] + }, + { + id: 'reloading', + label: 'label.reloading-attributes', + index: 3, + initialValues: [], + schema: 'assets/schema/provider/file-system.schema.json', + fields: [ + 'reloadableMetadataResolverAttributes' + ], + fieldsets: [ + { + type: 'group-lg', + class: ['col-12'], + fields: [ + 'reloadableMetadataResolverAttributes' + ] + } + ] + }, + { + id: 'summary', + label: 'label.finished', + index: 4, + initialValues: [], + schema: 'assets/schema/provider/file-system.schema.json', + fields: [ + 'enabled' + ], + fieldsets: [ + { + type: 'group-lg', + class: ['col-12'], + fields: [ + 'enabled' + ] + } + ] + } + ] +}; + + +export const FileSystemMetadataProviderEditor: Wizard = { + ...FileSystemMetadataProviderWizard, + steps: [ + { + id: 'common', + label: 'label.common-attributes', + index: 1, + initialValues: [], + schema: 'assets/schema/provider/filebacked-http-common.editor.schema.json', + fields: [ + 'enabled', + 'xmlId', + 'metadataFile' + ] + }, + { + id: 'reloading', + label: 'label.reloading-attributes', + index: 2, + initialValues: [], + schema: 'assets/schema/provider/filebacked-http-reloading.schema.json', + fields: [ + 'reloadableMetadataResolverAttributes' + ] + } + ] +}; diff --git a/ui/src/app/metadata/provider/model/index.ts b/ui/src/app/metadata/provider/model/index.ts index cfb64a08d..02ef91ec7 100644 --- a/ui/src/app/metadata/provider/model/index.ts +++ b/ui/src/app/metadata/provider/model/index.ts @@ -1,12 +1,15 @@ import { FileBackedHttpMetadataProviderWizard } from './file-backed-http.provider.form'; import { FileBackedHttpMetadataProviderEditor } from './file-backed-http.provider.form'; +import { FileSystemMetadataProviderWizard, FileSystemMetadataProviderEditor } from './file-system.provider.form'; export const MetadataProviderWizardTypes = [ - FileBackedHttpMetadataProviderWizard + FileBackedHttpMetadataProviderWizard, + FileSystemMetadataProviderWizard ]; export const MetadataProviderEditorTypes = [ - FileBackedHttpMetadataProviderEditor + FileBackedHttpMetadataProviderEditor, + FileSystemMetadataProviderEditor ]; export * from './file-backed-http.provider.form'; diff --git a/ui/src/app/metadata/provider/model/provider.form.ts b/ui/src/app/metadata/provider/model/provider.form.ts index 28e5794c5..26fbdd966 100644 --- a/ui/src/app/metadata/provider/model/provider.form.ts +++ b/ui/src/app/metadata/provider/model/provider.form.ts @@ -1,6 +1,5 @@ import { Wizard, WizardStep } from '../../../wizard/model'; import { MetadataProvider } from '../../domain/model'; -import { Metadata } from '../../domain/domain.type'; import { BaseMetadataProviderEditor } from './base.provider.form'; export const MetadataProviderWizard: Wizard = { @@ -17,7 +16,17 @@ export const MetadataProviderWizard: Wizard = { fields: [ 'name', '@type' + ], + fieldsets: [ + { + type: 'section', + class: ['col-12'], + fields: [ + 'name', + '@type' + ] + } ] } - ] as WizardStep[] + ] as WizardStep[], }; diff --git a/ui/src/app/wizard/reducer/index.ts b/ui/src/app/wizard/reducer/index.ts index 0d7176565..30f00b18d 100644 --- a/ui/src/app/wizard/reducer/index.ts +++ b/ui/src/app/wizard/reducer/index.ts @@ -61,12 +61,14 @@ export const getSplitSchema = (schema: any, step: WizardStep) => { const required = (schema.required || []).filter(val => keys.indexOf(val) > -1); let s: any = { type: schema.type, - definitions: schema.definitions, properties: { ...keys.reduce( (properties, key) => ({ ...properties, [key]: schema.properties[key] }) , {}) } }; + if (schema.definitions) { + s.definitions = schema.definitions; + } if (required && required.length) { s.required = required; } diff --git a/ui/src/assets/schema/provider/file-system.schema.json b/ui/src/assets/schema/provider/file-system.schema.json new file mode 100644 index 000000000..e015b15d8 --- /dev/null +++ b/ui/src/assets/schema/provider/file-system.schema.json @@ -0,0 +1,166 @@ +{ + "type": "object", + "required": [ + "name", + "@type", + "xmlId", + "metadataFile" + ], + "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 + }, + "metadataFile": { + "title": "label.metadata-file", + "description": "tooltip.metadata-file", + "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": { + "minRefreshDelay": { + "title": "label.min-refresh-delay", + "description": "tooltip.min-refresh-delay", + "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)?)?$" + }, + "maxRefreshDelay": { + "title": "label.max-refresh-delay", + "description": "tooltip.max-refresh-delay", + "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)?)?$" + }, + "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 + }, + "resolveViaPredicatesOnly": { + "title": "label.resolve-via-predicates-only", + "description": "tooltip.resolve-via-predicates-only", + "type": "boolean", + "widget": { + "id": "boolean-radio" + }, + "oneOf": [ + { + "enum": [ + true + ], + "description": "value.true" + }, + { + "enum": [ + false + ], + "description": "value.false" + } + ], + "default": true + }, + "expirationWarningThreshold": { + "title": "label.expiration-warning-threshold", + "description": "tooltip.expiration-warning-threshold", + "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/ui/src/assets/schema/provider/filebacked-http-reloading.schema.json b/ui/src/assets/schema/provider/filebacked-http-reloading.schema.json index f7f884e6a..de58d5137 100644 --- a/ui/src/assets/schema/provider/filebacked-http-reloading.schema.json +++ b/ui/src/assets/schema/provider/filebacked-http-reloading.schema.json @@ -60,51 +60,6 @@ "minimum": 0, "maximum": 1, "default": null - }, - "resolveViaPredicatesOnly": { - "title": "label.resolve-via-predicates-only", - "description": "tooltip.resolve-via-predicates-only", - "type": "boolean", - "widget": { - "id": "boolean-radio" - }, - "oneOf": [ - { - "enum": [ - true - ], - "description": "value.true" - }, - { - "enum": [ - false - ], - "description": "value.false" - } - ], - "default": true - }, - "expirationWarningThreshold": { - "title": "label.expiration-warning-threshold", - "description": "tooltip.expiration-warning-threshold", - "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)?)?$" } } } diff --git a/ui/src/assets/schema/provider/metadata-provider.schema.json b/ui/src/assets/schema/provider/metadata-provider.schema.json index 6cd17323f..3b3179815 100644 --- a/ui/src/assets/schema/provider/metadata-provider.schema.json +++ b/ui/src/assets/schema/provider/metadata-provider.schema.json @@ -28,6 +28,12 @@ "FileBackedHttpMetadataResolver" ], "description": "value.file-backed-http-metadata-provider" + }, + { + "enum": [ + "FileSystemMetadataResolver" + ], + "description": "value.file-system-metadata-provider" } ] } @@ -35,14 +41,5 @@ "required": [ "name", "@type" - ], - "fieldsets": [ - { - "type": "section", - "fields": [ - "name", - "@type" - ] - } ] } \ No newline at end of file