31 lines
1.2 KiB
TypeScript
31 lines
1.2 KiB
TypeScript
// Pure validation for the box user's password, shared by the Node action and
|
|
// unit tests. Kept free of Convex imports so it tests without the harness.
|
|
|
|
export type BoxPasswordValidation =
|
|
| { ok: true; value: string | null }
|
|
| { ok: false; error: string };
|
|
|
|
// null/'' is an explicit clear (sudo reverts to NOPASSWD). The applied value
|
|
// travels to `chpasswd` as a `user:password` stdin line, so control characters
|
|
// (including newline/tab) are rejected; colons are fine — chpasswd splits on
|
|
// the first colon only.
|
|
export const normalizeBoxPassword = (
|
|
password: string | null | undefined,
|
|
): BoxPasswordValidation => {
|
|
if (password == null || password === '') return { ok: true, value: null };
|
|
if (password.length < 8) {
|
|
return { ok: false, error: 'Password must be at least 8 characters.' };
|
|
}
|
|
if (password.length > 128) {
|
|
return { ok: false, error: 'Password must be at most 128 characters.' };
|
|
}
|
|
// eslint-disable-next-line no-control-regex -- rejecting control chars is the point
|
|
if (/[\u0000-\u001f\u007f]/.test(password)) {
|
|
return {
|
|
ok: false,
|
|
error: 'Password must not contain control characters.',
|
|
};
|
|
}
|
|
return { ok: true, value: password };
|
|
};
|