From 4a224cb59c93d6b1140ff87d14f10b234fb567c8 Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Tue, 5 Dec 2023 13:01:10 +0100 Subject: [PATCH 1/3] :sparkles: [#2] Implement type definitions for Cosign v1 component schema --- src/formio/components/cosign.ts | 37 +++++++++++++ src/formio/components/index.ts | 1 + src/formio/index.ts | 5 +- test-d/formio/components/cosign-v1.test-d.ts | 58 ++++++++++++++++++++ 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 src/formio/components/cosign.ts create mode 100644 test-d/formio/components/cosign-v1.test-d.ts diff --git a/src/formio/components/cosign.ts b/src/formio/components/cosign.ts new file mode 100644 index 0000000..f8c39e2 --- /dev/null +++ b/src/formio/components/cosign.ts @@ -0,0 +1,37 @@ +import {OFExtensions, StrictComponentSchema} from '..'; + +type TranslatableKeys = 'label' | 'description'; + +/** + * We don't currently support these properties - they get added in by base types, so we + * need to strip them out again. + */ +type KeysToOmit = + | 'hideLabel' + | 'placeholder' + | 'multiple' + | 'clearOnHide' + | 'conditional' + | 'errors' + | 'disabled' + | 'validateOn' + | 'tooltip'; + +export type CosignV1InputSchema = StrictComponentSchema & + Pick, 'openForms'>; + +/** + * The legacy Cosign component type, otherwise known as 'CosignOld'. + * + * The component does not actually provide any input data, it mostly functions as a + * marker in the form that cosigning is expected, hence the `never` value type. In the + * UI, it displays a button to start an (additional) login session to authenticate the + * cosigner and requires them to be physically in the same space. + * + * @group Form.io components + * @category Concrete types + */ +export interface CosignV1ComponentSchema extends Omit { + type: 'coSign'; + authPlugin: string; // plugin identifiers in the backend are dynamic +} diff --git a/src/formio/components/index.ts b/src/formio/components/index.ts index e8c0802..2948dbb 100644 --- a/src/formio/components/index.ts +++ b/src/formio/components/index.ts @@ -22,6 +22,7 @@ export * from './addressNL'; export * from './map'; export * from './editgrid'; export * from './signature'; +export * from './cosign'; // Layout components export * from './content'; diff --git a/src/formio/index.ts b/src/formio/index.ts index b77d613..82361fe 100644 --- a/src/formio/index.ts +++ b/src/formio/index.ts @@ -4,6 +4,7 @@ import { CheckboxComponentSchema, ColumnsComponentSchema, ContentComponentSchema, + CosignV1ComponentSchema, CurrencyComponentSchema, DateComponentSchema, DateTimeComponentSchema, @@ -79,7 +80,9 @@ export type AnyComponentSchema = // layout | ContentComponentSchema | ColumnsComponentSchema - | FieldsetComponentSchema; + | FieldsetComponentSchema + // deprecated + | CosignV1ComponentSchema; /** * Convenience type alias for all supported concrete component schema types. diff --git a/test-d/formio/components/cosign-v1.test-d.ts b/test-d/formio/components/cosign-v1.test-d.ts new file mode 100644 index 0000000..e856ce0 --- /dev/null +++ b/test-d/formio/components/cosign-v1.test-d.ts @@ -0,0 +1,58 @@ +import {expectAssignable, expectNotAssignable} from 'tsd'; + +import {CosignV1ComponentSchema} from '../../../lib/'; + +// minimal CoSign component schema +expectAssignable({ + id: 'yejak', + type: 'coSign', + key: 'someCoSign', + label: 'Some cosign', + authPlugin: 'digid', +}); + +// full, correct schema +expectAssignable({ + id: 'yejak', + type: 'coSign', + key: 'someCoSign', + // basic tab in builder form + label: 'Some cosign', + description: 'A description', + authPlugin: 'oidc-digid', + hidden: false, + // translations tab in builder form + openForms: { + translations: { + nl: { + label: 'foo', + description: 'bar', + }, + }, + }, +}); + +// different component type +expectNotAssignable({ + type: 'fieldset' as const, +}); + +// using unsupported properties +expectNotAssignable({ + id: 'yejak', + type: 'CoSign' as const, + key: 'someCoSign', + label: 'Some cosign', + authPlugin: 'digid', + hideLabel: true, +}); + +// multiple is not supported +expectNotAssignable({ + id: 'yejak', + type: 'CoSign' as const, + key: 'someCoSign', + label: 'Some cosign', + authPlugin: 'digid', + multiple: true as boolean, +}); From 63912a05333fd7c467a6b82181b370a027e34311 Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Tue, 5 Dec 2023 14:43:35 +0100 Subject: [PATCH 2/3] :sparkles: [#2] Implement 'new' cosign component schema type definitions --- src/formio/components/cosign.ts | 29 +++++ src/formio/index.ts | 2 + test-d/formio/components/cosign-v2.test-d.ts | 116 +++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 test-d/formio/components/cosign-v2.test-d.ts diff --git a/src/formio/components/cosign.ts b/src/formio/components/cosign.ts index f8c39e2..99ece67 100644 --- a/src/formio/components/cosign.ts +++ b/src/formio/components/cosign.ts @@ -1,4 +1,5 @@ import {OFExtensions, StrictComponentSchema} from '..'; +import {EmailInputSchema} from './email'; type TranslatableKeys = 'label' | 'description'; @@ -30,8 +31,36 @@ export type CosignV1InputSchema = StrictComponentSchema & * * @group Form.io components * @category Concrete types + * + * @deprecated + * + * The in-band cosign flow is problematic with existing DigiD/eHerkenning sessions. It + * is currently not scheduled for removal, but we recommend using the V2 variant for + * better UX. */ export interface CosignV1ComponentSchema extends Omit { type: 'coSign'; authPlugin: string; // plugin identifiers in the backend are dynamic } + +type V2KeysToOmit = 'hideLabel' | 'disabled' | 'placeholder'; + +/** + * The cosign component type, otherwise known as 'Cosign'. + * + * This is a custom component sharing most of the functionality with the email input + * component type - it collects the e-mail address of any/a cosigner so that they + * receive a notification they're expected to cosign. The actual cosigning happens + * out-of-band. This component *does* take form data input, as opposed to the V1 + * component implementation. + * + * @group Form.io components + * @category Concrete types + */ +export interface CosignV2ComponentSchema extends Omit { + type: 'cosign'; + validateOn: 'blur'; + authPlugin: string; // plugin identifiers in the backend are dynamic + defaultValue?: string; // no multiple support, so must always be a single string + autocomplete?: string; +} diff --git a/src/formio/index.ts b/src/formio/index.ts index 82361fe..2f9bea9 100644 --- a/src/formio/index.ts +++ b/src/formio/index.ts @@ -5,6 +5,7 @@ import { ColumnsComponentSchema, ContentComponentSchema, CosignV1ComponentSchema, + CosignV2ComponentSchema, CurrencyComponentSchema, DateComponentSchema, DateTimeComponentSchema, @@ -75,6 +76,7 @@ export type AnyComponentSchema = | AddressNLComponentSchema | NpFamilyMembersComponentSchema | SignatureComponentSchema + | CosignV2ComponentSchema | MapComponentSchema | EditGridComponentSchema // layout diff --git a/test-d/formio/components/cosign-v2.test-d.ts b/test-d/formio/components/cosign-v2.test-d.ts new file mode 100644 index 0000000..9e699b9 --- /dev/null +++ b/test-d/formio/components/cosign-v2.test-d.ts @@ -0,0 +1,116 @@ +import {expectAssignable, expectNotAssignable} from 'tsd'; + +import {CosignV2ComponentSchema} from '../../../lib/'; + +// minimal cosign component schema +expectAssignable({ + id: 'yejak', + type: 'cosign', + validateOn: 'blur', + key: 'someCoSign', + label: 'Some cosign', + authPlugin: 'digid', +}); + +// full, correct schema +expectAssignable({ + id: 'yejak', + type: 'cosign', + validateOn: 'blur', + // basic tab in builder form + label: 'Some cosign', + key: 'someCoSign', + description: 'A description', + tooltip: 'A tooltip', + authPlugin: 'oidc-digid', + showInSummary: true, + showInEmail: false, + showInPDF: true, + hidden: false, + clearOnHide: true, + isSensitiveData: true, + defaultValue: '', + autocomplete: 'email', + // advanced tab in builder form + conditional: { + show: undefined, + when: undefined, + eq: undefined, + }, + // validation tab in builder form + validate: { + required: false, + plugins: undefined, + }, + translatedErrors: { + nl: { + required: 'Je moet een waarde opgeven!!!', + }, + }, + errors: { + // translatedErrors is converted into errors by the backend + required: 'Je moet een waarde opgeven!!!', + }, + // registration tab in builder form + registration: { + attribute: '', + }, + // translations tab in builder form + openForms: { + translations: { + nl: { + label: 'foo', + description: 'bar', + tooltip: 'baz', + }, + }, + }, +}); + +// different component type +expectNotAssignable({ + type: 'fieldset' as const, +}); + +// using unsupported properties +expectNotAssignable({ + id: 'yejak', + type: 'cosign' as const, + validateOn: 'blur' as const, + key: 'someCoSign', + label: 'Some cosign', + authPlugin: 'digid', + hideLabel: true, +}); + +// multiple is not supported +expectNotAssignable({ + id: 'yejak', + type: 'cosign' as const, + validateOn: 'blur' as const, + key: 'someCoSign', + label: 'Some cosign', + authPlugin: 'digid', + multiple: true as boolean, +}); +expectNotAssignable({ + id: 'yejak', + type: 'cosign' as const, + validateOn: 'blur' as const, + key: 'someCoSign', + label: 'Some cosign', + authPlugin: 'digid', + defaultValue: [], +}); + +// while it shares functionality with email, we should not be able to use all +// email extensions +expectNotAssignable({ + id: 'yejak', + type: 'cosign' as const, + validateOn: 'blur' as const, + key: 'someCoSign', + label: 'Some cosign', + authPlugin: 'digid', + confirmationRecipient: true, +}); From 1c40152e494b9d15d89d827223018dfe83adf845 Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Tue, 5 Dec 2023 14:49:02 +0100 Subject: [PATCH 3/3] :fire: [#2] Drop (unintended) support for cosign registration attribute This snuck in accidentally because the component inherits from the email component in the implementation, but it was not a conscious decision. This does *not* make it impossible to send the data to StUF-ZDS, ZGW APIs or Objects API integration as the unmapped data is included by default in some form anyway or there are existing mechanisms to include it via custom data templates. --- src/formio/components/cosign.ts | 2 +- test-d/formio/components/cosign-v2.test-d.ts | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/formio/components/cosign.ts b/src/formio/components/cosign.ts index 99ece67..850683e 100644 --- a/src/formio/components/cosign.ts +++ b/src/formio/components/cosign.ts @@ -43,7 +43,7 @@ export interface CosignV1ComponentSchema extends Omit({ // translatedErrors is converted into errors by the backend required: 'Je moet een waarde opgeven!!!', }, - // registration tab in builder form - registration: { - attribute: '', - }, // translations tab in builder form openForms: { translations: { @@ -114,3 +110,16 @@ expectNotAssignable({ authPlugin: 'digid', confirmationRecipient: true, }); + +// registration attributes are not supported +expectNotAssignable({ + id: 'yejak', + type: 'cosign' as const, + validateOn: 'blur' as const, + key: 'someCoSign', + label: 'Some cosign', + authPlugin: 'digid', + registration: { + attribute: 'foo', + }, +});