Files
moonfire-nvr/ui/src/NewPassword.tsx
2023-01-11 14:54:18 -08:00

73 lines
2.4 KiB
TypeScript

// This file is part of Moonfire NVR, a security camera network video recorder.
// Copyright (C) 2023 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
// SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception
import { PasswordElement } from "react-hook-form-mui";
import { useWatch } from "react-hook-form";
// Minimum password length, taken from [NIST
// guidelines](https://pages.nist.gov/800-63-3/sp800-63b.html), section 5.1.1.
// This is enforced on the frontend for now; a user who really wants to violate
// the rule can via API request.
const MIN_PASSWORD_LENGTH = 8;
/// Form elements for setting a new password, shared between the ChangePassword
/// dialog (for any user to change their own password) and AddEditDialog
/// (for admins to add/edit any user).
///
/// Does no validation if `!required`; AddEditDialog doesn't care about these
/// fields unless the password action is "set" (rather than "leave" or "clear").
export default function NewPassword(props: { required?: boolean }) {
const required = props.required ?? true;
const newPasswordValue = useWatch({ name: "newPassword" });
return (
<>
<PasswordElement
name="newPassword"
label="New password"
variant="filled"
required={required}
autoComplete="new-password"
validation={{
validate: (v: string) => {
if (!required) {
return true;
} else if (v.length === 0) {
return "New password is required.";
} else if (v.length < MIN_PASSWORD_LENGTH) {
return `Passwords must have at least ${MIN_PASSWORD_LENGTH} characters.`;
} else {
return true;
}
},
}}
fullWidth
helperText=" "
/>
<PasswordElement
name="confirmNewPassword"
label="Confirm new password"
variant="filled"
type="password"
required={required}
autoComplete="new-password"
fullWidth
helperText=" "
validation={{
validate: (v: string) => {
if (!required) {
return true;
} else if (v.length === 0) {
return "Must confirm new password.";
} else if (v !== newPasswordValue) {
return "Passwords must match.";
} else {
return true;
}
},
}}
/>
</>
);
}