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'> {
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}`;
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');
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;
65 const token = await dispatch(getOrganizationTokenThunk());
67 await persistSession({
73 // Signing into subuser doesn't need offline mode support
75 offlineKey: undefined,
76 persistent: authentication.getPersistent(),
85 config={authMember(member.ID)}
88 onSuccess={async ({ response }) => {
89 const data = await response.json();
90 const LocalID = await handleData(data);
98 const memberAddress = <b key="member">{getMemberEmailOrName(member)}</b>;
102 title={c('Title').t`Signed in to member account`}
104 <ButtonLike as="a" color="norm" target="_blank" href={switchUrl} onClick={onClose}>
105 {c('Action').t`Switch account`}
107 <Button color="weak" onClick={onClose}>
108 {c('Action').t`Close`}
114 <div className="mb-4 text-break">{c('Info').jt`You are signed in to the account ${memberAddress}.`}</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>
123 export default LoginMemberModal;