Skip to content

Commit

Permalink
✨ [#4398] Display errors for authAttributePath in modal
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenbal committed Nov 25, 2024
1 parent 849e3c0 commit a16bf9a
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,66 @@ export const WithValidationErrors = {
},
};

export const ConfigurePrefillObjectsAPIWithValidationErrors = {
args: {
variables: [
{
form: 'http://localhost:8000/api/v2/forms/36612390',
formDefinition: undefined,
name: 'User defined',
key: 'userDefined',
source: 'user_defined',
prefillPlugin: 'objects_api',
prefillAttribute: '',
prefillIdentifierRole: '',
dataType: 'string',
dataFormat: undefined,
isSensitiveData: false,
serviceFetchConfiguration: undefined,
initialValue: [],
options: {
objectsApiGroup: 1,
objecttype: '2c77babf-a967-4057-9969-0200320d23f1',
objecttypeVersion: 2,
authAttributePath: ['path', 'to', 'bsn'],
variablesMapping: [
{
variableKey: 'formioComponent',
targetPath: ['height'],
},
{
variableKey: 'userDefined',
targetPath: ['species'],
},
],
},
errors: {
prefillOptions: {authAttributePath: 'This list may not be empty.'},
},
},
],
},
play: async ({canvasElement, step}) => {
const canvas = within(canvasElement);

await step('Open configuration modal', async () => {
const userDefinedVarsTab = await canvas.findByRole('tab', {name: 'Gebruikersvariabelen'});
expect(userDefinedVarsTab).toBeVisible();
await userEvent.click(userDefinedVarsTab);

// open modal for configuration
const editIcon = canvas.getByTitle('Prefill instellen');
await userEvent.click(editIcon);
expect(await canvas.findByRole('dialog')).toBeVisible();
});

await step('Verify that error is shown', async () => {
const error = canvas.getByText('This list may not be empty.');
expect(error).toBeVisible();
});
},
};

export const AddressNLMappingSpecificTargetsNoDeriveAddress = {
args: {
variables: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ import ErrorBoundary from 'components/errors/ErrorBoundary';
import {IDENTIFIER_ROLE_CHOICES} from '../constants';
import PrefillConfigurationForm from './PrefillConfigurationForm';

function isTruthy(value) {
if (value === undefined || value === null) {
return false;
}

// Check if the value is an object
if (typeof value === 'object') {
// Check if it's an empty object
if (Object.keys(value).length === 0) {
return false;
}
return true;
}
}
const PrefillSummary = ({
plugin = '',
attribute = '',
Expand All @@ -29,7 +43,11 @@ const PrefillSummary = ({
intl
);

const hasErrors = hasPluginErrors || hasAttributeErrors || hasIdentifierRoleErrors;
const hasErrors =
hasPluginErrors ||
hasAttributeErrors ||
hasIdentifierRoleErrors ||
isTruthy(errors.prefillOptions);

const icons = (
<div style={{display: 'flex', gap: '6px', alignItems: 'center'}}>
Expand Down Expand Up @@ -100,6 +118,9 @@ const PrefillSummary = ({
plugin: pluginErrors,
attribute: attributeErrors,
identifierRole: identifierRoleErrors,
// Directly pass these without normalizing, because the shape
// depends on the plugin that is used
options: errors.prefillOptions,
}}
/>
</ErrorBoundary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import useAsync from 'react-use/esm/useAsync';

import {FormContext} from 'components/admin/form_design/Context';
import useConfirm from 'components/admin/form_design/useConfirm';
import {normalizeErrors} from 'components/admin/forms/Field';
import Fieldset from 'components/admin/forms/Fieldset';
import FormRow from 'components/admin/forms/FormRow';
import {LOADING_OPTION} from 'components/admin/forms/Select';
Expand Down Expand Up @@ -127,6 +128,8 @@ const ObjectsAPIFields = ({errors, showCopyButton, setShowCopyButton}) => {
if (error) throw error;
const prefillProperties = loading ? LOADING_OPTION : value;

const [, authAttributePathErrors] = normalizeErrors(errors.options?.authAttributePath, intl);

return (
<>
{showCopyButton ? (
Expand Down Expand Up @@ -204,7 +207,11 @@ const ObjectsAPIFields = ({errors, showCopyButton, setShowCopyButton}) => {
objectTypeFieldName="options.objecttypeUuid"
/>
</ErrorBoundary>
<AuthAttributePath name={'options.authAttributePath'} style={{maxWidth: '50%'}} />
<AuthAttributePath
name={'options.authAttributePath'}
style={{maxWidth: '10em'}}
errors={authAttributePathErrors}
/>
</Fieldset>

<Fieldset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import ArrayInput from 'components/admin/forms/ArrayInput';
import Field from 'components/admin/forms/Field';
import FormRow from 'components/admin/forms/FormRow';

const AuthAttributePath = ({name, required = true, ...extraProps}) => {
const AuthAttributePath = ({name, errors, required = true, ...extraProps}) => {
const [fieldProps, , fieldHelpers] = useField({name: name, type: 'array'});
const {setValue} = fieldHelpers;

return (
<FormRow>
<Field
name={name}
errors={errors}
label={
<FormattedMessage
description="Objects API registration: authAttributePath label"
Expand Down
9 changes: 9 additions & 0 deletions src/openforms/prefill/contrib/objects_api/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ class ObjectsAPIOptionsSerializer(JsonSchemaSerializerMixin, serializers.Seriali
required=False,
help_text=_("Version of the objecttype in the Objecttypes API."),
)
auth_attribute_path = serializers.ListField(
child=serializers.CharField(label=_("Segment of a JSON path")),
label=_("Path to auth attribute (e.g. BSN/KVK) in objects"),
help_text=_(
"This is used to perform validation to verify that the authenticated user is the owner of the object."
),
allow_empty=False,
required=True,
)
variables_mapping = ObjecttypeVariableMappingSerializer(
label=_("variables mapping"),
many=True,
Expand Down

0 comments on commit a16bf9a

Please sign in to comment.