Use same lock values as mobile clients
[ProtonMail-WebClient.git] / packages / shared / lib / api / helpers / getAndVerifyApiKeys.ts
blob5ca0fb20894d77c7c5d337569b6f839c4449f84e
1 import { CryptoProxy } from '@proton/crypto';
2 import isTruthy from '@proton/utils/isTruthy';
4 import type { API_KEY_SOURCE } from '../../constants';
5 import type {
6     Api,
7     FetchedSignedKeyList,
8     KeyTransparencyVerificationResult,
9     ProcessedApiKey,
10     VerifyOutboundPublicKeys,
11 } from '../../interfaces';
12 import { getAllPublicKeys } from '../keys';
14 export interface ApiKeysWithKTStatus {
15     Address: {
16         Keys: ApiAddressKey[];
17         SignedKeyList: FetchedSignedKeyList | null;
18     };
19     addressKeys: ProcessedApiKey[];
20     addressKTResult?: KeyTransparencyVerificationResult;
21     catchAllKeys?: ProcessedApiKey[];
22     catchAllKTResult?: KeyTransparencyVerificationResult;
23     unverifiedKeys?: ProcessedApiKey[];
24     hasValidProtonMX?: boolean;
25     Code?: number;
26     Warnings?: string[];
29 interface ApiAddressKey {
30     PublicKey: string;
31     Flags: number;
32     Source: API_KEY_SOURCE;
35 const importKeys = async (keys: ApiAddressKey[], checkCompatibility?: boolean): Promise<ProcessedApiKey[]> => {
36     const promises = await Promise.all(
37         keys.map(async ({ PublicKey: armoredKey, Flags, Source }) => {
38             const publicKey = await CryptoProxy.importPublicKey({ armoredKey, checkCompatibility }).catch(() => null);
40             if (!publicKey) {
41                 return null;
42             }
44             return {
45                 armoredKey,
46                 flags: Flags,
47                 publicKey: publicKey,
48                 source: Source,
49             };
50         })
51     );
53     return promises.filter(isTruthy);
56 export const getAndVerifyApiKeys = async ({
57     api,
58     email,
59     internalKeysOnly,
60     verifyOutboundPublicKeys,
61     skipVerificationOfExternalDomains = false,
62     silence = false,
63     noCache = false,
64 }: {
65     api: Api;
66     email: string;
67     internalKeysOnly: boolean;
68     /** KT verification function, or `null` for legacy use-case where KT is disabled */
69     verifyOutboundPublicKeys: VerifyOutboundPublicKeys | null;
70     /** Optimisations _only_ for apps where users with external domains do not have valid keys (e.g. Mail) */
71     skipVerificationOfExternalDomains?: boolean;
72     silence?: boolean;
73     noCache?: boolean;
74 }): Promise<ApiKeysWithKTStatus> => {
75     const config: any = { ...getAllPublicKeys({ Email: email, InternalOnly: internalKeysOnly ? 1 : 0 }), silence };
76     if (noCache) {
77         config.cache = 'no-cache';
78     }
79     const { Address, CatchAll, Unverified, ProtonMX, ...rest } = await api<{
80         Address: {
81             Keys: ApiAddressKey[];
82             SignedKeyList: FetchedSignedKeyList | null;
83         };
84         CatchAll:
85             | {
86                   Keys: ApiAddressKey[];
87                   SignedKeyList: FetchedSignedKeyList | null;
88               }
89             | undefined;
90         Unverified: {
91             Keys: ApiAddressKey[];
92         };
93         ProtonMX: boolean;
94         Warnings: string[];
95     }>(config);
96     const addressKeys = await importKeys(Address.Keys);
97     const unverifiedKeys = Unverified ? await importKeys(Unverified.Keys, true) : undefined;
98     const catchAllKeys = CatchAll ? await importKeys(CatchAll.Keys) : undefined;
99     const ktResult = verifyOutboundPublicKeys
100         ? await verifyOutboundPublicKeys(
101               email,
102               skipVerificationOfExternalDomains,
103               { keyList: addressKeys, signedKeyList: Address.SignedKeyList },
104               CatchAll ? { keyList: catchAllKeys!, signedKeyList: CatchAll.SignedKeyList } : undefined
105           )
106         : {};
107     return {
108         Address,
109         addressKeys,
110         catchAllKeys,
111         unverifiedKeys,
112         hasValidProtonMX: ProtonMX,
113         ...rest,
114         ...ktResult,
115     };