1 import type { ReactNode } from 'react';
2 import { useEffect, useState } from 'react';
4 import { c } from 'ttag';
6 import type { AcceptOrganizationKeyInvitePayload } from '@proton/account';
7 import { acceptOrganizationKeyInvite, prepareAcceptOrganizationKeyInvite } from '@proton/account';
8 import { useOrganization } from '@proton/account/organization/hooks';
9 import { useOrganizationKey } from '@proton/account/organizationKey/hooks';
10 import { Button, Card, CircleLoader } from '@proton/atoms';
11 import Icon from '@proton/components/components/icon/Icon';
12 import type { ModalProps } from '@proton/components/components/modalTwo/Modal';
13 import ModalTwo from '@proton/components/components/modalTwo/Modal';
14 import ModalTwoContent from '@proton/components/components/modalTwo/ModalContent';
15 import ModalTwoFooter from '@proton/components/components/modalTwo/ModalFooter';
16 import ModalTwoHeader from '@proton/components/components/modalTwo/ModalHeader';
17 import getBoldFormattedText from '@proton/components/helpers/getBoldFormattedText';
18 import useApi from '@proton/components/hooks/useApi';
19 import useErrorHandler from '@proton/components/hooks/useErrorHandler';
20 import useNotifications from '@proton/components/hooks/useNotifications';
21 import { useLoading } from '@proton/hooks';
22 import { useDispatch } from '@proton/redux-shared-store';
23 import { getSilentApi } from '@proton/shared/lib/api/helpers/customConfig';
24 import { BRAND_NAME } from '@proton/shared/lib/constants';
25 import noop from '@proton/utils/noop';
27 import useVerifyOutboundPublicKeys from '../keyTransparency/useVerifyOutboundPublicKeys';
29 interface Props extends Omit<ModalProps, 'buttons' | 'title' | 'children'> {
30 onResetKeys?: () => void;
33 const ActivatePasswordlessOrganizationKey = ({ onResetKeys, ...rest }: Props) => {
34 const [organizationKey] = useOrganizationKey();
35 const [organization] = useOrganization();
36 const organizationName = organization?.Name || '';
37 const adminEmail = organizationKey?.Key.SignatureAddress || '';
38 const { createNotification } = useNotifications();
39 const dispatch = useDispatch();
40 const errorHandler = useErrorHandler();
41 const verifyOutboundPublicKeys = useVerifyOutboundPublicKeys();
42 const [payload, setPayload] = useState<AcceptOrganizationKeyInvitePayload | null>(null);
43 const silentApi = getSilentApi(useApi());
45 const [loading, withLoading] = useLoading();
46 const [loadingInit, withLoadingInit] = useLoading(true);
51 prepareAcceptOrganizationKeyInvite({
54 verifyOutboundPublicKeys,
65 const handleSubmit = async () => {
66 if (payload?.state === 'verified') {
68 await dispatch(acceptOrganizationKeyInvite({ api: silentApi, payload }));
69 createNotification({ text: c('passwordless').t`Organization key activated` });
78 const handleClose = loading ? noop : rest.onClose;
81 <ModalTwo open {...rest} onClose={handleClose}>
82 <ModalTwoHeader title={c('Title').t`Activate organization key`} {...rest} />
85 if (payload === null || loadingInit) {
87 <div className="text-center">
93 <div className="text-break mb-2">
94 {getBoldFormattedText(
96 .t`You have been made administrator of the organization **${organizationName}** by`
100 const getCard = (icon: ReactNode) => {
102 <Card rounded className="text-break">
103 <div className="flex justify-space-between gap-1">
104 <div className="flex-1">{adminEmail}</div>
105 <div className="shrink-0">{icon}</div>
111 if (payload.state === 'verified') {
115 {getCard(<Icon name="checkmark-circle-filled" className="color-success" />)}
116 <div className="mt-2 color-weak">
118 .t`We have verified the authenticity of this sender and invitation.`}
122 .t`To enable administrator rights on your account, activate the organization key.`}
131 {getCard(<Icon name="info-circle-filled" className="color-danger" />)}
132 <div className="mt-2 color-danger">
134 .t`We couldn't verify the security of this sender's address key. Sometimes there is a delay in updating the sender's information. Try again later. If you do not trust the validity of this invitation or sender, contact ${BRAND_NAME} Customer Support.`}
141 {payload === null || payload.state === 'verified' ? (
143 <Button disabled={loading} onClick={handleClose}>
144 {c('Action').t`Cancel`}
150 withLoading(handleSubmit());
153 {c('Action').t`Activate`}
159 <Button color="norm" disabled={loading} onClick={handleClose}>
160 {c('Action').t`Got it`}
169 export default ActivatePasswordlessOrganizationKey;