diff --git a/packages/console/src/pages/ApplicationDetails/SamlApplicationDetailsContent/AttributeMapping.tsx b/packages/console/src/pages/ApplicationDetails/SamlApplicationDetailsContent/AttributeMapping.tsx index e2529664a05..4cf5b705b6d 100644 --- a/packages/console/src/pages/ApplicationDetails/SamlApplicationDetailsContent/AttributeMapping.tsx +++ b/packages/console/src/pages/ApplicationDetails/SamlApplicationDetailsContent/AttributeMapping.tsx @@ -21,6 +21,7 @@ import { trySubmitSafe } from '@/utils/form'; import styles from './AttributeMapping.module.scss'; import { camelCaseToSentenceCase } from './utils'; +import { conditionalArray } from '@silverhand/essentials'; const defaultFormValue: Array<[UserClaim | 'id' | '', string]> = [['id', '']]; @@ -102,12 +103,9 @@ function AttributeMapping({ data, mutateApplication }: Props) { }) ); - const existingKeys = useMemo(() => formValues.map(([key]) => key).filter(Boolean), [formValues]); - - const availableKeys = useMemo( - () => completeUserClaims.filter((claim) => !existingKeys.includes(claim)), - [existingKeys] - ); + // Not using `useMemo` to avoid the reappearance of the available keys when the form values change. + const existingKeys = formValues.map(([key]) => key).filter(Boolean); + const availableKeys = completeUserClaims.filter((claim) => !existingKeys.includes(claim)); return ( ({ + options={conditionalArray( + availableKeys.map((claim) => ({ title: camelCaseToSentenceCase(claim), value: claim, })), - // If this is not specified, the component will fail to render the current value. The current value has been excluded in `availableKeys`. - { value, title: camelCaseToSentenceCase(value) }, - ]} + // If this is not specified, the component will fail to render the current value. The current value has been excluded in `availableKeys`. But we should not show if the current value is empty. + value.trim() && [{ title: camelCaseToSentenceCase(value), value }] + )} onChange={(value) => { onChange(value); }} diff --git a/packages/core/src/libraries/saml-application/saml-applications.ts b/packages/core/src/libraries/saml-application/saml-applications.ts index 929aaa1f26c..731a9334430 100644 --- a/packages/core/src/libraries/saml-application/saml-applications.ts +++ b/packages/core/src/libraries/saml-application/saml-applications.ts @@ -76,7 +76,10 @@ export const createSamlApplicationsLibrary = (queries: Queries) => { patchApplicationObject: PatchSamlApplication ): Promise => { const { name, description, customData, ...config } = patchApplicationObject; - const originalApplication = await findApplicationById(id); + const [originalApplication, originalAppConfig] = await Promise.all([ + findApplicationById(id), + findSamlApplicationConfigByApplicationId(id), + ]); const applicationData = removeUndefinedKeys( pick(patchApplicationObject, 'name', 'description', 'customData') ); @@ -95,11 +98,11 @@ export const createSamlApplicationsLibrary = (queries: Queries) => { : originalApplication, Object.keys(config).length > 0 ? updateSamlApplicationConfig({ - set: config, + set: { ...originalAppConfig, ...config }, where: { applicationId: id }, - jsonbMode: 'merge', + jsonbMode: 'replace', }) - : findSamlApplicationConfigByApplicationId(id), + : originalAppConfig, ]); return ensembleSamlApplication({ diff --git a/packages/integration-tests/src/tests/api/application/saml-application.test.ts b/packages/integration-tests/src/tests/api/application/saml-application.test.ts index 14fde07f91a..7713bc2fb00 100644 --- a/packages/integration-tests/src/tests/api/application/saml-application.test.ts +++ b/packages/integration-tests/src/tests/api/application/saml-application.test.ts @@ -142,6 +142,12 @@ describe('SAML application', () => { }, }, }, + { + name: 'Update with empty attribute mapping', + config: { + attributeMapping: {}, + }, + }, ])('should update SAML application - %#', async ({ name, config }) => { const formattedName = name ? `updated-${name}` : undefined; const initConfig = {