feat(INDA-383): daily stats.
[ProtonMail-WebClient.git] / packages / shared / lib / keys / updateActiveKeys.ts
blob65d4055d4137a151eada871e01f67eb319c4154d
1 import type { ActiveAddressKeyPayload } from '../api/keys';
2 import { AddressActiveStatus, updateAddressActiveKeysRoute } from '../api/keys';
3 import type { ActiveKey, Address, AddressKey, Api, DecryptedKey, KeyTransparencyVerify } from '../interfaces';
4 import { getActiveAddressKeys, getNormalizedActiveAddressKeys } from './getActiveKeys';
5 import { getInactiveKeys } from './getInactiveKeys';
6 import { getSignedKeyListWithDeferredPublish } from './signedKeyList';
8 /**
9  * Filters the decrypted keys to include only those that have been migrated and have a matching
10  * address key.
11  * A key is considered migrated if it has a Token and a Signature associated with it.
12  */
13 function filterMigratedDecryptedKeys(decryptedKeys: DecryptedKey[], addressKeys: AddressKey[]) {
14     return decryptedKeys.filter(({ ID }) => {
15         const matchingAddressKey = addressKeys.find((addressKey) => ID === addressKey.ID);
16         return matchingAddressKey && matchingAddressKey.Token && matchingAddressKey.Signature;
17     });
20 /**
21  * Checks if there is a mismatch between active keys reported by the server
22  * and decrypted keys of the client.
23  */
24 export const hasActiveKeysMismatch = (address: Address, decryptedKeys: DecryptedKey[]): Boolean => {
25     if (!decryptedKeys.length || !address.SignedKeyList) {
26         // If there are no decrypted keys or no skl, do not update.
27         return false;
28     }
29     // Only consider migrated keys as active.
30     const migratedDecryptedKeys = filterMigratedDecryptedKeys(decryptedKeys, address.Keys);
31     const activeKeysIDs = new Set(migratedDecryptedKeys.map(({ ID }) => ID));
32     return address.Keys.some(({ Active, ID }) => Active && !activeKeysIDs.has(ID));
35 /**
36  * Updates the active keys in the backend with the current active keys at the client.
37  * Should be called if a mismatch of active keys between the server and the client has been detected.
38  */
39 export const updateActiveKeys = async (
40     api: Api,
41     address: Address,
42     decryptedKeys: DecryptedKey[],
43     keyTransparencyVerify: KeyTransparencyVerify
44 ) => {
45     // Only consider migrated keys as active.
46     const migratedDecryptedKeys = filterMigratedDecryptedKeys(decryptedKeys, address.Keys);
47     const [activeKeys, inactiveKeys] = await Promise.all([
48         getActiveAddressKeys(address, address.SignedKeyList, address.Keys, migratedDecryptedKeys),
49         getInactiveKeys(address.Keys, migratedDecryptedKeys),
50     ]);
51     const normalizedActiveKeysByVersion = getNormalizedActiveAddressKeys(address, activeKeys);
52     const [signedKeyList, onSKLPublishSuccess] = await getSignedKeyListWithDeferredPublish(
53         normalizedActiveKeysByVersion,
54         address,
55         keyTransparencyVerify
56     );
57     const normalizedActiveKeys = (normalizedActiveKeysByVersion.v4 as ActiveKey[]).concat(
58         normalizedActiveKeysByVersion.v6
59     );
60     const activeKeysPayload = normalizedActiveKeys.map<ActiveAddressKeyPayload>(({ ID }) => {
61         return {
62             AddressKeyID: ID,
63             Active: AddressActiveStatus.ACTIVE,
64         };
65     });
66     const inactiveKeysPayload = inactiveKeys.map<ActiveAddressKeyPayload>(({ Key }) => {
67         return {
68             AddressKeyID: Key.ID,
69             Active: AddressActiveStatus.INACTIVE,
70         };
71     });
72     await api(
73         updateAddressActiveKeysRoute({
74             AddressID: address.ID,
75             Keys: activeKeysPayload.concat(inactiveKeysPayload),
76             SignedKeyList: signedKeyList,
77         })
78     );
79     await onSKLPublishSuccess();