Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / packages / components / containers / organization / useOrganizationModals.tsx
blobf817b7265eed8bae3f1c7007577b9cbb2bcd7156
1 import type { MutableRefObject } from 'react';
2 import { useEffect, useState } from 'react';
4 import { c, msgid } from 'ttag';
6 import { useAddresses } from '@proton/account/addresses/hooks';
7 import { useMembers } from '@proton/account/members/hooks';
8 import { useOrganization } from '@proton/account/organization/hooks';
9 import { getPrivatizeError } from '@proton/account/organizationKey/actions';
10 import { useOrganizationKey } from '@proton/account/organizationKey/hooks';
11 import { useUser } from '@proton/account/user/hooks';
12 import { Button, Href } from '@proton/atoms';
13 import useModalState from '@proton/components/components/modalTwo/useModalState';
14 import { MemberListBanner, MembersList } from '@proton/components/containers/organization/MemberListBanner';
15 import useNotifications from '@proton/components/hooks/useNotifications';
16 import { MEMBER_ROLE } from '@proton/shared/lib/constants';
17 import { getKnowledgeBaseUrl } from '@proton/shared/lib/helpers/url';
18 import type { Member } from '@proton/shared/lib/interfaces';
19 import {
20     OrganizationKeyMode,
21     OrganizationKeyState,
22     getMemberHasAccessToOrgKey,
23     getMemberHasMissingOrgKey,
24     getNonPrivateMembers,
25     getOrganizationKeyInfo,
26 } from '@proton/shared/lib/organization/helper';
28 import ActivatePasswordlessOrganizationKey from './ActivatePasswordlessOrganizationKey';
29 import ChangeOrganizationKeysModal from './ChangeOrganizationKeysModal';
30 import ChangeOrganizationKeysPasswordlessModal from './ChangeOrganizationKeysPasswordlessModal';
31 import ChangeOrganizationPasswordModal from './ChangeOrganizationPasswordModal';
32 import InviteOrganizationKeysModal from './InviteOrganizationKeysModal';
33 import ReactivateOrganizationKeysModal from './ReactivateOrganizationKeysModal';
34 import ReactivatePasswordlessOrganizationKey from './ReactivatePasswordlessOrganizationKey';
35 import { getActivationText, getReactivationText } from './helper';
37 const UserNeedsToInvite = ({
38     onRestorePrivilegesClick,
39     otherAdminsWithMissingOrgKeys,
40 }: {
41     onRestorePrivilegesClick: () => void;
42     otherAdminsWithMissingOrgKeys: Member[];
43 }) => {
44     const n = otherAdminsWithMissingOrgKeys.length;
45     return (
46         <MemberListBanner
47             icon="info-circle"
48             members={
49                 <>
50                     <div>
51                         {c('Restore administrator panel').ngettext(
52                             msgid`${n} administrator in your organization need access to the organization key.`,
53                             `${n} administrators in your organization need access to the organization key.`,
54                             n
55                         )}
56                     </div>
57                     <Href href={getKnowledgeBaseUrl('/restore-administrator')} className="inline-block">
58                         {c('Link').t`Learn more`}
59                     </Href>
60                     <MembersList members={otherAdminsWithMissingOrgKeys} />
61                 </>
62             }
63             action={
64                 <Button size="small" color="norm" onClick={onRestorePrivilegesClick}>
65                     {c('Title').t`Restore administrator privileges`}
66                 </Button>
67             }
68         />
69     );
72 const UserNeedsToReactivatePasswordless = ({ onRestorePrivilegesClick }: { onRestorePrivilegesClick: () => void }) => {
73     return (
74         <MemberListBanner
75             icon="info-circle"
76             members={
77                 <>
78                     <div>{getReactivationText()}</div>
79                     <Href href={getKnowledgeBaseUrl('/restore-administrator')} className="inline-block">
80                         {c('Link').t`Learn more`}
81                     </Href>
82                 </>
83             }
84             action={
85                 <Button size="small" color="norm" onClick={onRestorePrivilegesClick}>
86                     {c('Title').t`Restore administrator privileges`}
87                 </Button>
88             }
89         />
90     );
93 const UserNeedsToReactivate = ({ onRestorePrivilegesClick }: { onRestorePrivilegesClick: () => void }) => {
94     return (
95         <MemberListBanner
96             icon="info-circle"
97             members={
98                 <>
99                     <div>
100                         {c('Restore administrator panel')
101                             .t`Due to a password change, your organization administrator privileges have been restricted. The following actions are no longer permitted:`}
102                     </div>
103                     <ul className="mb-0">
104                         <li>{c('Restore administrator panel').t`Creating or accessing non-private user accounts`}</li>
105                         <li>{c('Restore administrator panel').t`Changing organization password`}</li>
106                         <li>{c('Restore administrator panel').t`Changing organization keys`}</li>
107                     </ul>
108                     <Href href={getKnowledgeBaseUrl('/restore-administrator')} className="inline-block">
109                         {c('Link').t`Learn more`}
110                     </Href>
111                 </>
112             }
113             action={
114                 <Button size="small" color="norm" onClick={onRestorePrivilegesClick}>
115                     {c('Title').t`Restore administrator privileges`}
116                 </Button>
117             }
118         />
119     );
122 const UserNeedsToActivate = ({ onActiveOrganizationKeyClick }: { onActiveOrganizationKeyClick: () => void }) => {
123     return (
124         <MemberListBanner
125             icon="info-circle"
126             members={getActivationText()}
127             action={
128                 <Button size="small" color="norm" onClick={onActiveOrganizationKeyClick}>
129                     {c('Action').t`Activate organization key`}
130                 </Button>
131             }
132         />
133     );
136 const useOrganizationModals = (onceRef: MutableRefObject<boolean>) => {
137     const [user] = useUser();
138     const [organization] = useOrganization();
139     const [organizationKey, loadingOrganizationKey] = useOrganizationKey();
140     const [addresses] = useAddresses();
141     const [members, loadingMembers] = useMembers();
142     const { createNotification } = useNotifications();
143     const [reactivateModalProps, setReactivateModal, reactivateModalRender] = useModalState();
144     const [reactivatePasswordlessModalProps, setReactivatePasswordlessModal, renderReactivatePasswordlessModal] =
145         useModalState();
146     const [activateModalProps, setActivateModal, renderActivateModal] = useModalState();
147     const [activatePasswordlessModalProps, setActivatePasswordlessModal, renderActivatePasswordless] = useModalState();
148     const [changeOrganizationKeysProps, setChangeOrganizationKeys, renderChangeOrganizationKeys] = useModalState();
149     const [
150         changePasswordlessOrganizationKeysProps,
151         setChangePasswordlessOrganizationKeys,
152         renderChangePasswordlessOrganizationKeys,
153     ] = useModalState();
154     const [
155         invitePasswordlessOrganizationKeys,
156         setInvitePasswordlessOrganizationKeys,
157         renderInvitePasswordlessOrganizationKeys,
158     ] = useModalState();
159     const [changeOrganizationPasswordProps, setChangeOrganizationPassword, renderChangeOrganizationPassword] =
160         useModalState();
161     const [changeMode, setChangeMode] = useState<'reset' | undefined>();
163     const organizationKeyInfo = getOrganizationKeyInfo(organization, organizationKey, addresses);
164     const otherAdmins = (members || []).filter(
165         (member) => member.Role === MEMBER_ROLE.ORGANIZATION_ADMIN && !member.Self
166     );
167     const otherAdminsWithKeyAccess = otherAdmins.filter(getMemberHasAccessToOrgKey);
168     const otherAdminsWithMissingOrgKey = otherAdmins.filter(getMemberHasMissingOrgKey);
169     const hasOtherAdmins = otherAdmins.length > 0;
170     const publicMembers = getNonPrivateMembers(members || []);
172     const disableResetOrganizationKeys = publicMembers.length > 0 && !organizationKey?.privateKey;
174     const handleChangeOrganizationKeys = (mode?: 'reset') => {
175         if (!organizationKey) {
176             throw new Error('Organization key not loaded');
177         }
178         if (disableResetOrganizationKeys) {
179             return createNotification({
180                 text: getPrivatizeError(),
181                 type: 'error',
182             });
183         }
184         setChangeMode(mode);
185         if (organizationKeyInfo.mode === OrganizationKeyMode.Passwordless) {
186             setChangePasswordlessOrganizationKeys(true);
187         } else {
188             setChangeOrganizationKeys(true);
189         }
190     };
192     const handleResetOrganizationKeys = () => {
193         handleChangeOrganizationKeys('reset');
194     };
196     const handleChangeOrganizationPassword = () => {
197         if (!organizationKey?.privateKey) {
198             return createNotification({ text: c('Error').t`Organization key is not decrypted`, type: 'error' });
199         }
201         setChangeOrganizationPassword(true);
202     };
204     const disabled =
205         !organization ||
206         loadingMembers ||
207         loadingOrganizationKey ||
208         !organizationKey ||
209         !user.isAdmin ||
210         !organization?.HasKeys;
212     useEffect(() => {
213         if (onceRef.current || disabled) {
214             return;
215         }
217         if (organizationKeyInfo.mode === OrganizationKeyMode.Passwordless) {
218             if (organizationKeyInfo.state === OrganizationKeyState.Activate) {
219                 setActivatePasswordlessModal(true);
220                 onceRef.current = true;
221             } else if (organizationKeyInfo.state === OrganizationKeyState.Inactive) {
222                 setReactivatePasswordlessModal(true);
223                 onceRef.current = true;
224             }
225         } else {
226             if (organizationKeyInfo.state === OrganizationKeyState.Activate) {
227                 setActivateModal(true);
228                 onceRef.current = true;
229             } else if (organizationKeyInfo.state === OrganizationKeyState.Inactive) {
230                 setReactivateModal(true);
231                 onceRef.current = true;
232             }
233         }
234     }, [disabled]);
236     const modals = (
237         <>
238             {reactivateModalRender && (
239                 <ReactivateOrganizationKeysModal
240                     mode="reactivate"
241                     onResetKeys={handleResetOrganizationKeys}
242                     {...reactivateModalProps}
243                 />
244             )}
245             {renderActivateModal && (
246                 <ReactivateOrganizationKeysModal
247                     mode="activate"
248                     onResetKeys={handleResetOrganizationKeys}
249                     {...activateModalProps}
250                 />
251             )}
252             {renderActivatePasswordless && (
253                 <ActivatePasswordlessOrganizationKey
254                     onResetKeys={handleResetOrganizationKeys}
255                     {...activatePasswordlessModalProps}
256                 />
257             )}
258             {renderReactivatePasswordlessModal && (
259                 <ReactivatePasswordlessOrganizationKey
260                     user={user}
261                     onResetKeys={handleResetOrganizationKeys}
262                     disableResetOrganizationKeys={disableResetOrganizationKeys}
263                     otherAdminsWithKeyAccess={otherAdminsWithKeyAccess}
264                     {...reactivatePasswordlessModalProps}
265                 />
266             )}
267             {renderChangeOrganizationKeys && organizationKey && (
268                 <ChangeOrganizationKeysModal
269                     mode={changeMode}
270                     hasOtherAdmins={hasOtherAdmins}
271                     organizationKey={organizationKey}
272                     {...changeOrganizationKeysProps}
273                 />
274             )}
275             {renderChangePasswordlessOrganizationKeys && (
276                 <ChangeOrganizationKeysPasswordlessModal
277                     mode={changeMode}
278                     {...changePasswordlessOrganizationKeysProps}
279                 />
280             )}
281             {renderInvitePasswordlessOrganizationKeys && (
282                 <InviteOrganizationKeysModal
283                     members={otherAdminsWithMissingOrgKey}
284                     {...invitePasswordlessOrganizationKeys}
285                 />
286             )}
287             {renderChangeOrganizationPassword && organizationKey?.privateKey && (
288                 <ChangeOrganizationPasswordModal
289                     hasOtherAdmins={hasOtherAdmins}
290                     organizationKey={organizationKey.privateKey}
291                     {...changeOrganizationPasswordProps}
292                 />
293             )}
294         </>
295     );
297     const handleActivatePasswordless = () => {
298         setActivatePasswordlessModal(true);
299     };
300     const handleReActivatePasswordless = () => {
301         setReactivatePasswordlessModal(true);
302     };
304     const handleActivate = () => {
305         if (organizationKeyInfo.mode === OrganizationKeyMode.Passwordless) {
306             handleActivatePasswordless();
307         } else {
308             setActivateModal(true);
309         }
310     };
311     const handleReactivate = () => {
312         if (organizationKeyInfo.mode === OrganizationKeyMode.Passwordless) {
313             handleReActivatePasswordless();
314         } else {
315             setActivateModal(true);
316         }
317     };
319     const info = (() => {
320         if (disabled || organizationKeyInfo.state === OrganizationKeyState.NoKey) {
321             return null;
322         }
323         if (organizationKeyInfo.mode === OrganizationKeyMode.Passwordless) {
324             if (organizationKeyInfo.state === OrganizationKeyState.Activate) {
325                 return <UserNeedsToActivate onActiveOrganizationKeyClick={handleActivatePasswordless} />;
326             }
327             if (organizationKeyInfo.state === OrganizationKeyState.Inactive) {
328                 return <UserNeedsToReactivatePasswordless onRestorePrivilegesClick={handleReActivatePasswordless} />;
329             }
330             if (otherAdminsWithMissingOrgKey.length) {
331                 return (
332                     <UserNeedsToInvite
333                         onRestorePrivilegesClick={() => {
334                             setInvitePasswordlessOrganizationKeys(true);
335                         }}
336                         otherAdminsWithMissingOrgKeys={otherAdminsWithMissingOrgKey}
337                     />
338                 );
339             }
340         } else {
341             if (organizationKeyInfo.state === OrganizationKeyState.Activate) {
342                 return <UserNeedsToActivate onActiveOrganizationKeyClick={handleActivate} />;
343             }
344             if (organizationKeyInfo.state === OrganizationKeyState.Inactive) {
345                 return <UserNeedsToReactivate onRestorePrivilegesClick={handleReactivate} />;
346             }
347         }
348     })();
350     return {
351         modals,
352         info,
353         handleChangeOrganizationPassword,
354         handleChangeOrganizationKeys,
355         handleResetOrganizationKeys,
356         handleActivatePasswordless,
357         handleActivate,
358         handleReactivate,
359     };
362 export default useOrganizationModals;