Merge branch 'DRVDOC-1260' into 'main'
[ProtonMail-WebClient.git] / packages / components / containers / recovery / SessionRecoverySection.tsx
blob2adf74b941fc5d04f612d6bd737e8079ab2feb70
1 import { c } from 'ttag';
3 import { Button } from '@proton/atoms';
4 import useModalState from '@proton/components/components/modalTwo/useModalState';
5 import Toggle from '@proton/components/components/toggle/Toggle';
6 import useApi from '@proton/components/hooks/useApi';
7 import useEventManager from '@proton/components/hooks/useEventManager';
8 import useNotifications from '@proton/components/hooks/useNotifications';
9 import useLoading from '@proton/hooks/useLoading';
10 import metrics, { observeApiError } from '@proton/metrics';
11 import { updateSessionAccountRecovery } from '@proton/shared/lib/api/sessionRecovery';
13 import {
14     useAvailableRecoveryMethods,
15     useIsSessionRecoveryEnabled,
16     useIsSessionRecoveryInitiationAvailable,
17 } from '../../hooks/useSessionRecovery';
18 import ChangePasswordModal, { MODES } from '../account/ChangePasswordModal';
19 import ReauthUsingRecoveryModal from '../account/ReauthUsingRecoveryModal';
20 import SettingsLayout from '../account/SettingsLayout';
21 import SettingsLayoutLeft from '../account/SettingsLayoutLeft';
22 import SettingsLayoutRight from '../account/SettingsLayoutRight';
23 import SettingsParagraph from '../account/SettingsParagraph';
24 import SettingsSection from '../account/SettingsSection';
25 import InitiateSessionRecoveryModal from '../account/sessionRecovery/InitiateSessionRecoveryModal';
26 import ConfirmDisableSessionRecoveryModal from './ConfirmDisableSessionRecoveryModal';
28 export const SessionRecoverySection = () => {
29     const api = useApi();
30     const { call } = useEventManager();
32     const [loadingSessionRecovery, withLoadingSessionRecovery] = useLoading();
34     const [sessionRecoveryModal, setSessionRecoveryModalOpen, renderSessionRecoveryModal] = useModalState();
35     const [recoveryModal, setRecoveryModalOpen, renderRecoveryModal] = useModalState();
36     const [changePasswordModal, setChangePasswordModalOpen, renderChangePasswordModal] = useModalState();
37     const [
38         confirmDisableSessionRecoveryModal,
39         setConfirmDisableSessionRecoveryModalOpen,
40         renderConfirmDisableSessionRecoveryModal,
41     ] = useModalState();
43     const [availableRecoveryMethods, loadingUseHasRecoveryMethod] = useAvailableRecoveryMethods();
44     const hasRecoveryMethod = availableRecoveryMethods.length > 0;
45     const isSessionRecoveryEnabled = useIsSessionRecoveryEnabled();
46     const isSessionRecoveryInitiationAvailable = useIsSessionRecoveryInitiationAvailable();
48     const { createNotification } = useNotifications();
50     const handleEnableSessionRecoveryToggle = async () => {
51         try {
52             await api(updateSessionAccountRecovery({ SessionAccountRecovery: 1 }));
53             await call();
54             metrics.core_session_recovery_settings_update_total.increment({
55                 status: 'success',
56             });
57         } catch (error) {
58             observeApiError(error, (status) =>
59                 metrics.core_session_recovery_settings_update_total.increment({
60                     status,
61                 })
62             );
63         }
64     };
66     return (
67         <>
68             {renderSessionRecoveryModal && (
69                 <InitiateSessionRecoveryModal
70                     onUseRecoveryMethodClick={() => {
71                         sessionRecoveryModal.onClose();
72                         setRecoveryModalOpen(true);
73                     }}
74                     confirmedStep
75                     {...sessionRecoveryModal}
76                 />
77             )}
78             {renderRecoveryModal && (
79                 <ReauthUsingRecoveryModal
80                     availableRecoveryMethods={availableRecoveryMethods}
81                     onBack={() => {
82                         recoveryModal.onClose();
83                         setSessionRecoveryModalOpen(true);
84                     }}
85                     onInitiateSessionRecoveryClick={() => {
86                         recoveryModal.onClose();
87                         setSessionRecoveryModalOpen(true);
88                     }}
89                     onSuccess={() => setChangePasswordModalOpen(true)}
90                     {...recoveryModal}
91                 />
92             )}
93             {renderChangePasswordModal && (
94                 <ChangePasswordModal
95                     mode={MODES.CHANGE_ONE_PASSWORD_MODE}
96                     signedInRecoveryFlow
97                     {...changePasswordModal}
98                 />
99             )}
100             {renderConfirmDisableSessionRecoveryModal && (
101                 <ConfirmDisableSessionRecoveryModal {...confirmDisableSessionRecoveryModal} />
102             )}
103             <SettingsSection>
104                 <SettingsParagraph>
105                     {c('session_recovery:settings:info')
106                         .t`To enhance the security of your account and protect your data, you can request a password reset from your account settings in the web application.`}
107                 </SettingsParagraph>
109                 <SettingsLayout>
110                     <SettingsLayoutLeft>
111                         <label className="pt-0 mb-2 md:mb-0 text-semibold" htmlFor="signedInReset">
112                             <span className="mr-2">
113                                 {c('session_recovery:settings:action').t`Allow password reset from settings`}
114                             </span>
115                         </label>
116                     </SettingsLayoutLeft>
117                     <SettingsLayoutRight isToggleContainer>
118                         <div className="flex items-center">
119                             <Toggle
120                                 loading={loadingSessionRecovery}
121                                 checked={isSessionRecoveryEnabled}
122                                 disabled={loadingUseHasRecoveryMethod}
123                                 id="signedInReset"
124                                 onChange={({ target: { checked } }) => {
125                                     if (!hasRecoveryMethod && !checked) {
126                                         createNotification({
127                                             text: c('session_recovery:settings:info')
128                                                 .t`To disallow password reset, you must have a recovery method set up.`,
129                                         });
130                                         return;
131                                     }
133                                     if (!checked) {
134                                         setConfirmDisableSessionRecoveryModalOpen(true);
135                                         return;
136                                     }
138                                     void withLoadingSessionRecovery(handleEnableSessionRecoveryToggle());
139                                 }}
140                             />
141                         </div>
143                         {isSessionRecoveryInitiationAvailable && (
144                             <Button className="mt-4" color="norm" onClick={() => setSessionRecoveryModalOpen(true)}>
145                                 {c('session_recovery:settings:action').t`Request password reset`}
146                             </Button>
147                         )}
148                     </SettingsLayoutRight>
149                 </SettingsLayout>
150             </SettingsSection>
151         </>
152     );