1 import { useState } from 'react';
3 import { c } from 'ttag';
5 import { changeMemberPassword } from '@proton/account/organizationKey/memberPasswordAction';
6 import { Button } from '@proton/atoms';
7 import Form from '@proton/components/components/form/Form';
8 import type { ModalProps } from '@proton/components/components/modalTwo/Modal';
9 import Modal from '@proton/components/components/modalTwo/Modal';
10 import ModalContent from '@proton/components/components/modalTwo/ModalContent';
11 import ModalFooter from '@proton/components/components/modalTwo/ModalFooter';
12 import ModalHeader from '@proton/components/components/modalTwo/ModalHeader';
13 import InputFieldTwo from '@proton/components/components/v2/field/InputField';
14 import PasswordInputTwo from '@proton/components/components/v2/input/PasswordInput';
15 import useFormErrors from '@proton/components/components/v2/useFormErrors';
16 import AuthModal from '@proton/components/containers/password/AuthModal';
17 import useApi from '@proton/components/hooks/useApi';
18 import useBeforeUnload from '@proton/components/hooks/useBeforeUnload';
19 import useErrorHandler from '@proton/components/hooks/useErrorHandler';
20 import useNotifications from '@proton/components/hooks/useNotifications';
21 import { useDispatch } from '@proton/redux-shared-store';
22 import { revoke } from '@proton/shared/lib/api/auth';
23 import { authMember } from '@proton/shared/lib/api/members';
24 import { lockSensitiveSettings } from '@proton/shared/lib/api/user';
25 import { withUIDHeaders } from '@proton/shared/lib/fetch/headers';
27 confirmPasswordValidator,
28 passwordLengthValidator,
30 } from '@proton/shared/lib/helpers/formValidators';
31 import type { Member } from '@proton/shared/lib/interfaces/Member';
32 import noop from '@proton/utils/noop';
34 import GenericError from '../error/GenericError';
38 confirmPassword: string;
41 interface Props extends ModalProps {
45 const ChangeMemberPasswordModal = ({ member, onClose, ...rest }: Props) => {
46 const normalApi = useApi();
47 const dispatch = useDispatch();
48 const silentApi = <T,>(config: any) => normalApi<T>({ ...config, silence: true });
49 const [memberAuthData, setMemberAuthData] = useState<{ UID: string }>();
50 const handleError = useErrorHandler();
52 const { createNotification } = useNotifications();
53 const { validator, onFormSubmit } = useFormErrors();
55 const lockAndClose = () => {
56 if (memberAuthData?.UID) {
58 silentApi(withUIDHeaders(memberAuthData.UID, revoke())),
59 silentApi(lockSensitiveSettings()),
65 const [inputs, setInputs] = useState<Inputs>({
69 const [loading, setLoading] = useState<boolean>(false);
70 const [error, setError] = useState(false);
72 useBeforeUnload(loading ? c('Info').t`By leaving now, changes may not be saved` : '');
74 const setPartialInput = (object: Partial<Inputs>) => setInputs((oldState) => ({ ...oldState, ...object }));
76 const newPasswordError = passwordLengthValidator(inputs.newPassword);
77 const confirmPasswordError =
78 passwordLengthValidator(inputs.confirmPassword) ||
79 confirmPasswordValidator(inputs.newPassword, inputs.confirmPassword);
81 if (!memberAuthData) {
85 config={authMember(member.ID, { Unlock: true })}
88 onSuccess={async (result) => {
89 const { response } = result;
91 const data = await response.json();
92 const UID = data?.UID;
94 throw new Error('Failed to get auth data');
96 setMemberAuthData({ UID });
103 const handleClose = () => {
107 <Modal {...rest} onClose={handleClose}>
108 <ModalHeader title={c('Title').t`Change password`} />
114 <Button color="norm" onClick={handleClose}>
122 const onSubmit = async () => {
123 if (!onFormSubmit()) {
126 if (newPasswordError || confirmPasswordError) {
134 changeMemberPassword({
136 memberUID: memberAuthData.UID,
137 password: inputs.newPassword,
142 createNotification({ text: c('Success').t`Password updated` });
152 const handleClose = loading ? noop : lockAndClose;
155 <b key="user" className="text-break">
156 {member.Name} ({(member?.Addresses || [])[0]?.Email ?? ''})
161 <Modal as={Form} onClose={handleClose} {...rest} onSubmit={onSubmit}>
162 <ModalHeader title={c('Title').t`Change password`} />
164 <div className="mb-4">{c('Info').jt`Enter new password for user ${userName}.`}</div>
167 label={c('Label').t`User's new password`}
169 requiredValidator(inputs.newPassword),
170 passwordLengthValidator(inputs.newPassword),
172 as={PasswordInputTwo}
174 autoComplete="new-password"
175 value={inputs.newPassword}
176 onValue={(value: string) => setPartialInput({ newPassword: value })}
182 label={c('Label').t`Confirm new password`}
184 requiredValidator(inputs.confirmPassword),
185 passwordLengthValidator(inputs.confirmPassword),
186 confirmPasswordValidator(inputs.newPassword, inputs.confirmPassword),
188 as={PasswordInputTwo}
189 autoComplete="new-password"
190 value={inputs.confirmPassword}
191 onValue={(value: string) => setPartialInput({ confirmPassword: value })}
196 <Button onClick={handleClose} disabled={loading}>
197 {c('Action').t`Cancel`}
199 <Button loading={loading} type="submit" color="norm">
200 {c('Action').t`Change password`}
207 export default ChangeMemberPasswordModal;