Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / packages / components / containers / organization / ReactivateOrganizationKeysModal.tsx
blob549fdaf7819499b2a46893a179bacd2775874c1e
1 import { useState } from 'react';
3 import { c } from 'ttag';
5 import { useGetOrganizationKey } from '@proton/account/organizationKey/hooks';
6 import { Button, Href } from '@proton/atoms';
7 import Alert from '@proton/components/components/alert/Alert';
8 import Form from '@proton/components/components/form/Form';
9 import type { ModalProps } from '@proton/components/components/modalTwo/Modal';
10 import Modal from '@proton/components/components/modalTwo/Modal';
11 import ModalContent from '@proton/components/components/modalTwo/ModalContent';
12 import ModalFooter from '@proton/components/components/modalTwo/ModalFooter';
13 import ModalHeader from '@proton/components/components/modalTwo/ModalHeader';
14 import InputFieldTwo from '@proton/components/components/v2/field/InputField';
15 import PasswordInputTwo from '@proton/components/components/v2/input/PasswordInput';
16 import useFormErrors from '@proton/components/components/v2/useFormErrors';
17 import useApi from '@proton/components/hooks/useApi';
18 import useAuthentication from '@proton/components/hooks/useAuthentication';
19 import useEventManager from '@proton/components/hooks/useEventManager';
20 import useNotifications from '@proton/components/hooks/useNotifications';
21 import type { PrivateKeyReference } from '@proton/crypto';
22 import { CryptoProxy } from '@proton/crypto';
23 import { useLoading } from '@proton/hooks';
24 import { CacheType } from '@proton/redux-utilities';
25 import { activateOrganizationKey, getOrganizationBackupKeys } from '@proton/shared/lib/api/organization';
26 import { requiredValidator } from '@proton/shared/lib/helpers/formValidators';
27 import { getKnowledgeBaseUrl } from '@proton/shared/lib/helpers/url';
28 import { decryptPrivateKeyWithSalt } from '@proton/shared/lib/keys';
29 import noop from '@proton/utils/noop';
31 interface Props extends ModalProps {
32     mode: 'reactivate' | 'activate';
33     onResetKeys?: () => void;
36 const ReactivateOrganizationKeysModal = ({ onResetKeys, mode, onClose, ...rest }: Props) => {
37     const getOrganizationKey = useGetOrganizationKey();
38     const { createNotification } = useNotifications();
39     const { call } = useEventManager();
40     const authentication = useAuthentication();
41     const api = useApi();
42     const { validator, onFormSubmit } = useFormErrors();
44     const [loading, withLoading] = useLoading();
45     const [backupPassword, setBackupPassword] = useState('');
46     const [error, setError] = useState('');
48     const { title, message, warning, success } = (() => {
49         if (mode === 'activate') {
50             return {
51                 title: c('Title').t`Activate organization key`,
52                 message: c('Info')
53                     .t`You must activate your organization private key with the backup organization key password provided to you by your organization administrator.`,
54                 warning: c('Info')
55                     .t`Without activation you will not be able to create new users, add addresses to existing users, or access non-private user accounts.`,
56                 success: c('passwordless').t`Organization key activated`,
57             };
58         }
60         if (mode === 'reactivate') {
61             const learnMore = (
62                 <Href key={1} href={getKnowledgeBaseUrl('/restore-administrator')}>
63                     {c('Link').t`Learn more`}
64                 </Href>
65             );
66             return {
67                 title: c('Title').t`Restore administrator privileges`,
68                 message: c('Info')
69                     .jt`Enter the Organization Password to restore administrator privileges. ${learnMore}`,
70                 warning: c('Info')
71                     .t`If another administrator changed this password, you will need to ask them for the new Organization Password.`,
72                 success: c('passwordless').t`Organization key restored`,
73             };
74         }
76         throw new Error('Invalid mode');
77     })();
79     const handleSubmit = async () => {
80         try {
81             setError('');
83             const { PrivateKey, KeySalt } = await api(getOrganizationBackupKeys());
84             let decryptedPrivateKey: PrivateKeyReference;
86             try {
87                 decryptedPrivateKey = await decryptPrivateKeyWithSalt({
88                     PrivateKey,
89                     password: backupPassword,
90                     keySalt: KeySalt,
91                 });
92             } catch (e) {
93                 throw new Error(c('Error').t`Incorrect password`);
94             }
96             const armoredPrivateKey = await CryptoProxy.exportPrivateKey({
97                 privateKey: decryptedPrivateKey,
98                 passphrase: authentication.getPassword(),
99             });
100             await api(activateOrganizationKey(armoredPrivateKey));
101             await call();
102             // Warning: Force a refetch of the org key because it's not present in the event manager.
103             await getOrganizationKey({ cache: CacheType.None });
105             createNotification({ text: success });
106             onClose?.();
107         } catch (e: any) {
108             setError(e.message);
109         }
110     };
112     const handleClose = loading ? noop : onClose;
114     return (
115         <Modal
116             as={Form}
117             onSubmit={() => {
118                 if (!onFormSubmit()) {
119                     return;
120                 }
121                 void withLoading(handleSubmit());
122             }}
123             onClose={handleClose}
124             {...rest}
125         >
126             <ModalHeader title={title} />
127             <ModalContent>
128                 <div className="mb-4">{message}</div>
129                 <Alert className="mb-4" type="warning">
130                     {warning}
131                 </Alert>
132                 <InputFieldTwo
133                     id="organizationPassword"
134                     as={PasswordInputTwo}
135                     label={c('Label').t`Organization password`}
136                     placeholder={c('Placeholder').t`Password`}
137                     value={backupPassword}
138                     onValue={(value: string) => {
139                         setError('');
140                         setBackupPassword(value);
141                     }}
142                     error={validator([requiredValidator(backupPassword), error])}
143                     autoComplete="off"
144                     autoFocus
145                 />
146             </ModalContent>
147             <ModalFooter>
148                 <Button onClick={handleClose} disabled={loading}>
149                     {c('Action').t`Close`}
150                 </Button>
151                 <div>
152                     {onResetKeys && (
153                         <Button
154                             className="mr-4"
155                             onClick={() => {
156                                 onClose?.();
157                                 onResetKeys();
158                             }}
159                         >{c('Action').t`Reset keys`}</Button>
160                     )}
161                     <Button loading={loading} type="submit" color="norm">
162                         {c('Action').t`Save`}
163                     </Button>
164                 </div>
165             </ModalFooter>
166         </Modal>
167     );
170 export default ReactivateOrganizationKeysModal;