🐛(frontend) Bug manage access role (#449)
* 🐛(frontend) update access role Currently, when you click on modify a role, the roles displayed are not the correct ones. We always took the role of the connected user. Additionally, there was a warning and a ban on changing roles if you were the last owner, but it was decided that it was the backend that was throwing the error and the action was allowed. * ✅(frontend) adapt tests We adapt the tests. Remove the check if you are the last owner and use the new props inside the relevant tests
This commit is contained in:
@@ -8,6 +8,10 @@ and this project adheres to
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛(frontend) fix update accesses form #448
|
||||
|
||||
## [1.2.1] - 2024-10-03
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -3,8 +3,11 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Role } from '../../domains';
|
||||
|
||||
const ORDERED_ROLES = [Role.VIEWER, Role.ADMIN, Role.OWNER];
|
||||
|
||||
interface ChooseRoleProps {
|
||||
availableRoles: Role[];
|
||||
roleAccess: Role;
|
||||
currentRole: Role;
|
||||
disabled: boolean;
|
||||
setRole: (role: Role) => void;
|
||||
@@ -12,55 +15,44 @@ interface ChooseRoleProps {
|
||||
|
||||
export const ChooseRole = ({
|
||||
availableRoles,
|
||||
roleAccess,
|
||||
disabled,
|
||||
currentRole,
|
||||
setRole,
|
||||
}: ChooseRoleProps) => {
|
||||
const { t } = useTranslation();
|
||||
const rolesToDisplay = Array.from(new Set([currentRole, ...availableRoles]));
|
||||
const rolesToDisplay: Role[] = Array.from(
|
||||
new Set([roleAccess, ...availableRoles]),
|
||||
);
|
||||
|
||||
const translations = {
|
||||
[Role.VIEWER]: t('Viewer'),
|
||||
[Role.ADMIN]: t('Administrator'),
|
||||
[Role.OWNER]: t('Owner'),
|
||||
};
|
||||
|
||||
return (
|
||||
<RadioGroup>
|
||||
{rolesToDisplay?.map((role) => {
|
||||
switch (role) {
|
||||
case Role.VIEWER:
|
||||
return (
|
||||
<Radio
|
||||
key={Role.VIEWER}
|
||||
label={t('Viewer')}
|
||||
value={Role.VIEWER}
|
||||
name="role"
|
||||
onChange={(evt) => setRole(evt.target.value as Role)}
|
||||
defaultChecked={currentRole === Role.VIEWER}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
case Role.ADMIN:
|
||||
return (
|
||||
<Radio
|
||||
key={Role.ADMIN}
|
||||
label={t('Administrator')}
|
||||
value={Role.ADMIN}
|
||||
name="role"
|
||||
onChange={(evt) => setRole(evt.target.value as Role)}
|
||||
defaultChecked={currentRole === Role.ADMIN}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
case Role.OWNER:
|
||||
return (
|
||||
<Radio
|
||||
key={Role.OWNER}
|
||||
label={t('Owner')}
|
||||
value={Role.OWNER}
|
||||
name="role"
|
||||
onChange={(evt) => setRole(evt.target.value as Role)}
|
||||
defaultChecked={currentRole === Role.OWNER}
|
||||
disabled={disabled || currentRole !== Role.OWNER}
|
||||
/>
|
||||
);
|
||||
}
|
||||
})}
|
||||
{ORDERED_ROLES.filter((role) => rolesToDisplay.includes(role)).map(
|
||||
(role) => {
|
||||
let disableRadio = disabled;
|
||||
if (role === Role.OWNER) {
|
||||
disableRadio = disableRadio || currentRole !== Role.OWNER;
|
||||
}
|
||||
|
||||
return (
|
||||
<Radio
|
||||
key={role}
|
||||
label={translations[role]}
|
||||
value={role}
|
||||
name="role"
|
||||
onChange={(evt) => setRole(evt.target.value as Role)}
|
||||
defaultChecked={roleAccess === role}
|
||||
disabled={disableRadio}
|
||||
/>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</RadioGroup>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,12 +7,11 @@ import {
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, Text, TextErrors } from '@/components';
|
||||
import { Box, TextErrors } from '@/components';
|
||||
import { Modal } from '@/components/Modal';
|
||||
import { useUpdateMailDomainAccess } from '@/features/mail-domains/access-management';
|
||||
|
||||
import { Role } from '../../domains';
|
||||
import { useWhoAmI } from '../hooks/useWhoAmI';
|
||||
import { Access } from '../types';
|
||||
|
||||
import { ChooseRole } from './ChooseRole';
|
||||
@@ -46,13 +45,10 @@ export const ModalRole = ({
|
||||
onClose();
|
||||
},
|
||||
});
|
||||
const { isLastOwner, isOtherOwner } = useWhoAmI(access);
|
||||
|
||||
const isNotAllowed = isOtherOwner || isLastOwner;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen
|
||||
isOpen={true}
|
||||
leftActions={
|
||||
<Button
|
||||
color="secondary"
|
||||
@@ -77,7 +73,7 @@ export const ModalRole = ({
|
||||
accessId: access.id,
|
||||
});
|
||||
}}
|
||||
disabled={isNotAllowed || isPending}
|
||||
disabled={isPending}
|
||||
>
|
||||
{t('Validate')}
|
||||
</Button>
|
||||
@@ -93,28 +89,11 @@ export const ModalRole = ({
|
||||
/>
|
||||
)}
|
||||
|
||||
{(isLastOwner || isOtherOwner) && (
|
||||
<Text
|
||||
$theme="warning"
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$gap="0.5rem"
|
||||
$margin={{ bottom: 'tiny' }}
|
||||
$justify="center"
|
||||
>
|
||||
<span className="material-icons">warning</span>
|
||||
{isLastOwner &&
|
||||
t(
|
||||
'You are the sole owner of this domain. Make another member the domain owner, before you can change your own role.',
|
||||
)}
|
||||
{isOtherOwner && t('You cannot update the role of other owner.')}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<ChooseRole
|
||||
roleAccess={access.role}
|
||||
availableRoles={access.can_set_role_to}
|
||||
currentRole={currentRole}
|
||||
disabled={isNotAllowed}
|
||||
disabled={false}
|
||||
setRole={setLocalRole}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -15,6 +15,7 @@ describe('ChooseRole', () => {
|
||||
) => {
|
||||
const defaultProps = {
|
||||
availableRoles: [Role.VIEWER, Role.ADMIN],
|
||||
roleAccess: Role.ADMIN,
|
||||
currentRole: Role.ADMIN,
|
||||
disabled: false,
|
||||
setRole: mockSetRole,
|
||||
@@ -28,13 +29,22 @@ describe('ChooseRole', () => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('renders available roles correctly', () => {
|
||||
it('renders available roles correctly when we are Administrator', () => {
|
||||
renderChooseRole();
|
||||
|
||||
expect(screen.getByLabelText('Viewer')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('Administrator')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders available roles correctly when we are owner', () => {
|
||||
renderChooseRole({
|
||||
currentRole: Role.OWNER,
|
||||
roleAccess: Role.OWNER,
|
||||
});
|
||||
expect(screen.getByLabelText('Viewer')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('Administrator')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('Owner')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('sets default role checked correctly', () => {
|
||||
renderChooseRole({ currentRole: Role.ADMIN });
|
||||
|
||||
@@ -91,6 +101,7 @@ describe('ChooseRole', () => {
|
||||
it('renders and checks owner role correctly when currentRole is owner', () => {
|
||||
renderChooseRole({
|
||||
currentRole: Role.OWNER,
|
||||
roleAccess: Role.OWNER,
|
||||
availableRoles: [Role.OWNER, Role.VIEWER, Role.ADMIN],
|
||||
});
|
||||
|
||||
|
||||
@@ -115,26 +115,6 @@ describe('ModalRole', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('disables the Validate button if the user is the last owner', () => {
|
||||
renderModalRole(true, false); // isLastOwner = true, isOtherOwner = false
|
||||
|
||||
const validateButton = screen.getByRole('button', { name: /Validate/i });
|
||||
expect(validateButton).toBeDisabled();
|
||||
expect(
|
||||
screen.getByText(/You are the sole owner of this domain/i),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('disables the Validate button if the user is another owner', () => {
|
||||
renderModalRole(false, true); // isLastOwner = false, isOtherOwner = true
|
||||
|
||||
const validateButton = screen.getByRole('button', { name: /Validate/i });
|
||||
expect(validateButton).toBeDisabled();
|
||||
expect(
|
||||
screen.getByText(/You cannot update the role of other owner/i),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows error message when update fails', async () => {
|
||||
fetchMock.patch(`end:mail-domains/domain-slug/accesses/1-1-1-1-1-1/`, {
|
||||
status: 400,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { UUID } from 'crypto';
|
||||
|
||||
export interface MailDomain {
|
||||
id: UUID;
|
||||
name: string;
|
||||
|
||||
Reference in New Issue
Block a user