Skip to content

Commit

Permalink
wizard: add user name validation (HMS-4903)
Browse files Browse the repository at this point in the history
this commit add validation to name field in Users step

JIRA: HMS-4903
  • Loading branch information
mgold1234 committed Jan 8, 2025
1 parent c6f76cf commit 5d2940d
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 5 deletions.
7 changes: 6 additions & 1 deletion src/Components/CreateImageWizard/CreateImageWizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
useDetailsValidation,
useRegistrationValidation,
useHostnameValidation,
useUsersValidation,
} from './utilities/useValidation';
import {
isAwsAccountIdValid,
Expand Down Expand Up @@ -225,6 +226,8 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
const firstBootValidation = useFirstBootValidation();
// Details
const detailsValidation = useDetailsValidation();
// Users
const usersValidation = useUsersValidation();

let startIndex = 1; // default index
if (isEdit) {
Expand Down Expand Up @@ -457,7 +460,9 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
key="wizard-users"
isHidden={!isUsersEnabled}
footer={
<CustomWizardFooter disableNext={false} optional={true} />
<CustomWizardFooter
disableNext={usersValidation.disabledNext}
/>
}
>
<UsersStep />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
setUserPasswordByIndex,
setUserSshKeyByIndex,
} from '../../../../../store/wizardSlice';
import { useUsersValidation } from '../../../utilities/useValidation';
import { HookValidatedInput } from '../../../ValidatedTextInput';
const UserInfo = () => {
const dispatch = useAppDispatch();
Expand Down Expand Up @@ -45,10 +46,7 @@ const UserInfo = () => {
dispatch(setUserSshKeyByIndex({ index: index, sshKey: value }));
};

const stepValidation = {
errors: {},
disabledNext: false,
};
const stepValidation = useUsersValidation();

return (
<>
Expand Down
23 changes: 23 additions & 0 deletions src/Components/CreateImageWizard/utilities/useValidation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
selectActivationKey,
selectRegistrationType,
selectHostname,
selectUserNameByIndex,
selectUsers,
} from '../../../store/wizardSlice';
import {
getDuplicateMountPoints,
Expand All @@ -27,6 +29,7 @@ import {
isMountpointMinSizeValid,
isSnapshotValid,
isHostnameValid,
isUserNameValid,
} from '../validators';

export type StepValidation = {
Expand Down Expand Up @@ -155,6 +158,26 @@ export function useHostnameValidation(): StepValidation {
return { errors: {}, disabledNext: false };
}

export function useUsersValidation(): StepValidation {
const index = 0;
const userNameSelector = selectUserNameByIndex(index);
const userName = useAppSelector(userNameSelector);
const userNameValid = isUserNameValid(userName);
const users = useAppSelector(selectUsers);
const canProceed =
// Case 1: there is no users
users.length === 0 ||
// Case 2: All fields are empty
userNameValid;

return {
errors: {
userName: !userNameValid ? 'Invalid user name' : '',
},
disabledNext: !canProceed,
};
}

export function useDetailsValidation(): StepValidation {
const name = useAppSelector(selectBlueprintName);
const description = useAppSelector(selectBlueprintDescription);
Expand Down
13 changes: 13 additions & 0 deletions src/Components/CreateImageWizard/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ export const isFileSystemConfigValid = (partitions: Partition[]) => {
return duplicates.length === 0;
};

export const isUserNameValid = (userName: string) => {
const isLengthValid =
userName !== undefined && userName.length >= 1 && userName.length <= 32;

// Check if the username follows the pattern:
// Starts and ends with a valid character (not a dot).
// Can contain alphanumeric characters, underscores, hyphens, and periods in the middle.
const isPatternValid = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*[a-zA-Z0-9_]$/.test(
userName
);
return isLengthValid && isPatternValid;
};

export const getDuplicateMountPoints = (partitions: Partition[]): string[] => {
const mountPointSet: Set<string> = new Set();
const duplicates: string[] = [];
Expand Down

0 comments on commit 5d2940d

Please sign in to comment.