Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / components / containers / members / LoginMemberModal.tsx
blobacbcd4b312fa8e2b9e0bb33045cb28db43f53f4b
1 import { useMemo, useState } from 'react';
3 import { c } from 'ttag';
5 import { getOrganizationTokenThunk } from '@proton/account';
6 import { Button, ButtonLike, Href } from '@proton/atoms';
7 import type { PromptProps } from '@proton/components/components/prompt/Prompt';
8 import Prompt from '@proton/components/components/prompt/Prompt';
9 import AuthModal from '@proton/components/containers/password/AuthModal';
10 import useApi from '@proton/components/hooks/useApi';
11 import useAuthentication from '@proton/components/hooks/useAuthentication';
12 import { useDispatch } from '@proton/redux-shared-store';
13 import { revoke } from '@proton/shared/lib/api/auth';
14 import { authMember } from '@proton/shared/lib/api/members';
15 import { getUser } from '@proton/shared/lib/api/user';
16 import { getAppHref } from '@proton/shared/lib/apps/helper';
17 import { getSlugFromApp } from '@proton/shared/lib/apps/slugHelper';
18 import { maybeResumeSessionByUser, persistSession } from '@proton/shared/lib/authentication/persistedSessionHelper';
19 import type { APP_NAMES } from '@proton/shared/lib/constants';
20 import { APPS, SSO_PATHS } from '@proton/shared/lib/constants';
21 import { withUIDHeaders } from '@proton/shared/lib/fetch/headers';
22 import { getKnowledgeBaseUrl } from '@proton/shared/lib/helpers/url';
23 import type { User } from '@proton/shared/lib/interfaces';
24 import type { Member } from '@proton/shared/lib/interfaces/Member';
25 import { getMemberEmailOrName } from '@proton/shared/lib/keys/memberHelper';
26 import noop from '@proton/utils/noop';
28 interface Props extends Omit<PromptProps, 'title' | 'children' | 'buttons'> {
29     member: Member;
30     app: APP_NAMES;
33 const LoginMemberModal = ({ app, member, onClose, ...rest }: Props) => {
34     const normalApi = useApi();
35     const silentApi = <T,>(config: any) => normalApi<T>({ ...config, silence: true });
36     const [authed, setAuthed] = useState(false);
37     const [data, setData] = useState<{ LocalID: number }>();
38     const authentication = useAuthentication();
39     const dispatch = useDispatch();
41     const switchUrl = useMemo(() => {
42         const href = getAppHref(SSO_PATHS.SWITCH, APPS.PROTONACCOUNT);
43         const search = `?product=${getSlugFromApp(app || APPS.PROTONMAIL)}`;
44         return `${href}${search}`;
45     }, [app]);
47     if (!authed || !data) {
48         const handleData = async (data: { UID: string; LocalID: number }) => {
49             const UID = data?.UID;
50             const LocalID = data?.LocalID;
52             if (!UID || !LocalID) {
53                 throw new Error('Failed to get auth data');
54             }
56             const memberApi = <T,>(config: any) => silentApi<T>(withUIDHeaders(UID, config));
57             const User = await memberApi<{ User: User }>(getUser()).then(({ User }) => User);
59             const validatedSession = await maybeResumeSessionByUser(silentApi, User);
60             if (validatedSession) {
61                 memberApi(revoke()).catch(noop);
62                 return validatedSession.LocalID;
63             }
65             const token = await dispatch(getOrganizationTokenThunk());
67             await persistSession({
68                 api: memberApi,
69                 keyPassword: token,
70                 User,
71                 LocalID,
72                 UID,
73                 // Signing into subuser doesn't need offline mode support
74                 clearKeyPassword: '',
75                 offlineKey: undefined,
76                 persistent: authentication.getPersistent(),
77                 trusted: false,
78             });
80             return LocalID;
81         };
82         return (
83             <AuthModal
84                 scope="password"
85                 config={authMember(member.ID)}
86                 {...rest}
87                 onCancel={onClose}
88                 onSuccess={async ({ response }) => {
89                     const data = await response.json();
90                     const LocalID = await handleData(data);
91                     setData({ LocalID });
92                     setAuthed(true);
93                 }}
94             />
95         );
96     }
98     const memberAddress = <b key="member">{getMemberEmailOrName(member)}</b>;
100     return (
101         <Prompt
102             title={c('Title').t`Signed in to member account`}
103             buttons={[
104                 <ButtonLike as="a" color="norm" target="_blank" href={switchUrl} onClick={onClose}>
105                     {c('Action').t`Switch account`}
106                 </ButtonLike>,
107                 <Button color="weak" onClick={onClose}>
108                     {c('Action').t`Close`}
109                 </Button>,
110             ]}
111             onClose={onClose}
112             {...rest}
113         >
114             <div className="mb-4 text-break">{c('Info').jt`You are signed in to the account ${memberAddress}.`}</div>
115             <div>
116                 {c('Info').t`You can now access and manage the account as an administrator.`}{' '}
117                 <Href href={getKnowledgeBaseUrl('/manage-public-users-organization')}>{c('Link').t`Learn more`}</Href>
118             </div>
119         </Prompt>
120     );
123 export default LoginMemberModal;