wizrad: add validation to ssh key field (HMS-5349)
this commit add validation to ssh key field JIRA: HMS-5349
This commit is contained in:
parent
0f86336af6
commit
7d34d30b08
3 changed files with 115 additions and 113 deletions
|
|
@ -34,6 +34,7 @@ import {
|
|||
isHostnameValid,
|
||||
isKernelNameValid,
|
||||
isUserNameValid,
|
||||
isSshKeyValid,
|
||||
} from '../validators';
|
||||
|
||||
export type StepValidation = {
|
||||
|
|
@ -192,12 +193,20 @@ export function useUsersValidation(): StepValidation {
|
|||
users.length === 0 ||
|
||||
// Case 2: All fields are empty
|
||||
(userName === '' && userPassword === '' && userSshKey === '') ||
|
||||
// Case 3: userName is valid
|
||||
(userName && isUserNameValid(userName));
|
||||
// Case 3: userName is valid and SshKey is valid
|
||||
(userName &&
|
||||
isUserNameValid(userName) &&
|
||||
userSshKey &&
|
||||
isSshKeyValid(userSshKey));
|
||||
|
||||
return {
|
||||
errors: {
|
||||
userName: !isUserNameValid(userName) ? 'Invalid user name' : '',
|
||||
userSshKey: !userSshKey
|
||||
? ''
|
||||
: !isSshKeyValid(userSshKey)
|
||||
? 'Invalid SSH key'
|
||||
: '',
|
||||
},
|
||||
disabledNext: !canProceed,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -68,6 +68,17 @@ export const isUserNameValid = (userName: string) => {
|
|||
return isLengthValid && isNotNumericOnly && isPatternValid;
|
||||
};
|
||||
|
||||
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.
|
||||
// 3. Optional comment at the end.
|
||||
const isPatternValid =
|
||||
/^(ssh-(rsa|dss|ed25519)|ecdsa-sha2-nistp(256|384|521))\s+[A-Za-z0-9+/=]+(\s+\S+)?$/.test(
|
||||
sshKey
|
||||
);
|
||||
return isPatternValid;
|
||||
};
|
||||
|
||||
export const getDuplicateMountPoints = (partitions: Partition[]): string[] => {
|
||||
const mountPointSet: Set<string> = new Set();
|
||||
const duplicates: string[] = [];
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ import {
|
|||
} from '../../wizardTestUtils';
|
||||
|
||||
let router: RemixRouter | undefined = undefined;
|
||||
const validUserName = 'best';
|
||||
const validSshKey = 'ssh-rsa d';
|
||||
|
||||
const goToUsersStep = async () => {
|
||||
await clickNext();
|
||||
|
|
@ -54,41 +56,27 @@ const clickRevisitButton = async () => {
|
|||
await waitFor(() => user.click(revisitButton));
|
||||
};
|
||||
|
||||
const addValidUser = async () => {
|
||||
const clickAddUser = async () => {
|
||||
const user = userEvent.setup();
|
||||
const addUser = await screen.findByRole('button', { name: /add a user/i });
|
||||
expect(addUser).toBeEnabled();
|
||||
await waitFor(() => user.click(addUser));
|
||||
const enterUserName = screen.getByRole('textbox', {
|
||||
name: /blueprint user name/i,
|
||||
});
|
||||
const nextButton = await getNextButton();
|
||||
await waitFor(() => user.type(enterUserName, 'best'));
|
||||
await waitFor(() => expect(enterUserName).toHaveValue('best'));
|
||||
const enterSshKey = await screen.findByRole('textbox', {
|
||||
name: /public SSH key/i,
|
||||
});
|
||||
await waitFor(() => user.type(enterSshKey, 'ssh-rsa d'));
|
||||
await waitFor(() => expect(enterSshKey).toHaveValue('ssh-rsa d'));
|
||||
await waitFor(() => expect(nextButton).toBeEnabled());
|
||||
};
|
||||
|
||||
const addInvalidUser = async () => {
|
||||
const addSshKey = async (sshKey: string) => {
|
||||
const user = userEvent.setup();
|
||||
const addUser = await screen.findByRole('button', { name: /add a user/i });
|
||||
expect(addUser).toBeEnabled();
|
||||
await waitFor(() => user.click(addUser));
|
||||
const enterUserName = screen.getByRole('textbox', {
|
||||
name: /blueprint user name/i,
|
||||
});
|
||||
const nextButton = await getNextButton();
|
||||
await waitFor(() => user.type(enterUserName, '..'));
|
||||
await waitFor(() => expect(enterUserName).toHaveValue('..'));
|
||||
const enterSshKey = await screen.findByRole('textbox', {
|
||||
name: /public SSH key/i,
|
||||
});
|
||||
await waitFor(() => user.type(enterSshKey, 'ssh-rsa d'));
|
||||
await waitFor(() => expect(nextButton).toBeDisabled());
|
||||
await waitFor(() => user.type(enterSshKey, sshKey));
|
||||
await waitFor(() => expect(enterSshKey).toHaveValue(sshKey));
|
||||
};
|
||||
const addUserName = async (userName: string) => {
|
||||
const user = userEvent.setup();
|
||||
const enterUserName = screen.getByRole('textbox', {
|
||||
name: /blueprint user name/i,
|
||||
});
|
||||
await waitFor(() => user.type(enterUserName, userName));
|
||||
await waitFor(() => expect(enterUserName).toHaveValue(userName));
|
||||
};
|
||||
|
||||
describe('Step Users', () => {
|
||||
|
|
@ -129,100 +117,94 @@ describe('Step Users', () => {
|
|||
await goToRegistrationStep();
|
||||
await clickRegisterLater();
|
||||
await goToUsersStep();
|
||||
await addValidUser();
|
||||
await clickAddUser();
|
||||
await addUserName(validUserName);
|
||||
await addSshKey(validSshKey);
|
||||
const nextButton = await getNextButton();
|
||||
await waitFor(() => expect(nextButton).toBeEnabled());
|
||||
await goToReviewStep();
|
||||
await clickRevisitButton();
|
||||
await screen.findByRole('heading', { name: /Users/ });
|
||||
});
|
||||
|
||||
describe('User request generated correctly', () => {
|
||||
test('with valid name and password', async () => {
|
||||
await renderCreateMode();
|
||||
await goToRegistrationStep();
|
||||
await clickRegisterLater();
|
||||
await goToUsersStep();
|
||||
await addValidUser();
|
||||
await goToReviewStep();
|
||||
// informational modal pops up in the first test only as it's tied
|
||||
// to a 'imageBuilder.saveAndBuildModalSeen' variable in localStorage
|
||||
await openAndDismissSaveAndBuildModal();
|
||||
const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT);
|
||||
|
||||
const expectedRequest = {
|
||||
...blueprintRequest,
|
||||
customizations: {
|
||||
users: [
|
||||
{
|
||||
name: 'best',
|
||||
ssh_key: 'ssh-rsa d',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
await waitFor(() => {
|
||||
expect(receivedRequest).toEqual(expectedRequest);
|
||||
});
|
||||
});
|
||||
|
||||
test('with valid name, ssh key and checked Administrator checkbox', async () => {
|
||||
const user = userEvent.setup();
|
||||
await renderCreateMode();
|
||||
await goToRegistrationStep();
|
||||
await clickRegisterLater();
|
||||
await goToUsersStep();
|
||||
await addValidUser();
|
||||
const isAdmin = screen.getByRole('checkbox', {
|
||||
name: /administrator/i,
|
||||
});
|
||||
user.click(isAdmin);
|
||||
await goToReviewStep();
|
||||
const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT);
|
||||
|
||||
const expectedRequest = {
|
||||
...blueprintRequest,
|
||||
customizations: {
|
||||
users: [
|
||||
{
|
||||
name: 'best',
|
||||
ssh_key: 'ssh-rsa d',
|
||||
groups: ['wheel'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
await waitFor(() => {
|
||||
expect(receivedRequest).toEqual(expectedRequest);
|
||||
});
|
||||
});
|
||||
|
||||
test('with invalid name', async () => {
|
||||
await renderCreateMode();
|
||||
await goToRegistrationStep();
|
||||
await clickRegisterLater();
|
||||
await goToUsersStep();
|
||||
await addInvalidUser();
|
||||
const invalidUserMessage = screen.getByText(/invalid user name/i);
|
||||
await waitFor(() => expect(invalidUserMessage));
|
||||
});
|
||||
test('with invalid name', async () => {
|
||||
await renderCreateMode();
|
||||
await goToRegistrationStep();
|
||||
await clickRegisterLater();
|
||||
await goToUsersStep();
|
||||
await clickAddUser();
|
||||
await addUserName('ss.');
|
||||
await addSshKey('ssh');
|
||||
const invalidUserMessage = screen.getByText(/invalid user name/i);
|
||||
await waitFor(() => expect(invalidUserMessage));
|
||||
});
|
||||
|
||||
describe('Users edit mode', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
test('with invalid ssh key', async () => {
|
||||
await renderCreateMode();
|
||||
await goToRegistrationStep();
|
||||
await clickRegisterLater();
|
||||
await goToUsersStep();
|
||||
await clickAddUser();
|
||||
await addSshKey('ssh');
|
||||
await addUserName('bestUser');
|
||||
const invalidUserMessage = screen.getByText(/invalid ssh key/i);
|
||||
await waitFor(() => expect(invalidUserMessage));
|
||||
});
|
||||
});
|
||||
|
||||
describe('User request generated correctly', () => {
|
||||
test('with valid name, ssh key and checked Administrator checkbox', async () => {
|
||||
const user = userEvent.setup();
|
||||
await renderCreateMode();
|
||||
await goToRegistrationStep();
|
||||
await clickRegisterLater();
|
||||
await goToUsersStep();
|
||||
await clickAddUser();
|
||||
await addUserName(validUserName);
|
||||
await addSshKey(validSshKey);
|
||||
const nextButton = await getNextButton();
|
||||
await waitFor(() => expect(nextButton).toBeEnabled());
|
||||
const isAdmin = screen.getByRole('checkbox', {
|
||||
name: /administrator/i,
|
||||
});
|
||||
|
||||
test('edit mode works', async () => {
|
||||
const id = mockBlueprintIds['users'];
|
||||
await renderEditMode(id);
|
||||
|
||||
// starts on review step
|
||||
const receivedRequest = await interceptEditBlueprintRequest(
|
||||
`${EDIT_BLUEPRINT}/${id}`
|
||||
);
|
||||
const expectedRequest = usersCreateBlueprintRequest;
|
||||
user.click(isAdmin);
|
||||
await goToReviewStep();
|
||||
// informational modal pops up in the first test only as it's tied
|
||||
// to a 'imageBuilder.saveAndBuildModalSeen' variable in localStorage
|
||||
await openAndDismissSaveAndBuildModal();
|
||||
const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT);
|
||||
const expectedRequest = {
|
||||
...blueprintRequest,
|
||||
customizations: {
|
||||
users: [
|
||||
{
|
||||
name: 'best',
|
||||
ssh_key: 'ssh-rsa d',
|
||||
groups: ['wheel'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
await waitFor(() => {
|
||||
expect(receivedRequest).toEqual(expectedRequest);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Users edit mode', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('edit mode works', async () => {
|
||||
const id = mockBlueprintIds['users'];
|
||||
await renderEditMode(id);
|
||||
|
||||
// starts on review step
|
||||
const receivedRequest = await interceptEditBlueprintRequest(
|
||||
`${EDIT_BLUEPRINT}/${id}`
|
||||
);
|
||||
const expectedRequest = usersCreateBlueprintRequest;
|
||||
expect(receivedRequest).toEqual(expectedRequest);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue