|
1 | | -import { ApiSecurity, ApiUrl, AppDetails } from '../shared'; |
2 | | -import { headersWithToken } from '../shared/headers'; |
3 | | -import { HttpClient } from '../shared/http/client'; |
4 | | -import { |
5 | | - EncryptedKeystore, |
6 | | - KeystoreType, |
7 | | - HybridEncryptedEmail, |
8 | | - PwdProtectedEmail, |
9 | | - HybridKeyPair, |
10 | | - Email, |
11 | | - RecipientWithPublicKey, |
12 | | - base64ToUint8Array, |
13 | | - EmailPublicParameters, |
14 | | -} from 'internxt-crypto'; |
15 | | - |
16 | | -import { createKeystores, encryptEmail, passwordProtectAndSendEmail, openKeystore, recoverKeys } from './create'; |
17 | | - |
18 | | -export class Mail { |
19 | | - private readonly client: HttpClient; |
20 | | - private readonly appDetails: AppDetails; |
21 | | - private readonly apiSecurity: ApiSecurity; |
22 | | - private readonly apiUrl: ApiUrl; |
23 | | - |
24 | | - public static client(apiUrl: ApiUrl, appDetails: AppDetails, apiSecurity: ApiSecurity) { |
25 | | - return new Mail(apiUrl, appDetails, apiSecurity); |
26 | | - } |
27 | | - |
28 | | - private constructor(apiUrl: ApiUrl, appDetails: AppDetails, apiSecurity: ApiSecurity) { |
29 | | - this.client = HttpClient.create(apiUrl, apiSecurity.unauthorizedCallback); |
30 | | - this.appDetails = appDetails; |
31 | | - this.apiSecurity = apiSecurity; |
32 | | - this.apiUrl = apiUrl; |
33 | | - } |
34 | | - |
35 | | - /** |
36 | | - * Uploads encrypted keystore to the server |
37 | | - * |
38 | | - * @param encryptedKeystore - The encrypted keystore |
39 | | - * @returns Server response |
40 | | - */ |
41 | | - async uploadKeystoreToServer(encryptedKeystore: EncryptedKeystore): Promise<void> { |
42 | | - return this.client.post(`${this.apiUrl}/keystore`, { encryptedKeystore }, this.headers()); |
43 | | - } |
44 | | - |
45 | | - /** |
46 | | - * Creates recovery and encryption keystores and uploads them to the server |
47 | | - * |
48 | | - * @param userEmail - The email of the user |
49 | | - * @param baseKey - The secret key of the user |
50 | | - * @returns The recovery codes and keys of the user |
51 | | - */ |
52 | | - async createAndUploadKeystores( |
53 | | - userEmail: string, |
54 | | - baseKey: Uint8Array, |
55 | | - ): Promise<{ recoveryCodes: string; keys: HybridKeyPair }> { |
56 | | - const { encryptionKeystore, recoveryKeystore, recoveryCodes, keys } = await createKeystores(userEmail, baseKey); |
57 | | - await Promise.all([this.uploadKeystoreToServer(encryptionKeystore), this.uploadKeystoreToServer(recoveryKeystore)]); |
58 | | - return { recoveryCodes, keys }; |
59 | | - } |
60 | | - |
61 | | - /** |
62 | | - * Requests encrypted keystore from the server |
63 | | - * |
64 | | - * @param userEmail - The email of the user |
65 | | - * @param keystoreType - The type of the keystore |
66 | | - * @returns The encrypted keystore |
67 | | - */ |
68 | | - async downloadKeystoreFromServer(userEmail: string, keystoreType: KeystoreType): Promise<EncryptedKeystore> { |
69 | | - return this.client.getWithParams(`${this.apiUrl}/user/keystore`, { userEmail, keystoreType }, this.headers()); |
70 | | - } |
71 | | - |
72 | | - /** |
73 | | - * Requests encrypted keystore from the server and opens it |
74 | | - * |
75 | | - * @param userEmail - The email of the user |
76 | | - * @param baseKey - The secret key of the user |
77 | | - * @returns The hybrid keys of the user |
78 | | - */ |
79 | | - async getUserEmailKeys(userEmail: string, baseKey: Uint8Array): Promise<HybridKeyPair> { |
80 | | - const keystore = await this.downloadKeystoreFromServer(userEmail, KeystoreType.ENCRYPTION); |
81 | | - return openKeystore(keystore, baseKey); |
82 | | - } |
83 | | - |
84 | | - /** |
85 | | - * Requests recovery keystore from the server and opens it |
86 | | - * |
87 | | - * @param userEmail - The email of the user |
88 | | - * @param recoveryCodes - The recovery codes of the user |
89 | | - * @returns The hybrid keys of the user |
90 | | - */ |
91 | | - async recoverUserEmailKeys(userEmail: string, recoveryCodes: string): Promise<HybridKeyPair> { |
92 | | - const keystore = await this.downloadKeystoreFromServer(userEmail, KeystoreType.RECOVERY); |
93 | | - return recoverKeys(keystore, recoveryCodes); |
94 | | - } |
95 | | - |
96 | | - /** |
97 | | - * Request user with corresponding public keys from the server |
98 | | - * |
99 | | - * @param userEmail - The email of the user |
100 | | - * @returns User with corresponding public keys |
101 | | - */ |
102 | | - async getUserWithPublicKeys(userEmail: string): Promise<RecipientWithPublicKey> { |
103 | | - const response = await this.client.post<{ publicKey: string; email: string }[]>( |
104 | | - `${this.apiUrl}/users/public-keys`, |
105 | | - { emails: [userEmail] }, |
106 | | - this.headers(), |
107 | | - ); |
108 | | - if (!response[0]) throw new Error(`No public keys found for ${userEmail}`); |
109 | | - const singleResponse = response[0]; |
110 | | - const publicHybridKey = base64ToUint8Array(singleResponse.publicKey); |
111 | | - const result = { email: singleResponse.email, publicHybridKey }; |
112 | | - return result; |
113 | | - } |
114 | | - |
115 | | - /** |
116 | | - * Request users with corresponding public keys from the server |
117 | | - * |
118 | | - * @param emails - The emails of the users |
119 | | - * @returns Users with corresponding public keys |
120 | | - */ |
121 | | - async getSeveralUsersWithPublicKeys(emails: string[]): Promise<RecipientWithPublicKey[]> { |
122 | | - const response = await this.client.post<{ publicKey: string; email: string }[]>( |
123 | | - `${this.apiUrl}/users/public-keys`, |
124 | | - { emails }, |
125 | | - this.headers(), |
126 | | - ); |
127 | | - |
128 | | - const result = await Promise.all( |
129 | | - response.map(async (item) => { |
130 | | - const publicHybridKey = base64ToUint8Array(item.publicKey); |
131 | | - return { email: item.email, publicHybridKey }; |
132 | | - }), |
133 | | - ); |
134 | | - |
135 | | - return result; |
136 | | - } |
137 | | - |
138 | | - /** |
139 | | - * Sends the encrypted emails to the server |
140 | | - * |
141 | | - * @param emails - The encrypted emails |
142 | | - * @param params - The public parameters of the email (sender, recipients, CCs, BCCs, etc.) |
143 | | - * @returns Server response |
144 | | - */ |
145 | | - async sendEncryptedEmail(emails: HybridEncryptedEmail[], params: EmailPublicParameters): Promise<void> { |
146 | | - return this.client.post(`${this.apiUrl}/emails`, { emails, params }, this.headers()); |
147 | | - } |
148 | | - |
149 | | - /** |
150 | | - * Encrypts and sends email(s) to the server |
151 | | - * |
152 | | - * @param email - The message to encrypt |
153 | | - * @param aux - The optional auxilary data to encrypt together with the email (e.g. email sender) |
154 | | - * @returns Server response |
155 | | - */ |
156 | | - async encryptAndSendEmail(email: Email, aux?: string): Promise<void> { |
157 | | - const recipientEmails = email.params.recipients.map((user) => user.email); |
158 | | - const recipients = await this.getSeveralUsersWithPublicKeys(recipientEmails); |
159 | | - |
160 | | - const encEmails = await encryptEmail(email, recipients, aux); |
161 | | - return this.sendEncryptedEmail(encEmails, email.params); |
162 | | - } |
163 | | - |
164 | | - /** |
165 | | - * Sends the password-protected email to the server |
166 | | - * |
167 | | - * @param email - The password-protected email |
168 | | - * @returns Server response |
169 | | - */ |
170 | | - async sendPasswordProtectedEmail(email: PwdProtectedEmail, params: EmailPublicParameters): Promise<void> { |
171 | | - return this.client.post(`${this.apiUrl}/emails`, { email, params }, this.headers()); |
172 | | - } |
173 | | - |
174 | | - /** |
175 | | - * Creates the password-protected email and sends it to the server |
176 | | - * |
177 | | - * @param email - The email |
178 | | - * @param pwd - The password |
179 | | - * @param aux - The optional auxilary data to encrypt together with the email (e.g. email sender) |
180 | | - * @returns Server response |
181 | | - */ |
182 | | - async passwordProtectAndSendEmail(email: Email, pwd: string, aux?: string): Promise<void> { |
183 | | - const encEmail = await passwordProtectAndSendEmail(email, pwd, aux); |
184 | | - return this.sendPasswordProtectedEmail(encEmail, email.params); |
185 | | - } |
186 | | - |
187 | | - /** |
188 | | - * Returns the needed headers for the module requests |
189 | | - * @private |
190 | | - */ |
191 | | - private headers() { |
192 | | - return headersWithToken({ |
193 | | - clientName: this.appDetails.clientName, |
194 | | - clientVersion: this.appDetails.clientVersion, |
195 | | - token: this.apiSecurity.token, |
196 | | - desktopToken: this.appDetails.desktopHeader, |
197 | | - customHeaders: this.appDetails.customHeaders, |
198 | | - }); |
199 | | - } |
200 | | -} |
| 1 | +export * from './types'; |
| 2 | +export * from './mail'; |
0 commit comments