Merge pull request #2247 from automatisch/AUT-1381
feat: introduce inline error messages in SamlConfiguration and RoleMappings forms
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import api from 'helpers/api';
|
import api from 'helpers/api';
|
||||||
import { enqueueSnackbar } from 'notistack';
|
|
||||||
|
|
||||||
export default function useAdminCreateSamlAuthProvider() {
|
export default function useAdminCreateSamlAuthProvider() {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@@ -16,20 +15,6 @@ export default function useAdminCreateSamlAuthProvider() {
|
|||||||
queryKey: ['admin', 'samlAuthProviders'],
|
queryKey: ['admin', 'samlAuthProviders'],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
|
||||||
const errors = Object.entries(
|
|
||||||
error.response.data.errors || [['', 'Failed while saving!']],
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const error of errors) {
|
|
||||||
enqueueSnackbar(`${error[0] ? error[0] + ': ' : ''} ${error[1]}`, {
|
|
||||||
variant: 'error',
|
|
||||||
SnackbarProps: {
|
|
||||||
'data-test': 'snackbar-create-saml-auth-provider-error',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import api from 'helpers/api';
|
import api from 'helpers/api';
|
||||||
import { enqueueSnackbar } from 'notistack';
|
|
||||||
|
|
||||||
export default function useAdminUpdateSamlAuthProvider(samlAuthProviderId) {
|
export default function useAdminUpdateSamlAuthProvider(samlAuthProviderId) {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@@ -19,20 +18,6 @@ export default function useAdminUpdateSamlAuthProvider(samlAuthProviderId) {
|
|||||||
queryKey: ['admin', 'samlAuthProviders'],
|
queryKey: ['admin', 'samlAuthProviders'],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
|
||||||
const errors = Object.entries(
|
|
||||||
error.response.data.errors || [['', 'Failed while saving!']],
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const error of errors) {
|
|
||||||
enqueueSnackbar(`${error[0] ? error[0] + ': ' : ''} ${error[1]}`, {
|
|
||||||
variant: 'error',
|
|
||||||
SnackbarProps: {
|
|
||||||
'data-test': 'snackbar-update-saml-auth-provider-error',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import api from 'helpers/api';
|
|||||||
|
|
||||||
export default function useSamlAuthProvider({ samlAuthProviderId } = {}) {
|
export default function useSamlAuthProvider({ samlAuthProviderId } = {}) {
|
||||||
const query = useQuery({
|
const query = useQuery({
|
||||||
queryKey: ['samlAuthProviders', samlAuthProviderId],
|
queryKey: ['admin', 'samlAuthProviders', samlAuthProviderId],
|
||||||
queryFn: async ({ signal }) => {
|
queryFn: async ({ signal }) => {
|
||||||
const { data } = await api.get(
|
const { data } = await api.get(
|
||||||
`/v1/admin/saml-auth-providers/${samlAuthProviderId}`,
|
`/v1/admin/saml-auth-providers/${samlAuthProviderId}`,
|
||||||
|
|||||||
@@ -290,12 +290,13 @@
|
|||||||
"authenticationForm.defaultRole": "Default role",
|
"authenticationForm.defaultRole": "Default role",
|
||||||
"authenticationForm.successfullySaved": "The provider has been saved.",
|
"authenticationForm.successfullySaved": "The provider has been saved.",
|
||||||
"authenticationForm.save": "Save",
|
"authenticationForm.save": "Save",
|
||||||
|
"authenticationForm.mandatoryInput": "{inputName} is required.",
|
||||||
"roleMappingsForm.title": "Role mappings",
|
"roleMappingsForm.title": "Role mappings",
|
||||||
"roleMappingsForm.remoteRoleName": "Remote role name",
|
"roleMappingsForm.remoteRoleName": "Remote role name",
|
||||||
"roleMappingsForm.role": "Role",
|
"roleMappingsForm.role": "Role",
|
||||||
"roleMappingsForm.appendRoleMapping": "Append",
|
"roleMappingsForm.appendRoleMapping": "Append",
|
||||||
"roleMappingsForm.save": "Save",
|
"roleMappingsForm.save": "Save",
|
||||||
"roleMappingsForm.notFound": "No role mappings have found.",
|
"roleMappingsForm.notFound": "No role mappings have been found.",
|
||||||
"roleMappingsForm.successfullySaved": "Role mappings have been saved.",
|
"roleMappingsForm.successfullySaved": "Role mappings have been saved.",
|
||||||
"adminApps.title": "Apps",
|
"adminApps.title": "Apps",
|
||||||
"adminApps.connections": "Connections",
|
"adminApps.connections": "Connections",
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import LoadingButton from '@mui/lab/LoadingButton';
|
|||||||
import Divider from '@mui/material/Divider';
|
import Divider from '@mui/material/Divider';
|
||||||
import Stack from '@mui/material/Stack';
|
import Stack from '@mui/material/Stack';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
|
import Alert from '@mui/material/Alert';
|
||||||
import { useMemo } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { yupResolver } from '@hookform/resolvers/yup';
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
import * as yup from 'yup';
|
import * as yup from 'yup';
|
||||||
|
|
||||||
@@ -63,11 +63,11 @@ const getValidationSchema = (formatMessage) =>
|
|||||||
|
|
||||||
function RoleMappings({ provider, providerLoading }) {
|
function RoleMappings({ provider, providerLoading }) {
|
||||||
const formatMessage = useFormatMessage();
|
const formatMessage = useFormatMessage();
|
||||||
const enqueueSnackbar = useEnqueueSnackbar();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
mutateAsync: updateRoleMappings,
|
mutateAsync: updateRoleMappings,
|
||||||
isPending: isUpdateRoleMappingsPending,
|
isPending: isUpdateRoleMappingsPending,
|
||||||
|
isSuccess: isUpdateRoleMappingsSuccess,
|
||||||
} = useAdminUpdateSamlAuthProviderRoleMappings(provider?.id);
|
} = useAdminUpdateSamlAuthProviderRoleMappings(provider?.id);
|
||||||
|
|
||||||
const { data, isLoading: isAdminSamlAuthProviderRoleMappingsLoading } =
|
const { data, isLoading: isAdminSamlAuthProviderRoleMappingsLoading } =
|
||||||
@@ -75,9 +75,12 @@ function RoleMappings({ provider, providerLoading }) {
|
|||||||
adminSamlAuthProviderId: provider?.id,
|
adminSamlAuthProviderId: provider?.id,
|
||||||
});
|
});
|
||||||
const roleMappings = data?.data;
|
const roleMappings = data?.data;
|
||||||
|
const fieldNames = ['remoteRoleName', 'roleId'];
|
||||||
|
const [fieldErrors, setFieldErrors] = useState(null);
|
||||||
|
|
||||||
const handleRoleMappingsUpdate = async (values) => {
|
const handleRoleMappingsUpdate = async (values) => {
|
||||||
try {
|
try {
|
||||||
|
setFieldErrors(null);
|
||||||
if (provider?.id) {
|
if (provider?.id) {
|
||||||
await updateRoleMappings(
|
await updateRoleMappings(
|
||||||
values.roleMappings.map(({ roleId, remoteRoleName }) => ({
|
values.roleMappings.map(({ roleId, remoteRoleName }) => ({
|
||||||
@@ -85,29 +88,20 @@ function RoleMappings({ provider, providerLoading }) {
|
|||||||
remoteRoleName,
|
remoteRoleName,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
enqueueSnackbar(formatMessage('roleMappingsForm.successfullySaved'), {
|
|
||||||
variant: 'success',
|
|
||||||
SnackbarProps: {
|
|
||||||
'data-test': 'snackbar-update-role-mappings-success',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errors = Object.values(
|
const errors = error?.response?.data?.errors;
|
||||||
error.response.data.errors || [['Failed while saving!']],
|
if (errors) {
|
||||||
);
|
Object.entries(errors).forEach(([fieldName, fieldErrors]) => {
|
||||||
|
if (fieldNames.includes(fieldName) && Array.isArray(fieldErrors)) {
|
||||||
for (const [error] of errors) {
|
setFieldErrors((prevErrors) => [
|
||||||
enqueueSnackbar(error, {
|
...(prevErrors || []),
|
||||||
variant: 'error',
|
`${fieldName}: ${fieldErrors.join(', ')}`,
|
||||||
SnackbarProps: {
|
]);
|
||||||
'data-test': 'snackbar-update-role-mappings-error',
|
}
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
throw errors || error;
|
||||||
throw new Error('Failed while saving!');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,6 +112,25 @@ function RoleMappings({ provider, providerLoading }) {
|
|||||||
[roleMappings],
|
[roleMappings],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const renderErrors = (errors) => {
|
||||||
|
const generalError = errors?.root?.general?.message;
|
||||||
|
if (fieldErrors) {
|
||||||
|
return fieldErrors.map((error, index) => (
|
||||||
|
<Alert key={index} data-test="error-alert" severity="error">
|
||||||
|
{error}
|
||||||
|
</Alert>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generalError) {
|
||||||
|
return (
|
||||||
|
<Alert data-test="error-alert" severity="error">
|
||||||
|
{generalError}
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
providerLoading ||
|
providerLoading ||
|
||||||
!provider?.id ||
|
!provider?.id ||
|
||||||
@@ -140,27 +153,35 @@ function RoleMappings({ provider, providerLoading }) {
|
|||||||
reValidateMode="onChange"
|
reValidateMode="onChange"
|
||||||
noValidate
|
noValidate
|
||||||
automaticValidation={false}
|
automaticValidation={false}
|
||||||
>
|
render={({ formState: { errors, isDirty } }) => (
|
||||||
<Stack direction="column" spacing={2}>
|
<Stack direction="column" spacing={2}>
|
||||||
<RoleMappingsFieldArray />
|
<RoleMappingsFieldArray />
|
||||||
|
{renderErrors(errors)}
|
||||||
|
{isUpdateRoleMappingsSuccess && !isDirty && (
|
||||||
|
<Alert data-test="success-alert" severity="success">
|
||||||
|
{formatMessage('roleMappingsForm.successfullySaved')}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
sx={{ boxShadow: 2 }}
|
sx={{ boxShadow: 2 }}
|
||||||
loading={isUpdateRoleMappingsPending}
|
loading={isUpdateRoleMappingsPending}
|
||||||
|
disabled={!isDirty}
|
||||||
>
|
>
|
||||||
{formatMessage('roleMappingsForm.save')}
|
{formatMessage('roleMappingsForm.save')}
|
||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Form>
|
)}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RoleMappings.propTypes = {
|
RoleMappings.propTypes = {
|
||||||
provider: PropTypes.shape({
|
provider: PropTypes.shape({
|
||||||
id: PropTypes.oneOf([PropTypes.number, PropTypes.string]).isRequired,
|
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
||||||
}),
|
}),
|
||||||
providerLoading: PropTypes.bool,
|
providerLoading: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import PropTypes from 'prop-types';
|
|||||||
import LoadingButton from '@mui/lab/LoadingButton';
|
import LoadingButton from '@mui/lab/LoadingButton';
|
||||||
import Stack from '@mui/material/Stack';
|
import Stack from '@mui/material/Stack';
|
||||||
import MuiTextField from '@mui/material/TextField';
|
import MuiTextField from '@mui/material/TextField';
|
||||||
|
import Alert from '@mui/material/Alert';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
|
import * as yup from 'yup';
|
||||||
|
|
||||||
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
|
|
||||||
import ControlledAutocomplete from 'components/ControlledAutocomplete';
|
import ControlledAutocomplete from 'components/ControlledAutocomplete';
|
||||||
import Form from 'components/Form';
|
import Form from 'components/Form';
|
||||||
import Switch from 'components/Switch';
|
import Switch from 'components/Switch';
|
||||||
@@ -28,29 +30,94 @@ const defaultValues = {
|
|||||||
defaultRoleId: '',
|
defaultRoleId: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getValidationSchema = (formatMessage) => {
|
||||||
|
const getMandatoryFieldMessage = (fieldTranslationId) =>
|
||||||
|
formatMessage('authenticationForm.mandatoryInput', {
|
||||||
|
inputName: formatMessage(fieldTranslationId),
|
||||||
|
});
|
||||||
|
|
||||||
|
return yup.object().shape({
|
||||||
|
active: yup.boolean(),
|
||||||
|
name: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(getMandatoryFieldMessage('authenticationForm.name')),
|
||||||
|
certificate: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(getMandatoryFieldMessage('authenticationForm.certificate')),
|
||||||
|
signatureAlgorithm: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(
|
||||||
|
getMandatoryFieldMessage('authenticationForm.signatureAlgorithm'),
|
||||||
|
),
|
||||||
|
issuer: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(getMandatoryFieldMessage('authenticationForm.issuer')),
|
||||||
|
entryPoint: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(getMandatoryFieldMessage('authenticationForm.entryPoint')),
|
||||||
|
firstnameAttributeName: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(
|
||||||
|
getMandatoryFieldMessage('authenticationForm.firstnameAttributeName'),
|
||||||
|
),
|
||||||
|
surnameAttributeName: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(
|
||||||
|
getMandatoryFieldMessage('authenticationForm.surnameAttributeName'),
|
||||||
|
),
|
||||||
|
emailAttributeName: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(
|
||||||
|
getMandatoryFieldMessage('authenticationForm.emailAttributeName'),
|
||||||
|
),
|
||||||
|
roleAttributeName: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(
|
||||||
|
getMandatoryFieldMessage('authenticationForm.roleAttributeName'),
|
||||||
|
),
|
||||||
|
defaultRoleId: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(getMandatoryFieldMessage('authenticationForm.defaultRole')),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function generateRoleOptions(roles) {
|
function generateRoleOptions(roles) {
|
||||||
return roles?.map(({ name: label, id: value }) => ({ label, value }));
|
return roles?.map(({ name: label, id: value }) => ({ label, value }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function SamlConfiguration({ provider, providerLoading }) {
|
function SamlConfiguration({ provider, providerLoading }) {
|
||||||
const formatMessage = useFormatMessage();
|
const formatMessage = useFormatMessage();
|
||||||
const { data, loading: isRolesLoading } = useRoles();
|
const { data, isLoading: isRolesLoading } = useRoles();
|
||||||
const roles = data?.data;
|
const roles = data?.data;
|
||||||
const enqueueSnackbar = useEnqueueSnackbar();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
mutateAsync: createSamlAuthProvider,
|
mutateAsync: createSamlAuthProvider,
|
||||||
isPending: isCreateSamlAuthProviderPending,
|
isPending: isCreateSamlAuthProviderPending,
|
||||||
|
isSuccess: isCreateSamlAuthProviderSuccess,
|
||||||
} = useAdminCreateSamlAuthProvider();
|
} = useAdminCreateSamlAuthProvider();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
mutateAsync: updateSamlAuthProvider,
|
mutateAsync: updateSamlAuthProvider,
|
||||||
isPending: isUpdateSamlAuthProviderPending,
|
isPending: isUpdateSamlAuthProviderPending,
|
||||||
|
isSuccess: isUpdateSamlAuthProviderSuccess,
|
||||||
} = useAdminUpdateSamlAuthProvider(provider?.id);
|
} = useAdminUpdateSamlAuthProvider(provider?.id);
|
||||||
|
|
||||||
const isPending =
|
const isPending =
|
||||||
isCreateSamlAuthProviderPending || isUpdateSamlAuthProviderPending;
|
isCreateSamlAuthProviderPending || isUpdateSamlAuthProviderPending;
|
||||||
|
|
||||||
|
const isSuccess =
|
||||||
|
isCreateSamlAuthProviderSuccess || isUpdateSamlAuthProviderSuccess;
|
||||||
|
|
||||||
const handleSubmit = async (providerData) => {
|
const handleSubmit = async (providerData) => {
|
||||||
try {
|
try {
|
||||||
if (provider?.id) {
|
if (provider?.id) {
|
||||||
@@ -58,15 +125,9 @@ function SamlConfiguration({ provider, providerLoading }) {
|
|||||||
} else {
|
} else {
|
||||||
await createSamlAuthProvider(providerData);
|
await createSamlAuthProvider(providerData);
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
enqueueSnackbar(formatMessage('authenticationForm.successfullySaved'), {
|
const errors = error?.response?.data?.errors;
|
||||||
variant: 'success',
|
throw errors || error;
|
||||||
SnackbarProps: {
|
|
||||||
'data-test': 'snackbar-save-saml-provider-success',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
throw new Error('Failed while saving!');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,7 +136,13 @@ function SamlConfiguration({ provider, providerLoading }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form defaultValues={provider || defaultValues} onSubmit={handleSubmit}>
|
<Form
|
||||||
|
defaultValues={provider || defaultValues}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
noValidate
|
||||||
|
resolver={yupResolver(getValidationSchema(formatMessage))}
|
||||||
|
automaticValidation={false}
|
||||||
|
render={({ formState: { errors, isDirty } }) => (
|
||||||
<Stack direction="column" gap={2}>
|
<Stack direction="column" gap={2}>
|
||||||
<Switch
|
<Switch
|
||||||
name="active"
|
name="active"
|
||||||
@@ -86,6 +153,8 @@ function SamlConfiguration({ provider, providerLoading }) {
|
|||||||
name="name"
|
name="name"
|
||||||
label={formatMessage('authenticationForm.name')}
|
label={formatMessage('authenticationForm.name')}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
error={!!errors?.name}
|
||||||
|
helperText={errors?.name?.message}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
required={true}
|
required={true}
|
||||||
@@ -93,6 +162,8 @@ function SamlConfiguration({ provider, providerLoading }) {
|
|||||||
label={formatMessage('authenticationForm.certificate')}
|
label={formatMessage('authenticationForm.certificate')}
|
||||||
fullWidth
|
fullWidth
|
||||||
multiline
|
multiline
|
||||||
|
error={!!errors?.certificate}
|
||||||
|
helperText={errors?.certificate?.message}
|
||||||
/>
|
/>
|
||||||
<ControlledAutocomplete
|
<ControlledAutocomplete
|
||||||
name="signatureAlgorithm"
|
name="signatureAlgorithm"
|
||||||
@@ -104,10 +175,14 @@ function SamlConfiguration({ provider, providerLoading }) {
|
|||||||
{ label: 'SHA256', value: 'sha256' },
|
{ label: 'SHA256', value: 'sha256' },
|
||||||
{ label: 'SHA512', value: 'sha512' },
|
{ label: 'SHA512', value: 'sha512' },
|
||||||
]}
|
]}
|
||||||
|
showHelperText={false}
|
||||||
renderInput={(params) => (
|
renderInput={(params) => (
|
||||||
<MuiTextField
|
<MuiTextField
|
||||||
{...params}
|
{...params}
|
||||||
label={formatMessage('authenticationForm.signatureAlgorithm')}
|
label={formatMessage('authenticationForm.signatureAlgorithm')}
|
||||||
|
required
|
||||||
|
error={!!errors?.signatureAlgorithm}
|
||||||
|
helperText={errors?.signatureAlgorithm?.message}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@@ -116,36 +191,48 @@ function SamlConfiguration({ provider, providerLoading }) {
|
|||||||
name="issuer"
|
name="issuer"
|
||||||
label={formatMessage('authenticationForm.issuer')}
|
label={formatMessage('authenticationForm.issuer')}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
error={!!errors?.issuer}
|
||||||
|
helperText={errors?.issuer?.message}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
required={true}
|
required={true}
|
||||||
name="entryPoint"
|
name="entryPoint"
|
||||||
label={formatMessage('authenticationForm.entryPoint')}
|
label={formatMessage('authenticationForm.entryPoint')}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
error={!!errors?.entryPoint}
|
||||||
|
helperText={errors?.entryPoint?.message}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
required={true}
|
required={true}
|
||||||
name="firstnameAttributeName"
|
name="firstnameAttributeName"
|
||||||
label={formatMessage('authenticationForm.firstnameAttributeName')}
|
label={formatMessage('authenticationForm.firstnameAttributeName')}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
error={!!errors?.firstnameAttributeName}
|
||||||
|
helperText={errors?.firstnameAttributeName?.message}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
required={true}
|
required={true}
|
||||||
name="surnameAttributeName"
|
name="surnameAttributeName"
|
||||||
label={formatMessage('authenticationForm.surnameAttributeName')}
|
label={formatMessage('authenticationForm.surnameAttributeName')}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
error={!!errors?.surnameAttributeName}
|
||||||
|
helperText={errors?.surnameAttributeName?.message}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
required={true}
|
required={true}
|
||||||
name="emailAttributeName"
|
name="emailAttributeName"
|
||||||
label={formatMessage('authenticationForm.emailAttributeName')}
|
label={formatMessage('authenticationForm.emailAttributeName')}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
error={!!errors?.emailAttributeName}
|
||||||
|
helperText={errors?.emailAttributeName?.message}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
required={true}
|
required={true}
|
||||||
name="roleAttributeName"
|
name="roleAttributeName"
|
||||||
label={formatMessage('authenticationForm.roleAttributeName')}
|
label={formatMessage('authenticationForm.roleAttributeName')}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
error={!!errors?.roleAttributeName}
|
||||||
|
helperText={errors?.roleAttributeName?.message}
|
||||||
/>
|
/>
|
||||||
<ControlledAutocomplete
|
<ControlledAutocomplete
|
||||||
name="defaultRoleId"
|
name="defaultRoleId"
|
||||||
@@ -153,25 +240,41 @@ function SamlConfiguration({ provider, providerLoading }) {
|
|||||||
disablePortal
|
disablePortal
|
||||||
disableClearable={true}
|
disableClearable={true}
|
||||||
options={generateRoleOptions(roles)}
|
options={generateRoleOptions(roles)}
|
||||||
|
showHelperText={false}
|
||||||
renderInput={(params) => (
|
renderInput={(params) => (
|
||||||
<MuiTextField
|
<MuiTextField
|
||||||
{...params}
|
{...params}
|
||||||
label={formatMessage('authenticationForm.defaultRole')}
|
label={formatMessage('authenticationForm.defaultRole')}
|
||||||
|
required
|
||||||
|
error={!!errors?.defaultRoleId}
|
||||||
|
helperText={errors?.defaultRoleId?.message}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
loading={isRolesLoading}
|
loading={isRolesLoading}
|
||||||
/>
|
/>
|
||||||
|
{errors?.root?.general && (
|
||||||
|
<Alert data-test="error-alert" severity="error">
|
||||||
|
{errors.root.general.message}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
{isSuccess && !isDirty && (
|
||||||
|
<Alert data-test="success-alert" severity="success">
|
||||||
|
{formatMessage('authenticationForm.successfullySaved')}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
sx={{ boxShadow: 2 }}
|
sx={{ boxShadow: 2 }}
|
||||||
loading={isPending}
|
loading={isPending}
|
||||||
|
disabled={!isDirty}
|
||||||
>
|
>
|
||||||
{formatMessage('authenticationForm.save')}
|
{formatMessage('authenticationForm.save')}
|
||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Form>
|
)}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user