Wizard: Add group input to User step

This adds a group input to the User step. The input is implemented as a `LabelInput`, when Administrator checkbox is checked, `wheel` group gets added and it's removal automatically unchecks the Administrator checkbox again.
This commit is contained in:
regexowl 2025-03-24 12:46:48 +01:00 committed by Lucas Garfield
parent 47b5eb8392
commit 7a225e4146
3 changed files with 67 additions and 1 deletions

View file

@ -15,10 +15,16 @@ import {
setUserSshKeyByIndex,
setUserAdministratorByIndex,
removeUser,
selectUserGroupsByIndex,
addUserGroupByIndex,
removeUserGroupByIndex,
} from '../../../../../store/wizardSlice';
import LabelInput from '../../../LabelInput';
import { PasswordValidatedInput } from '../../../utilities/PasswordValidatedInput';
import { useUsersValidation } from '../../../utilities/useValidation';
import { ValidatedInputAndTextArea } from '../../../ValidatedInput';
import { isUserGroupValid } from '../../../validators';
const UserInfo = () => {
const dispatch = useAppDispatch();
const index = 0;
@ -30,6 +36,8 @@ const UserInfo = () => {
const userSshKey = useAppSelector(userSshKeySelector);
const userIsAdministratorSelector = selectUserAdministrator(index);
const userIsAdministrator = useAppSelector(userIsAdministratorSelector);
const userGroupsSelector = selectUserGroupsByIndex(index);
const userGroups = useAppSelector(userGroupsSelector);
const handleNameChange = (
_e: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
@ -111,13 +119,30 @@ const UserInfo = () => {
<FormGroup>
<Checkbox
label="Administrator"
isChecked={userIsAdministrator}
isChecked={userIsAdministrator || userGroups.includes('wheel')}
onChange={(_e, value) => handleCheckboxChange(_e, value)}
aria-label="Administrator"
id="user Administrator"
name="user Administrator"
/>
</FormGroup>
<FormGroup label="Groups">
<LabelInput
ariaLabel="Add user group"
placeholder="Add user group"
validator={isUserGroupValid}
list={userGroups}
item="Group"
addAction={(value) =>
addUserGroupByIndex({ index: index, group: value })
}
removeAction={(value) =>
removeUserGroupByIndex({ index: index, group: value })
}
stepValidation={stepValidation}
fieldName="groups"
/>
</FormGroup>
<Tooltip position="top-start" content={'Remove user'}>
<FormGroup>
<Button

View file

@ -67,6 +67,15 @@ export const isUserNameValid = (userName: string) => {
return isLengthValid && isNotNumericOnly && isPatternValid;
};
export const isUserGroupValid = (group: string) => {
// see `man groupadd` for the exact specification
return (
group.length <= 32 &&
/^[a-zA-Z0-9_][a-zA-Z0-9_-]*(\$)?$/.test(group) &&
/[a-zA-Z]+/.test(group) // contains at least one letter
);
};
export const isSshKeyValid = (sshKey: string) => {
// 1. Key types: ssh-rsa, ssh-dss, ssh-ed25519, or ecdsa-sha2-nistp(256|384|521).
// 2. Base64-encoded key material.