1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-30 19:52:20 +01:00

(bug) unable to remove an SSO data mapping field once saved

This commit is contained in:
Sylvain 2022-06-22 16:42:14 +02:00
parent 2d80600e97
commit c1246092ed
5 changed files with 52 additions and 15 deletions

View File

@ -24,6 +24,7 @@
- Fix a bug: unable to generate the secret key base during the setup
- Fix a bug: error message during the setup: the input device is not a TTY
- Fix a bug: when Fab-manager was installed as non-root user, unable to compile the assets during the upgrade
- Fix a bug: unable to remove an SSO data mapping field once saved
- [TODO DEPLOY] `\curl -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/scripts/set-docker-user.sh | bash`
## v5.4.4 2022 June 8

View File

@ -1,9 +1,9 @@
import React, { useEffect, useState } from 'react';
import { UseFormRegister, useFieldArray, ArrayPath, useWatch, Path } from 'react-hook-form';
import { UseFormRegister, useFieldArray, ArrayPath, useWatch, Path, FieldPathValue } from 'react-hook-form';
import { FieldValues } from 'react-hook-form/dist/types/fields';
import AuthProviderAPI from '../../api/auth-provider';
import { AuthenticationProviderMapping, MappingFields, mappingType, ProvidableType } from '../../models/authentication-provider';
import { Control, UseFormSetValue } from 'react-hook-form/dist/types/form';
import { Control, UnpackNestedValue, UseFormSetValue } from 'react-hook-form/dist/types/form';
import { FormSelect } from '../form/form-select';
import { FormInput } from '../form/form-input';
import { useTranslation } from 'react-i18next';
@ -96,6 +96,31 @@ export const DataMappingForm = <TFieldValues extends FieldValues, TContext exten
};
};
/**
* Remove the data whom index is provided: mark it as "to destroy" or simply remove it if it was unsaved
*/
const removeMapping = (index: number): void => {
if (currentFormValues[index].id) {
setValue(
`auth_provider_mappings_attributes.${index}._destroy` as Path<TFieldValues>,
true as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>
);
} else {
remove(index);
}
};
/**
* Return a className based on the current mapping-item status
*/
const itemStatus = (index: number): string => {
if (currentFormValues[index]?.id) {
if (currentFormValues[index]._destroy) return 'destroyed-item';
return 'saved-item';
}
return 'new-item';
};
// fetch the mapping data from the API on mount
useEffect(() => {
AuthProviderAPI.mappingFields().then((data) => {
@ -114,7 +139,7 @@ export const DataMappingForm = <TFieldValues extends FieldValues, TContext exten
</FabButton>
</div>
{fields.map((item, index) => (
<div key={item.id} className="mapping-item">
<div key={item.id} className={`mapping-item ${itemStatus(index)}`}>
<div className="inputs">
<FormInput id={`auth_provider_mappings_attributes.${index}.id`} register={register} type="hidden" />
<div className="local-data">
@ -141,7 +166,7 @@ export const DataMappingForm = <TFieldValues extends FieldValues, TContext exten
onClick={toggleTypeMappingModal(index)}
disabled={getField(output, index) === undefined}
tooltip={t('app.admin.authentication.data_mapping_form.data_mapping')} />
<FabButton icon={<i className="fa fa-trash" />} onClick={() => remove(index)} className="delete-button" />
<FabButton icon={<i className="fa fa-trash" />} onClick={() => removeMapping(index)} className="delete-button" />
<TypeMappingModal model={getModel(output, index)}
field={getField(output, index)}
type={getDataType(output, index)}

View File

@ -44,17 +44,19 @@ export const OpenidConnectDataMappingForm = <TFieldValues extends FieldValues>({
const model = currentFormValues[index]?.local_model;
const field = currentFormValues[index]?.local_field;
const configuration = standardConfiguration[`${model}.${field}`];
setValue(
`auth_provider_mappings_attributes.${index}.api_field` as Path<TFieldValues>,
configuration.api_field as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>
);
if (configuration.transformation) {
Object.keys(configuration.transformation).forEach((key) => {
setValue(
`auth_provider_mappings_attributes.${index}.transformation.${key}` as Path<TFieldValues>,
configuration.transformation[key] as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>
);
});
if (configuration) {
setValue(
`auth_provider_mappings_attributes.${index}.api_field` as Path<TFieldValues>,
configuration.api_field as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>
);
if (configuration.transformation) {
Object.keys(configuration.transformation).forEach((key) => {
setValue(
`auth_provider_mappings_attributes.${index}.transformation.${key}` as Path<TFieldValues>,
configuration.transformation[key] as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>
);
});
}
}
};

View File

@ -14,6 +14,7 @@ export type mappingType = 'string' | 'text' | 'date' | 'integer' | 'boolean';
export interface AuthenticationProviderMapping {
id?: number,
_destroy?: boolean,
local_model: 'user' | 'profile',
local_field: string,
api_field: string,

View File

@ -24,5 +24,13 @@
color: white;
}
}
&.destroyed-item {
display: none;
}
&.new-item {
background-color: var(--information-lightest);
}
}
}