Use same lock values as mobile clients
[ProtonMail-WebClient.git] / packages / shared / lib / calendar / crypto / keys / reactivateCalendarKeys.ts
blobb2684b2705a76b30a9d98d4d009a3fc2489fc0b9
1 import type { useGetAddressKeys } from '@proton/components';
2 import { CryptoProxy } from '@proton/crypto';
4 import { getAllCalendarKeys, getPassphrases, queryMembers, reactivateCalendarKey } from '../../../api/calendars';
5 import type { Address, Api } from '../../../interfaces';
6 import type {
7     Calendar,
8     CalendarKey,
9     CalendarMember,
10     Passphrase,
11     ReenableKeyResponse,
12 } from '../../../interfaces/calendar';
13 import { splitKeys } from '../../../keys';
14 import { getMemberAddressWithAdminPermissions } from '../../getMemberWithAdmin';
15 import { decryptPassphrase } from './calendarKeys';
17 interface ReactivateCalendarsKeysArgumentsShared {
18     api: Api;
19     getAddressKeys: ReturnType<typeof useGetAddressKeys>;
20     addresses: Address[];
23 interface ReactivateCalendarsKeysArguments extends ReactivateCalendarsKeysArgumentsShared {
24     calendars: Calendar[];
27 interface ReactivateCalendarKeysArguments extends ReactivateCalendarsKeysArgumentsShared {
28     ID: string;
31 const reactivateCalendarKeys = async ({
32     api,
33     ID: CalendarID,
34     getAddressKeys,
35     addresses,
36 }: ReactivateCalendarKeysArguments) => {
37     const [{ Keys = [] }, { Passphrases = [] }, { Members = [] }] = await Promise.all([
38         api<{ Keys: CalendarKey[] }>(getAllCalendarKeys(CalendarID)),
39         api<{ Passphrases: Passphrase[] }>(getPassphrases(CalendarID)),
40         api<{ Members: CalendarMember[] }>(queryMembers(CalendarID)),
41     ]);
43     const { Member: selfMember, Address: selfAddress } = getMemberAddressWithAdminPermissions(Members, addresses);
44     const addressKeys = await getAddressKeys(selfAddress.ID);
45     const { privateKeys, publicKeys } = splitKeys(addressKeys);
47     const decryptedPrimaryPassphrase = await (() => {
48         const targetPassphrase = Passphrases.find(({ Flags }) => Flags === 1);
49         if (!targetPassphrase) {
50             throw new Error('Passphrase not found');
51         }
52         const { MemberPassphrases = [] } = targetPassphrase;
53         const memberPassphrase = MemberPassphrases.find(({ MemberID }) => MemberID === selfMember.ID);
54         if (!memberPassphrase) {
55             throw new Error('Member passphrase not found');
56         }
57         const { Passphrase, Signature } = memberPassphrase;
58         return decryptPassphrase({
59             armoredPassphrase: Passphrase,
60             armoredSignature: Signature,
61             privateKeys,
62             publicKeys,
63         });
64     })();
66     return Promise.all(
67         Keys.filter(({ Flags }) => Flags === 0).map(async ({ PassphraseID, PrivateKey, ID: KeyID }) => {
68             try {
69                 const targetPassphrase = Passphrases.find(
70                     ({ ID: otherPassphraseID }) => otherPassphraseID === PassphraseID
71                 );
72                 if (!targetPassphrase) {
73                     throw new Error('Passphrase not found');
74                 }
75                 const { MemberPassphrases = [] } = targetPassphrase;
76                 const memberPassphrase = MemberPassphrases.find(({ MemberID }) => MemberID === selfMember.ID);
77                 if (!memberPassphrase) {
78                     throw new Error('Member passphrase not found');
79                 }
80                 const { Passphrase, Signature } = memberPassphrase;
81                 const decryptedPassphrase = await decryptPassphrase({
82                     armoredPassphrase: Passphrase,
83                     armoredSignature: Signature,
84                     privateKeys,
85                     publicKeys,
86                 });
87                 const privateKey = await CryptoProxy.importPrivateKey({
88                     armoredKey: PrivateKey,
89                     passphrase: decryptedPassphrase,
90                 });
91                 const armoredEncryptedKey = await CryptoProxy.exportPrivateKey({
92                     privateKey: privateKey,
93                     passphrase: decryptedPrimaryPassphrase,
94                 });
95                 return await api<ReenableKeyResponse>(
96                     reactivateCalendarKey(CalendarID, KeyID, { PrivateKey: armoredEncryptedKey })
97                 );
98             } catch (e: any) {
99                 console.error(e);
100             }
101         })
102     );
105 export const reactivateCalendarsKeys = async ({
106     api,
107     calendars,
108     getAddressKeys,
109     addresses,
110 }: ReactivateCalendarsKeysArguments) => {
111     return Promise.all(
112         calendars.map(async (calendar) => {
113             return reactivateCalendarKeys({
114                 api,
115                 ID: calendar.ID,
116                 getAddressKeys,
117                 addresses,
118             });
119         })
120     );