Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / shared / lib / keys / reactivation / reactivateKeysProcessLegacy.ts
blob420f280a4a9df354449fba54da403d2941572585
1 import type { PrivateKeyReferenceV4, PrivateKeyReferenceV6 } from '@proton/crypto';
2 import { CryptoProxy } from '@proton/crypto';
3 import { getDefaultKeyFlags } from '@proton/shared/lib/keys';
5 import { reactivateKeyRoute } from '../../api/keys';
6 import {
7     type ActiveKeyWithVersion,
8     type Address,
9     type Api,
10     type DecryptedKey,
11     type Key,
12     type KeyTransparencyVerify,
13     isActiveKeyV6,
14 } from '../../interfaces';
15 import {
16     getActiveAddressKeys,
17     getActiveKeyObject,
18     getNormalizedActiveAddressKeys,
19     getPrimaryFlag,
20 } from '../getActiveKeys';
21 import { getSignedKeyListWithDeferredPublish } from '../signedKeyList';
22 import type { KeyReactivationData, KeyReactivationRecord, OnKeyReactivationCallback } from './interface';
23 import { resetUserId } from './reactivateKeyHelper';
25 interface ReactivateKeysProcessArguments {
26     api: Api;
27     keyPassword: string;
28     keysToReactivate: KeyReactivationData[];
29     address?: Address;
30     onReactivation: OnKeyReactivationCallback;
31     keys: DecryptedKey[];
32     Keys: Key[];
33     keyTransparencyVerify: KeyTransparencyVerify;
36 export const reactivateKeysProcess = async ({
37     api,
38     keyPassword,
39     keysToReactivate,
40     address,
41     onReactivation,
42     keys,
43     Keys,
44     keyTransparencyVerify,
45 }: ReactivateKeysProcessArguments) => {
46     const activeKeys = await getActiveAddressKeys(address, address?.SignedKeyList, Keys, keys);
48     let mutableActiveKeys = activeKeys;
50     for (const keyToReactivate of keysToReactivate) {
51         const { id, Key, privateKey: reactivatedKey } = keyToReactivate;
52         const { ID } = Key;
53         try {
54             if (!reactivatedKey) {
55                 throw new Error('Missing key');
56             }
58             await resetUserId(Key, reactivatedKey);
60             const privateKeyArmored = await CryptoProxy.exportPrivateKey({
61                 privateKey: reactivatedKey,
62                 passphrase: keyPassword,
63             });
64             const newActiveKey = (await getActiveKeyObject(
65                 reactivatedKey as PrivateKeyReferenceV4 | PrivateKeyReferenceV6,
66                 {
67                     ID,
68                     // We do not mark the v6 as primary by default, because it will fail if forwarding is enabled
69                     primary: reactivatedKey.isPrivateKeyV6() ? 0 : getPrimaryFlag(mutableActiveKeys.v4),
70                     flags: getDefaultKeyFlags(address),
71                 }
72             )) as ActiveKeyWithVersion;
73             const toNormalize = isActiveKeyV6(newActiveKey)
74                 ? { v4: [...mutableActiveKeys.v4], v6: [...mutableActiveKeys.v6, newActiveKey] }
75                 : { v4: [...mutableActiveKeys.v4, newActiveKey], v6: [...mutableActiveKeys.v6] };
76             const updatedActiveKeys = getNormalizedActiveAddressKeys(address, toNormalize);
77             const [SignedKeyList, onSKLPublishSuccess] = address
78                 ? await getSignedKeyListWithDeferredPublish(updatedActiveKeys, address, keyTransparencyVerify)
79                 : [undefined, undefined];
80             await api(
81                 reactivateKeyRoute({
82                     ID,
83                     PrivateKey: privateKeyArmored,
84                     SignedKeyList,
85                 })
86             );
87             if (onSKLPublishSuccess) {
88                 await onSKLPublishSuccess();
89             }
91             mutableActiveKeys = updatedActiveKeys;
93             onReactivation(id, 'ok');
94         } catch (e: any) {
95             onReactivation(id, e);
96         }
97     }
100 export interface ReactivateKeysProcessLegacyArguments {
101     api: Api;
102     keyReactivationRecords: KeyReactivationRecord[];
103     onReactivation: OnKeyReactivationCallback;
104     addressesKeys: { address: Address; keys: DecryptedKey[] }[];
105     userKeys: DecryptedKey[];
106     keyPassword: string;
107     keyTransparencyVerify: KeyTransparencyVerify;
110 const reactivateKeysProcessLegacy = async ({
111     keyReactivationRecords,
112     addressesKeys,
113     userKeys,
114     api,
115     onReactivation,
116     keyPassword,
117     keyTransparencyVerify,
118 }: ReactivateKeysProcessLegacyArguments) => {
119     for (const keyReactivationRecord of keyReactivationRecords) {
120         const { user, address, keysToReactivate } = keyReactivationRecord;
121         try {
122             const Keys = address ? address.Keys : user?.Keys || [];
123             const keys = address
124                 ? addressesKeys.find((addressKeys) => addressKeys.address.ID === address.ID)?.keys
125                 : userKeys;
126             if (!keys) {
127                 throw new Error('Missing keys');
128             }
129             await reactivateKeysProcess({
130                 api,
131                 keyPassword,
132                 keysToReactivate,
133                 address,
134                 onReactivation,
135                 keys,
136                 Keys,
137                 keyTransparencyVerify,
138             });
139         } catch (e: any) {
140             keysToReactivate.forEach(({ id }) => onReactivation(id, e));
141         }
142     }
145 export default reactivateKeysProcessLegacy;