import { useEffect, useState } from 'react' import { Alert, Button, ControlLabel, FormControl, FormGroup, } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' import { getUserFacingMessage, getErrorMessageKey, postJSON, } from '../../../infrastructure/fetch-json' import getMeta from '../../../utils/meta' import { ExposedSettings } from '../../../../../types/exposed-settings' import { PasswordStrengthOptions } from '../../../../../types/password-strength-options' import useAsync from '../../../shared/hooks/use-async' type PasswordUpdateResult = { message?: { text: string } } function PasswordSection() { const { t } = useTranslation() return ( <>

{t('change_password')}

) } function PasswordInnerSection() { const { t } = useTranslation() const { isOverleaf } = getMeta('ol-ExposedSettings') as ExposedSettings const isExternalAuthenticationSystemUsed = getMeta( 'ol-isExternalAuthenticationSystemUsed' ) as boolean const hasPassword = getMeta('ol-hasPassword') as boolean if (isExternalAuthenticationSystemUsed && !isOverleaf) { return

{t('password_managed_externally')}

} if (!hasPassword) { return (

{t('no_existing_password')}

) } return } function PasswordForm() { const { t } = useTranslation() const passwordStrengthOptions = getMeta( 'ol-passwordStrengthOptions' ) as PasswordStrengthOptions const [currentPassword, setCurrentPassword] = useState('') const [newPassword1, setNewPassword1] = useState('') const [newPassword2, setNewPassword2] = useState('') const { isLoading, isSuccess, isError, data, error, runAsync } = useAsync() const [isNewPasswordValid, setIsNewPasswordValid] = useState(false) const [isFormValid, setIsFormValid] = useState(false) const handleCurrentPasswordChange = ( event: React.ChangeEvent ) => { setCurrentPassword(event.target.value) } const handleNewPassword1Change = ( event: React.ChangeEvent ) => { setNewPassword1(event.target.value) setIsNewPasswordValid(event.target.validity.valid) } const handleNewPassword2Change = ( event: React.ChangeEvent ) => { setNewPassword2(event.target.value) } useEffect(() => { setIsFormValid( !!currentPassword && isNewPasswordValid && newPassword1 === newPassword2 ) }, [currentPassword, newPassword1, newPassword2, isNewPasswordValid]) const handleSubmit = (event: React.FormEvent) => { event.preventDefault() if (!isFormValid) { return } runAsync( postJSON('/user/password/update', { body: { currentPassword, newPassword1, newPassword2, }, }) ).catch(() => {}) } return (
{isSuccess && data?.message?.text ? ( {data.message.text} ) : null} {isError ? ( {getErrorMessageKey(error) === 'password-must-be-strong' ? ( <> , ]} /> . {t('use_a_different_password')}. ) : getErrorMessageKey(error) === 'password-contains-email' ? ( <> {t('invalid_password_contains_email')}.{' '} {t('use_a_different_password')}. ) : getErrorMessageKey(error) === 'password-too-similar' ? ( <> {t('invalid_password_too_similar')}.{' '} {t('use_a_different_password')}. ) : ( getUserFacingMessage(error) )} ) : null} ) } type PasswordFormGroupProps = { id: string label: string value: string handleChange: (event: React.ChangeEvent) => void minLength?: number validationMessage?: string autoComplete?: string } function PasswordFormGroup({ id, label, value, handleChange, minLength, validationMessage: parentValidationMessage, autoComplete, }: PasswordFormGroupProps) { const [validationMessage, setValidationMessage] = useState('') const [hadInteraction, setHadInteraction] = useState(false) const handleInvalid = ( event: React.InvalidEvent ) => { event.preventDefault() } const handleChangeAndValidity = ( event: React.ChangeEvent ) => { handleChange(event) setHadInteraction(true) setValidationMessage(event.target.validationMessage) } return ( {label} {hadInteraction && (parentValidationMessage || validationMessage) ? ( {parentValidationMessage || validationMessage} ) : null} ) } export default PasswordSection