import { SaveIcon } from '@heroicons/react/outline'; import axios from 'axios'; import { Form, Formik } from 'formik'; import { useRouter } from 'next/router'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; import { Permission, useUser } from '../../../../hooks/useUser'; import globalMessages from '../../../../i18n/globalMessages'; import Error from '../../../../pages/_error'; import Alert from '../../../Common/Alert'; import Button from '../../../Common/Button'; import LoadingSpinner from '../../../Common/LoadingSpinner'; import PageTitle from '../../../Common/PageTitle'; import SensitiveInput from '../../../Common/SensitiveInput'; const messages = defineMessages({ password: 'Password', currentpassword: 'Current Password', newpassword: 'New Password', confirmpassword: 'Confirm Password', toastSettingsSuccess: 'Password saved successfully!', toastSettingsFailure: 'Something went wrong while saving the password.', toastSettingsFailureVerifyCurrent: 'Something went wrong while saving the password. Was your current password entered correctly?', validationCurrentPassword: 'You must provide your current password', validationNewPassword: 'You must provide a new password', validationNewPasswordLength: 'Password is too short; should be a minimum of 8 characters', validationConfirmPassword: 'You must confirm the new password', validationConfirmPasswordSame: 'Passwords must match', noPasswordSet: 'This user account currently does not have a password set. Configure a password below to enable this account to sign in as a "local user."', noPasswordSetOwnAccount: 'Your account currently does not have a password set. Configure a password below to enable sign-in as a "local user" using your email address.', nopermissionDescription: "You do not have permission to modify this user's password.", }); const UserPasswordChange: React.FC = () => { const intl = useIntl(); const { addToast } = useToasts(); const router = useRouter(); const { user: currentUser } = useUser(); const { user, hasPermission } = useUser({ id: Number(router.query.userId) }); const { data, error, mutate: revalidate, } = useSWR<{ hasPassword: boolean }>( user ? `/api/v1/user/${user?.id}/settings/password` : null ); const PasswordChangeSchema = Yup.object().shape({ currentPassword: Yup.lazy(() => data?.hasPassword && currentUser?.id === user?.id ? Yup.string().required( intl.formatMessage(messages.validationCurrentPassword) ) : Yup.mixed().optional() ), newPassword: Yup.string() .required(intl.formatMessage(messages.validationNewPassword)) .min(8, intl.formatMessage(messages.validationNewPasswordLength)), confirmPassword: Yup.string() .required(intl.formatMessage(messages.validationConfirmPassword)) .oneOf( [Yup.ref('newPassword'), null], intl.formatMessage(messages.validationConfirmPasswordSame) ), }); if (!data && !error) { return ; } if (!data) { return ; } if ( currentUser?.id !== user?.id && hasPermission(Permission.ADMIN) && currentUser?.id !== 1 ) { return ( <>

{intl.formatMessage(messages.password)}

); } return ( <>

{intl.formatMessage(messages.password)}

{ try { await axios.post(`/api/v1/user/${user?.id}/settings/password`, { currentPassword: values.currentPassword, newPassword: values.newPassword, confirmPassword: values.confirmPassword, }); addToast(intl.formatMessage(messages.toastSettingsSuccess), { autoDismiss: true, appearance: 'success', }); } catch (e) { addToast( intl.formatMessage( data.hasPassword && user?.id === currentUser?.id ? messages.toastSettingsFailureVerifyCurrent : messages.toastSettingsFailure ), { autoDismiss: true, appearance: 'error', } ); } finally { revalidate(); resetForm(); } }} > {({ errors, touched, isSubmitting, isValid }) => { return (
{!data.hasPassword && ( )} {data.hasPassword && user?.id === currentUser?.id && (
{errors.currentPassword && touched.currentPassword && (
{errors.currentPassword}
)}
)}
{errors.newPassword && touched.newPassword && (
{errors.newPassword}
)}
{errors.confirmPassword && touched.confirmPassword && (
{errors.confirmPassword}
)}
); }}
); }; export default UserPasswordChange;