return Promise.reject('No such user');
}
Object.assign(user, {
- ...omitBy({ name, email, scmAccount }, isUndefined),
+ ...omitBy({ name, email, scmAccounts: scmAccount }, isUndefined),
});
return this.reply({ user });
};
return postJSONBody('/api/v2/users', data);
}
-export function updateUser(data: {
- email?: string;
- login: string;
- name?: string;
- scmAccount: string[];
-}): Promise<{ user: User }> {
+type UpdateUserArg =
+ | {
+ email?: string;
+ login: string;
+ name?: string;
+ scmAccount: string[];
+ }
+ | { login: string; scmAccount: string[] };
+
+export function updateUser(data: UpdateUserArg): Promise<{ user: User }> {
return postJSON('/api/users/update', {
...data,
scmAccount: data.scmAccount.length > 0 ? data.scmAccount : '',
/>
</Alert>
)}
- {openUserForm && <UserForm onClose={() => setOpenUserForm(false)} />}
+ {openUserForm && (
+ <UserForm onClose={() => setOpenUserForm(false)} isInstanceManaged={false} />
+ )}
</div>
);
}
expect(ui.bobUpdateGroupButton.query()).not.toBeInTheDocument();
});
- it('should not be able to update / change password / deactivate a managed user', async () => {
+ it('should not be able to update scm account', async () => {
+ const user = userEvent.setup();
+
renderUsersApp();
await act(async () => expect(await ui.bobRow.find()).toBeInTheDocument());
- expect(ui.bobUpdateButton.query()).not.toBeInTheDocument();
+ expect(ui.bobUpdateButton.get()).toBeInTheDocument();
+
+ await user.click(ui.bobUpdateButton.get());
+
+ expect(
+ ui.bobRow.byRole('button', { name: 'users.deactivate' }).query()
+ ).not.toBeInTheDocument();
+ expect(
+ ui.bobRow.byRole('button', { name: 'my_profile.password.title' }).query()
+ ).not.toBeInTheDocument();
+
+ await user.click(await ui.bobRow.byRole('button', { name: 'update_scm' }).get());
+
+ expect(ui.userNameInput.get()).toBeDisabled();
+ expect(ui.emailInput.get()).toBeDisabled();
+
+ await user.click(ui.scmAddButton.get());
+ await user.type(ui.dialogSCMInput().get(), 'SCM');
+ await act(() => user.click(ui.updateButton.get()));
+
+ expect(await ui.bobRow.byText(/SCM/).find()).toBeInTheDocument();
});
- it('should ONLY be able to deactivate a local user', async () => {
+ it('should be able to deactivate a local user', async () => {
const user = userEvent.setup();
renderUsersApp();
const [openForm, setOpenForm] = React.useState<string | undefined>(undefined);
- const isInstanceManaged = () => {
- return manageProvider !== undefined;
- };
+ const isInstanceManaged = manageProvider !== undefined;
- const isUserLocal = () => {
- return isInstanceManaged() && !user.managed;
- };
-
- const isUserManaged = () => {
- return isInstanceManaged() && user.managed;
- };
-
- if (isUserManaged()) {
- return null;
- }
+ const isUserLocal = isInstanceManaged && !user.managed;
return (
<>
<ActionsDropdown label={translateWithParameters('users.manage_user', user.login)}>
- {!isInstanceManaged() && (
- <>
- <ActionsDropdownItem className="js-user-update" onClick={() => setOpenForm('update')}>
- {translate('update_details')}
- </ActionsDropdownItem>
- {user.local && (
- <ActionsDropdownItem
- className="js-user-change-password"
- onClick={() => setOpenForm('password')}
- >
- {translate('my_profile.password.title')}
- </ActionsDropdownItem>
- )}
- </>
+ <ActionsDropdownItem className="js-user-update" onClick={() => setOpenForm('update')}>
+ {isInstanceManaged ? translate('update_scm') : translate('update_details')}
+ </ActionsDropdownItem>
+ {!isInstanceManaged && user.local && (
+ <ActionsDropdownItem
+ className="js-user-change-password"
+ onClick={() => setOpenForm('password')}
+ >
+ {translate('my_profile.password.title')}
+ </ActionsDropdownItem>
)}
- {isUserActive(user) && !isInstanceManaged() && <ActionsDropdownDivider />}
- {isUserActive(user) && (!isInstanceManaged() || isUserLocal()) && (
+ {isUserActive(user) && !isInstanceManaged && <ActionsDropdownDivider />}
+ {isUserActive(user) && (!isInstanceManaged || isUserLocal) && (
<ActionsDropdownItem
className="js-user-deactivate"
destructive
{openForm === 'password' && (
<PasswordForm onClose={() => setOpenForm(undefined)} user={user} />
)}
- {openForm === 'update' && <UserForm onClose={() => setOpenForm(undefined)} user={user} />}
+ {openForm === 'update' && (
+ <UserForm
+ onClose={() => setOpenForm(undefined)}
+ user={user}
+ isInstanceManaged={isInstanceManaged}
+ />
+ )}
</>
);
}
export interface Props {
onClose: () => void;
user?: RestUserDetailed;
+ isInstanceManaged: boolean;
}
const BAD_REQUEST = 400;
const INTERNAL_SERVER_ERROR = 500;
export default function UserForm(props: Props) {
- const { user } = props;
+ const { user, isInstanceManaged } = props;
const { mutate: createUser } = usePostUserMutation();
const { mutate: updateUser } = useUpdateUserMutation();
const { user } = props;
updateUser(
- {
- email: user?.local ? email : undefined,
- login,
- name: user?.local ? name : undefined,
- scmAccount: scmAccounts,
- },
+ isInstanceManaged
+ ? { scmAccount: scmAccounts, login }
+ : {
+ email: user?.local ? email : undefined,
+ login,
+ name: user?.local ? name : undefined,
+ scmAccount: scmAccounts,
+ },
{ onSuccess: props.onClose, onError: handleError }
);
};
minLength={3}
name="login"
onChange={(e) => setLogin(e.currentTarget.value)}
- required
+ required={!isInstanceManaged}
type="text"
value={login}
/>
<div className="modal-field">
<label htmlFor="create-user-name">
{translate('name')}
- <MandatoryFieldMarker />
+ {!isInstanceManaged && <MandatoryFieldMarker />}
</label>
<input
autoComplete="off"
autoFocus={!!user}
- disabled={user && !user.local}
+ disabled={(user && !user.local) || isInstanceManaged}
id="create-user-name"
maxLength={200}
name="name"
onChange={(e) => setName(e.currentTarget.value)}
- required
+ required={!isInstanceManaged}
type="text"
value={name}
/>
<label htmlFor="create-user-email">{translate('users.email')}</label>
<input
autoComplete="off"
- disabled={user && !user.local}
+ disabled={(user && !user.local) || isInstanceManaged}
id="create-user-email"
maxLength={100}
name="email"
const {
name,
login,
- managed,
groupsCount,
tokensCount,
avatar,
</ButtonIcon>
</td>
- {(manageProvider === undefined || !managed) && (
- <td className="thin nowrap text-right text-middle">
- <UserActions user={user} manageProvider={manageProvider} />
- </td>
- )}
+ <td className="thin nowrap text-right text-middle">
+ <UserActions user={user} manageProvider={manageProvider} />
+ </td>
{openTokenForm && <TokensFormModal onClose={() => setOpenTokenForm(false)} user={user} />}
{openGroupForm && <GroupsForm onClose={() => setOpenGroupForm(false)} user={user} />}
this_name_is_already_taken=This name is already taken.
tooltip_is_interactive=This is a tooltip with interactive elements. Use the TAB key to cycle through the interactive elements.
update_details=Update details
+update_scm=Update SCM details
work_duration.x_days={0}d
work_duration.x_hours={0}h
work_duration.x_minutes={0}min