@secrecy/lib 1.74.0-feat-groups-identity.4 → 1.74.0-feat-transfer-adaptations.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/base-client.js +4 -27
- package/dist/lib/client/SecrecyAppClient.js +17 -13
- package/dist/lib/client/SecrecyCloudClient.js +156 -368
- package/dist/lib/client/SecrecyDbClient.js +7 -3
- package/dist/lib/client/SecrecyMailClient.js +48 -38
- package/dist/lib/client/SecrecyOrganizationClient.js +12 -10
- package/dist/lib/client/SecrecyPayClient.js +5 -1
- package/dist/lib/client/SecrecyPseudonymClient.js +8 -4
- package/dist/lib/client/SecrecyUserClient.js +11 -11
- package/dist/lib/client/SecrecyWalletClient.js +2 -0
- package/dist/lib/client/convert/data.js +4 -4
- package/dist/lib/client/convert/mail.js +6 -5
- package/dist/lib/client/convert/node.js +34 -46
- package/dist/lib/client/data-link.js +77 -0
- package/dist/lib/client/download.js +84 -0
- package/dist/lib/client/helpers.js +11 -18
- package/dist/lib/client/index.js +12 -48
- package/dist/lib/client/storage.js +2 -3
- package/dist/lib/client/types/index.js +7 -3
- package/dist/lib/client/upload.js +252 -0
- package/dist/lib/client.js +7 -0
- package/dist/lib/crypto/data.js +3 -0
- package/dist/lib/crypto/domain.js +123 -12
- package/dist/lib/crypto/helpers.js +23 -0
- package/dist/lib/index.js +0 -1
- package/dist/types/base-client.d.ts +1 -2
- package/dist/types/client/SecrecyAppClient.d.ts +3 -2
- package/dist/types/client/SecrecyCloudClient.d.ts +28 -20
- package/dist/types/client/SecrecyDbClient.d.ts +3 -1
- package/dist/types/client/SecrecyMailClient.d.ts +3 -2
- package/dist/types/client/SecrecyOrganizationClient.d.ts +3 -2
- package/dist/types/client/SecrecyPayClient.d.ts +3 -1
- package/dist/types/client/SecrecyPseudonymClient.d.ts +3 -2
- package/dist/types/client/SecrecyUserClient.d.ts +3 -2
- package/dist/types/client/convert/data.d.ts +3 -3
- package/dist/types/client/convert/mail.d.ts +5 -3
- package/dist/types/client/convert/node.d.ts +5 -5
- package/dist/types/client/data-link.d.ts +37 -0
- package/dist/types/client/download.d.ts +2 -0
- package/dist/types/client/index.d.ts +3 -11
- package/dist/types/client/storage.d.ts +2 -3
- package/dist/types/client/types/index.d.ts +9 -13
- package/dist/types/client/types/mail.d.ts +1 -2
- package/dist/types/client/types/node.d.ts +9 -12
- package/dist/types/client/types/user.d.ts +0 -15
- package/dist/types/client/upload.d.ts +38 -0
- package/dist/types/client.d.ts +6174 -681
- package/dist/types/crypto/domain.d.ts +36 -8
- package/dist/types/crypto/helpers.d.ts +12 -0
- package/dist/types/crypto/index.d.ts +3 -3
- package/dist/types/index.d.ts +1 -2
- package/package.json +4 -2
- package/dist/lib/client/types/identity.js +0 -18
- package/dist/types/client/types/identity.d.ts +0 -29
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export class SecrecyDbClient {
|
|
2
|
-
#client;
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
// #client: SecrecyClient;
|
|
3
|
+
// #keys: KeyPair;
|
|
4
|
+
#apiClient;
|
|
5
|
+
constructor(_client, _keys, apiClient) {
|
|
6
|
+
// this.#client = client;
|
|
7
|
+
// this.#keys = keys;
|
|
8
|
+
this.#apiClient = apiClient;
|
|
5
9
|
}
|
|
6
10
|
}
|
|
@@ -3,29 +3,35 @@ import { encryptCryptoBox, sodium } from '../index.js';
|
|
|
3
3
|
import { convertInternalMailToExternal } from './convert/mail.js';
|
|
4
4
|
export class SecrecyMailClient {
|
|
5
5
|
#client;
|
|
6
|
-
|
|
6
|
+
#keys;
|
|
7
|
+
#apiClient;
|
|
8
|
+
constructor(client, keys, apiClient) {
|
|
7
9
|
this.#client = client;
|
|
10
|
+
this.#keys = keys;
|
|
11
|
+
this.#apiClient = apiClient;
|
|
8
12
|
}
|
|
9
13
|
async get({ id }) {
|
|
10
|
-
const mail = await this.#
|
|
14
|
+
const mail = await this.#apiClient.mail.byId.query({ id });
|
|
11
15
|
return await convertInternalMailToExternal({
|
|
12
16
|
mail,
|
|
13
|
-
|
|
17
|
+
client: this.#client,
|
|
18
|
+
keyPair: this.#keys,
|
|
14
19
|
});
|
|
15
20
|
}
|
|
16
21
|
async recover({ mailId }) {
|
|
17
|
-
const { isRecovered } = await this.#
|
|
22
|
+
const { isRecovered } = await this.#apiClient.mail.recover.mutate({
|
|
18
23
|
id: mailId,
|
|
19
24
|
});
|
|
20
25
|
return isRecovered;
|
|
21
26
|
}
|
|
22
27
|
async deletedMails({ mailType, }) {
|
|
23
|
-
const deletedMails = await this.#
|
|
28
|
+
const deletedMails = await this.#apiClient.mail.deleted.query({
|
|
24
29
|
type: mailType,
|
|
25
30
|
});
|
|
26
31
|
return await Promise.all(deletedMails.map(async (mail) => await convertInternalMailToExternal({
|
|
27
32
|
mail,
|
|
28
|
-
|
|
33
|
+
client: this.#client,
|
|
34
|
+
keyPair: this.#keys,
|
|
29
35
|
})));
|
|
30
36
|
}
|
|
31
37
|
async create(data, customMessage) {
|
|
@@ -37,7 +43,7 @@ export class SecrecyMailClient {
|
|
|
37
43
|
return { ...mail, type: 'sent' };
|
|
38
44
|
}
|
|
39
45
|
async waitingReceivedMails() {
|
|
40
|
-
const waitingReceivedMails = await this.#
|
|
46
|
+
const waitingReceivedMails = await this.#apiClient.mail.waitingReceived.query({});
|
|
41
47
|
const waitingReceivedMailsWithIds = waitingReceivedMails.map((mail) => ({
|
|
42
48
|
id: Math.random().toString(36).substring(2, 9),
|
|
43
49
|
sender: mail.sender,
|
|
@@ -73,18 +79,18 @@ export class SecrecyMailClient {
|
|
|
73
79
|
throw new Error(`File ${f.name} (${f.id}) does not exists`);
|
|
74
80
|
}
|
|
75
81
|
}
|
|
76
|
-
f.name = sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), this.#
|
|
82
|
+
f.name = sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), this.#keys.publicKey, this.#keys.privateKey));
|
|
77
83
|
}
|
|
78
84
|
}
|
|
79
|
-
const updateDraftMail = await this.#
|
|
85
|
+
const updateDraftMail = await this.#apiClient.mail.updateDraft.mutate({
|
|
80
86
|
id: draftId,
|
|
81
87
|
recipients: recipients ?? null,
|
|
82
88
|
replyToId: replyToId ?? null,
|
|
83
89
|
body: body !== undefined
|
|
84
|
-
? sodium.to_hex(encryptCryptoBox(sodium.from_string(body), this.#
|
|
90
|
+
? sodium.to_hex(encryptCryptoBox(sodium.from_string(body), this.#keys.publicKey, this.#keys.privateKey))
|
|
85
91
|
: null,
|
|
86
92
|
subject: subject !== undefined
|
|
87
|
-
? sodium.to_hex(encryptCryptoBox(sodium.from_string(subject), this.#
|
|
93
|
+
? sodium.to_hex(encryptCryptoBox(sodium.from_string(subject), this.#keys.publicKey, this.#keys.privateKey))
|
|
88
94
|
: null,
|
|
89
95
|
senderFiles: senderFiles ?? null,
|
|
90
96
|
hash,
|
|
@@ -92,27 +98,28 @@ export class SecrecyMailClient {
|
|
|
92
98
|
});
|
|
93
99
|
return (await convertInternalMailToExternal({
|
|
94
100
|
mail: updateDraftMail,
|
|
95
|
-
|
|
101
|
+
client: this.#client,
|
|
102
|
+
keyPair: this.#keys,
|
|
96
103
|
}));
|
|
97
104
|
}
|
|
98
105
|
async deleteDraft(draftId) {
|
|
99
|
-
const { isDeleted } = await this.#
|
|
106
|
+
const { isDeleted } = await this.#apiClient.mail.deleteDraft.mutate({
|
|
100
107
|
id: draftId,
|
|
101
108
|
});
|
|
102
109
|
return isDeleted;
|
|
103
110
|
}
|
|
104
111
|
async deleteTrash({ ids }) {
|
|
105
|
-
const { isDeleted } = await this.#
|
|
112
|
+
const { isDeleted } = await this.#apiClient.mail.deleteTrash.mutate({
|
|
106
113
|
ids,
|
|
107
114
|
});
|
|
108
115
|
return isDeleted;
|
|
109
116
|
}
|
|
110
117
|
async emptyTrash() {
|
|
111
|
-
const { isDeleted } = await this.#
|
|
118
|
+
const { isDeleted } = await this.#apiClient.mail.emptyTrash.mutate({});
|
|
112
119
|
return isDeleted;
|
|
113
120
|
}
|
|
114
121
|
async delete({ mailId }) {
|
|
115
|
-
const { isDeleted } = await this.#
|
|
122
|
+
const { isDeleted } = await this.#apiClient.mail.delete.mutate({
|
|
116
123
|
id: mailId,
|
|
117
124
|
});
|
|
118
125
|
return isDeleted;
|
|
@@ -146,7 +153,7 @@ export class SecrecyMailClient {
|
|
|
146
153
|
recipients.push(input);
|
|
147
154
|
}
|
|
148
155
|
}
|
|
149
|
-
const { isSent } = await this.#
|
|
156
|
+
const { isSent } = await this.#apiClient.mail.sendDraft.mutate({
|
|
150
157
|
temporaryRecipients,
|
|
151
158
|
recipients,
|
|
152
159
|
id: draft.mailIntegrityId,
|
|
@@ -168,11 +175,10 @@ export class SecrecyMailClient {
|
|
|
168
175
|
if (input === null) {
|
|
169
176
|
continue;
|
|
170
177
|
}
|
|
171
|
-
await this.#
|
|
178
|
+
await this.#apiClient.mail.sendOne.mutate({
|
|
172
179
|
id: mail.mailIntegrityId,
|
|
173
180
|
recipient: {
|
|
174
181
|
...input,
|
|
175
|
-
recipientPublicKey: input.recipientPubKey,
|
|
176
182
|
attachments: input.attachments.map((attachment) => ({
|
|
177
183
|
id: attachment.dataId,
|
|
178
184
|
key: attachment.key,
|
|
@@ -201,58 +207,62 @@ export class SecrecyMailClient {
|
|
|
201
207
|
}
|
|
202
208
|
senderFiles.push({
|
|
203
209
|
id: data.id,
|
|
204
|
-
name: sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), this.#
|
|
210
|
+
name: sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), this.#keys.publicKey, this.#keys.privateKey)),
|
|
205
211
|
});
|
|
206
212
|
}
|
|
207
|
-
const createDraftMail = await this.#
|
|
213
|
+
const createDraftMail = await this.#apiClient.mail.createDraft.mutate({
|
|
208
214
|
recipients,
|
|
209
215
|
replyToId,
|
|
210
|
-
body: sodium.to_hex(encryptCryptoBox(sodium.from_string(body), this.#
|
|
211
|
-
subject: sodium.to_hex(encryptCryptoBox(sodium.from_string(subject), this.#
|
|
216
|
+
body: sodium.to_hex(encryptCryptoBox(sodium.from_string(body), this.#keys.publicKey, this.#keys.privateKey)),
|
|
217
|
+
subject: sodium.to_hex(encryptCryptoBox(sodium.from_string(subject), this.#keys.publicKey, this.#keys.privateKey)),
|
|
212
218
|
senderFiles,
|
|
213
219
|
hash,
|
|
214
220
|
hashKey,
|
|
215
221
|
});
|
|
216
222
|
return (await convertInternalMailToExternal({
|
|
217
223
|
mail: createDraftMail,
|
|
218
|
-
|
|
224
|
+
client: this.#client,
|
|
225
|
+
keyPair: this.#keys,
|
|
219
226
|
}));
|
|
220
227
|
}
|
|
221
228
|
async read({ mailId }) {
|
|
222
|
-
const { isRead } = await this.#
|
|
229
|
+
const { isRead } = await this.#apiClient.mail.read.mutate({
|
|
223
230
|
id: mailId,
|
|
224
231
|
});
|
|
225
232
|
return isRead;
|
|
226
233
|
}
|
|
227
234
|
async unread({ mailId }) {
|
|
228
|
-
const { isUnread } = await this.#
|
|
235
|
+
const { isUnread } = await this.#apiClient.mail.unread.mutate({
|
|
229
236
|
id: mailId,
|
|
230
237
|
});
|
|
231
238
|
return isUnread;
|
|
232
239
|
}
|
|
233
240
|
async receivedMails(input) {
|
|
234
|
-
const receivedMails = await this.#
|
|
241
|
+
const receivedMails = await this.#apiClient.mail.received.query(input);
|
|
235
242
|
return await Promise.all(receivedMails.map(async (mail) => (await convertInternalMailToExternal({
|
|
236
243
|
mail,
|
|
237
|
-
|
|
244
|
+
client: this.#client,
|
|
245
|
+
keyPair: this.#keys,
|
|
238
246
|
}))));
|
|
239
247
|
}
|
|
240
248
|
async sentMails(input) {
|
|
241
|
-
const sentMails = await this.#
|
|
249
|
+
const sentMails = await this.#apiClient.mail.sent.query(input);
|
|
242
250
|
return await Promise.all(sentMails.map(async (mail) => (await convertInternalMailToExternal({
|
|
243
251
|
mail,
|
|
244
|
-
|
|
252
|
+
client: this.#client,
|
|
253
|
+
keyPair: this.#keys,
|
|
245
254
|
}))));
|
|
246
255
|
}
|
|
247
256
|
async draftMails(input) {
|
|
248
|
-
const draftMails = await this.#
|
|
257
|
+
const draftMails = await this.#apiClient.mail.draft.query(input);
|
|
249
258
|
return await Promise.all(draftMails.map(async (mail) => (await convertInternalMailToExternal({
|
|
250
259
|
mail,
|
|
251
|
-
|
|
260
|
+
client: this.#client,
|
|
261
|
+
keyPair: this.#keys,
|
|
252
262
|
}))));
|
|
253
263
|
}
|
|
254
264
|
async unreadReceivedMailsCount() {
|
|
255
|
-
const unreadReceivedMailsCount = await this.#
|
|
265
|
+
const unreadReceivedMailsCount = await this.#apiClient.mail.unreadReceivedCount.query({});
|
|
256
266
|
return unreadReceivedMailsCount;
|
|
257
267
|
}
|
|
258
268
|
_eachUser = async (data, subject, body, idOrMail) => {
|
|
@@ -272,17 +282,17 @@ export class SecrecyMailClient {
|
|
|
272
282
|
const key = dataInHistory.key;
|
|
273
283
|
attachments.push({
|
|
274
284
|
dataId: f.id,
|
|
275
|
-
name: sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), pubKey, this.#
|
|
285
|
+
name: sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), pubKey, this.#keys.privateKey)),
|
|
276
286
|
key: key
|
|
277
|
-
? sodium.to_hex(encryptCryptoBox(sodium.from_hex(key), pubKey, this.#
|
|
287
|
+
? sodium.to_hex(encryptCryptoBox(sodium.from_hex(key), pubKey, this.#keys.privateKey))
|
|
278
288
|
: null,
|
|
279
289
|
});
|
|
280
290
|
}
|
|
281
291
|
return {
|
|
282
292
|
// recipientId: userId,
|
|
283
|
-
|
|
284
|
-
body: sodium.to_hex(encryptCryptoBox(sodium.from_string(body), pubKey, this.#
|
|
285
|
-
subject: sodium.to_hex(encryptCryptoBox(sodium.from_string(subject), pubKey, this.#
|
|
293
|
+
recipientId: idOrMail,
|
|
294
|
+
body: sodium.to_hex(encryptCryptoBox(sodium.from_string(body), pubKey, this.#keys.privateKey)),
|
|
295
|
+
subject: sodium.to_hex(encryptCryptoBox(sodium.from_string(subject), pubKey, this.#keys.privateKey)),
|
|
286
296
|
attachments,
|
|
287
297
|
};
|
|
288
298
|
};
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
export class SecrecyOrganizationClient {
|
|
2
|
-
#client
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
// readonly #client: SecrecyClient
|
|
3
|
+
#apiClient;
|
|
4
|
+
constructor(_client, _keys, apiClient) {
|
|
5
|
+
// this.#client = client
|
|
6
|
+
this.#apiClient = apiClient;
|
|
5
7
|
}
|
|
6
8
|
async create(input) {
|
|
7
|
-
return this.#
|
|
9
|
+
return this.#apiClient.org.create.mutate(input);
|
|
8
10
|
}
|
|
9
11
|
async update(input) {
|
|
10
|
-
return this.#
|
|
12
|
+
return this.#apiClient.org.update.mutate(input);
|
|
11
13
|
}
|
|
12
14
|
async addMember(input) {
|
|
13
|
-
return this.#
|
|
15
|
+
return this.#apiClient.org.addMember.mutate(input);
|
|
14
16
|
}
|
|
15
17
|
async removeMember(input) {
|
|
16
|
-
return this.#
|
|
18
|
+
return this.#apiClient.org.removeMember.mutate(input);
|
|
17
19
|
}
|
|
18
20
|
async updateRole(input) {
|
|
19
|
-
return this.#
|
|
21
|
+
return this.#apiClient.org.updateRole.mutate(input);
|
|
20
22
|
}
|
|
21
23
|
async list(input) {
|
|
22
|
-
return this.#
|
|
24
|
+
return this.#apiClient.org.list.query(input);
|
|
23
25
|
}
|
|
24
26
|
async plans(input) {
|
|
25
|
-
return this.#
|
|
27
|
+
return this.#apiClient.org.plans.query(input);
|
|
26
28
|
}
|
|
27
29
|
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { popup } from '../utils/popup-tools.js';
|
|
2
2
|
export class SecrecyPayClient {
|
|
3
3
|
#client;
|
|
4
|
-
|
|
4
|
+
// #keys: KeyPair
|
|
5
|
+
// #apiClient: ApiClient
|
|
6
|
+
constructor(client, _keys, _apiClient) {
|
|
5
7
|
this.#client = client;
|
|
8
|
+
// this.#keys = keys
|
|
9
|
+
// this.#apiClient = apiClient
|
|
6
10
|
}
|
|
7
11
|
async confirmPaymentIntent({ paymentIntentId, secrecyIdWhoCreatedPaymentIntent, secrecyIdWhoNeedToConfirmPaymentIntent, amount, currency, }) {
|
|
8
12
|
const hash = Buffer.from(JSON.stringify({
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
export class SecrecyPseudonymClient {
|
|
2
2
|
#client;
|
|
3
|
-
|
|
3
|
+
#keys;
|
|
4
|
+
#apiClient;
|
|
5
|
+
constructor(client, keys, apiClient) {
|
|
4
6
|
this.#client = client;
|
|
7
|
+
this.#keys = keys;
|
|
8
|
+
this.#apiClient = apiClient;
|
|
5
9
|
}
|
|
6
10
|
async askForLabel(input) {
|
|
7
|
-
return await this.#
|
|
11
|
+
return await this.#apiClient.pseudonym.askForLabel.query(input);
|
|
8
12
|
}
|
|
9
13
|
async askForUser(input) {
|
|
10
|
-
return await this.#
|
|
14
|
+
return await this.#apiClient.pseudonym.askForUser.query(input);
|
|
11
15
|
}
|
|
12
16
|
async cross(input) {
|
|
13
|
-
return await this.#
|
|
17
|
+
return await this.#apiClient.pseudonym.cross.query(input);
|
|
14
18
|
}
|
|
15
19
|
}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
export class SecrecyUserClient {
|
|
2
|
-
#
|
|
3
|
-
constructor(
|
|
4
|
-
this.#
|
|
2
|
+
#apiClient;
|
|
3
|
+
constructor(_client, _keys, apiClient) {
|
|
4
|
+
this.#apiClient = apiClient;
|
|
5
5
|
}
|
|
6
6
|
async answerInvitation(input) {
|
|
7
|
-
return await this.#
|
|
7
|
+
return await this.#apiClient.contacts.answerInvitation.mutate(input);
|
|
8
8
|
}
|
|
9
9
|
async cancelInvitation(input) {
|
|
10
|
-
return await this.#
|
|
10
|
+
return await this.#apiClient.contacts.cancelInvitation.mutate(input);
|
|
11
11
|
}
|
|
12
12
|
async createInvitation(input) {
|
|
13
|
-
return await this.#
|
|
13
|
+
return await this.#apiClient.contacts.createInvitation.mutate(input);
|
|
14
14
|
}
|
|
15
15
|
async getContacts(input) {
|
|
16
|
-
return await this.#
|
|
16
|
+
return await this.#apiClient.contacts.getContacts.query(input);
|
|
17
17
|
}
|
|
18
18
|
async getReceivedInvitations(input) {
|
|
19
|
-
return await this.#
|
|
19
|
+
return await this.#apiClient.contacts.getReceivedInvitations.query(input);
|
|
20
20
|
}
|
|
21
21
|
async getSentInvitations(input) {
|
|
22
|
-
return await this.#
|
|
22
|
+
return await this.#apiClient.contacts.getSentInvitations.query(input);
|
|
23
23
|
}
|
|
24
24
|
async removeContact(input) {
|
|
25
|
-
return await this.#
|
|
25
|
+
return await this.#apiClient.contacts.removeContact.mutate(input);
|
|
26
26
|
}
|
|
27
27
|
async getUsers(input) {
|
|
28
|
-
return await this.#
|
|
28
|
+
return await this.#apiClient.account.getUsers.query(input);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { popup } from '../utils/popup-tools.js';
|
|
2
2
|
export class SecrecyWalletClient {
|
|
3
3
|
#client;
|
|
4
|
+
// #keys: KeyPair;
|
|
4
5
|
// #thunder: ReturnType<typeof Thunder>;
|
|
5
6
|
constructor(client) {
|
|
6
7
|
this.#client = client;
|
|
8
|
+
// this.#keys = keys;
|
|
7
9
|
// this.#thunder = thunder;
|
|
8
10
|
}
|
|
9
11
|
async createTransaction({ network = 'mainnet', tx, }) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { dataCache } from '../../cache.js';
|
|
2
2
|
import { decryptCryptoBox } from '../../crypto/index.js';
|
|
3
3
|
import { sodium } from '../../sodium.js';
|
|
4
|
-
export function apiDataToInternal(apiData,
|
|
4
|
+
export function apiDataToInternal(apiData, keyPair) {
|
|
5
5
|
const data = {
|
|
6
6
|
id: apiData.id,
|
|
7
7
|
md5: apiData.md5,
|
|
@@ -10,7 +10,7 @@ export function apiDataToInternal(apiData, keyPairs) {
|
|
|
10
10
|
size: apiData.size,
|
|
11
11
|
sizeEncrypted: apiData.sizeEncrypted,
|
|
12
12
|
key: apiData.access.key
|
|
13
|
-
? sodium.to_hex(decryptCryptoBox(sodium.from_hex(apiData.access.key), apiData.access.sharedByPubKey,
|
|
13
|
+
? sodium.to_hex(decryptCryptoBox(sodium.from_hex(apiData.access.key), apiData.access.sharedByPubKey, keyPair.privateKey))
|
|
14
14
|
: null,
|
|
15
15
|
mime: apiData.mime ?? undefined,
|
|
16
16
|
ext: apiData.ext ?? undefined,
|
|
@@ -30,6 +30,6 @@ export function internalDataToExternalData(internal) {
|
|
|
30
30
|
ext: internal.ext ?? undefined,
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
-
export function apiDataToExternal(apiData,
|
|
34
|
-
return internalDataToExternalData(apiDataToInternal(apiData,
|
|
33
|
+
export function apiDataToExternal(apiData, keyPair) {
|
|
34
|
+
return internalDataToExternalData(apiDataToInternal(apiData, keyPair));
|
|
35
35
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { sodium, decryptCryptoBox } from '../../index.js';
|
|
2
|
-
export async function convertInternalMailToExternal({ mail,
|
|
1
|
+
import { sodium, decryptCryptoBox, } from '../../index.js';
|
|
2
|
+
export async function convertInternalMailToExternal({ client, mail, keyPair, }) {
|
|
3
3
|
let type = mail.type;
|
|
4
4
|
if (mail.mailIntegrityDraft !== null) {
|
|
5
5
|
type = 'draft';
|
|
@@ -8,8 +8,10 @@ export async function convertInternalMailToExternal({ mail, keyPairs, }) {
|
|
|
8
8
|
if (mI === null) {
|
|
9
9
|
throw new Error('Mail integrity is null');
|
|
10
10
|
}
|
|
11
|
-
const pubKey = mail.
|
|
12
|
-
|
|
11
|
+
const pubKey = mail.type === 'received'
|
|
12
|
+
? await client.app.userPublicKey(mail.sender.id)
|
|
13
|
+
: keyPair.publicKey;
|
|
14
|
+
const privateKey = keyPair.privateKey;
|
|
13
15
|
const body = sodium.to_string(decryptCryptoBox(sodium.from_hex(mail.body), pubKey, privateKey));
|
|
14
16
|
const subject = sodium.to_string(decryptCryptoBox(sodium.from_hex(mail.subject), pubKey, privateKey));
|
|
15
17
|
const hash = sodium.crypto_generichash(sodium.crypto_generichash_BYTES, JSON.stringify({ body, subject }), mI.hashKey, 'hex');
|
|
@@ -28,7 +30,6 @@ export async function convertInternalMailToExternal({ mail, keyPairs, }) {
|
|
|
28
30
|
temporaryRecipients: [], // TODO
|
|
29
31
|
recipients: mI.recipients,
|
|
30
32
|
sender: mail.sender,
|
|
31
|
-
senderPublicKey: mail.senderPubKey,
|
|
32
33
|
attachments: mail.attachments.map((f) => {
|
|
33
34
|
const name = sodium.to_string(decryptCryptoBox(sodium.from_hex(f.name), pubKey, privateKey));
|
|
34
35
|
return {
|
|
@@ -3,11 +3,11 @@ import { decryptCryptoBox } from '../../crypto/index.js';
|
|
|
3
3
|
import { nodesCache, nodesEncryptionCache } from '../../cache.js';
|
|
4
4
|
import { decryptSecretStream } from '../../crypto/data.js';
|
|
5
5
|
import { apiDataToInternal, internalDataToExternalData } from './data.js';
|
|
6
|
-
async function apiNodeToInternal(apiNode,
|
|
6
|
+
async function apiNodeToInternal(apiNode, keyPair) {
|
|
7
7
|
const internal = {
|
|
8
8
|
id: apiNode.id,
|
|
9
9
|
type: apiNode.type,
|
|
10
|
-
|
|
10
|
+
access: apiNode.access,
|
|
11
11
|
name: apiNode.name,
|
|
12
12
|
isFavorite: apiNode.isFavorite,
|
|
13
13
|
breadcrumb: 'breadcrumb' in apiNode ? apiNode.breadcrumb : [],
|
|
@@ -21,48 +21,38 @@ async function apiNodeToInternal(apiNode, keyPairs) {
|
|
|
21
21
|
createdAt: apiNode.createdAt,
|
|
22
22
|
updatedAt: apiNode.updatedAt,
|
|
23
23
|
deletedAt: apiNode.deletedAt,
|
|
24
|
-
|
|
25
|
-
permissions: apiNode.permissions,
|
|
24
|
+
users: apiNode.users,
|
|
26
25
|
parentId: apiNode.parentId ?? null,
|
|
27
26
|
currentDataId: apiNode.currentDataId ?? null,
|
|
28
27
|
};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const pk = keyPairs[access.identityPubKey];
|
|
34
|
-
const key = decryptCryptoBox(sodium.from_hex(access.nameKey), access.sharedByPubKey, pk);
|
|
35
|
-
access.nameKey = sodium.to_hex(key);
|
|
36
|
-
}
|
|
37
|
-
const firstAccess = internal.accesses[0];
|
|
38
|
-
if (!firstAccess || firstAccess.nameKey === null) {
|
|
39
|
-
throw new Error('No access found for node ' + internal.id);
|
|
28
|
+
if (apiNode.access.nameKey !== null) {
|
|
29
|
+
const key = decryptCryptoBox(sodium.from_hex(apiNode.access.nameKey), apiNode.access.sharedByPubKey, keyPair.privateKey);
|
|
30
|
+
internal.name = sodium.to_string(await decryptSecretStream(key, sodium.from_hex(internal.name)));
|
|
31
|
+
internal.access.nameKey = sodium.to_hex(key);
|
|
40
32
|
}
|
|
41
|
-
internal.name = sodium.to_string(await decryptSecretStream(sodium.from_hex(firstAccess.nameKey), sodium.from_hex(internal.name)));
|
|
42
33
|
for (const b of internal.breadcrumb) {
|
|
43
34
|
if (b.nameKey === null) {
|
|
44
35
|
continue;
|
|
45
36
|
}
|
|
46
|
-
const
|
|
47
|
-
const key = decryptCryptoBox(sodium.from_hex(b.nameKey), b.sharedByPubKey, pk);
|
|
37
|
+
const key = decryptCryptoBox(sodium.from_hex(b.nameKey), b.pubKey, keyPair.privateKey);
|
|
48
38
|
b.nameKey = sodium.to_hex(key);
|
|
49
39
|
b.name = sodium.to_string(await decryptSecretStream(key, sodium.from_hex(b.name)));
|
|
50
40
|
}
|
|
51
41
|
nodesCache.set(internal.id, internal);
|
|
52
42
|
return internal;
|
|
53
43
|
}
|
|
54
|
-
export async function apiNodeFullToInternalFull(apiNodeFull,
|
|
55
|
-
const f = await apiNodeToInternal(apiNodeFull,
|
|
44
|
+
export async function apiNodeFullToInternalFull(apiNodeFull, keyPair) {
|
|
45
|
+
const f = await apiNodeToInternal(apiNodeFull, keyPair);
|
|
56
46
|
const nodeFull = {
|
|
57
47
|
...f,
|
|
58
48
|
current: !!apiNodeFull.current
|
|
59
|
-
? apiDataToInternal(apiNodeFull.current,
|
|
49
|
+
? apiDataToInternal(apiNodeFull.current, keyPair)
|
|
60
50
|
: undefined,
|
|
61
51
|
parent: apiNodeFull.parent !== null
|
|
62
|
-
? await apiNodeToInternal(apiNodeFull.parent,
|
|
52
|
+
? await apiNodeToInternal(apiNodeFull.parent, keyPair)
|
|
63
53
|
: null,
|
|
64
|
-
children: await Promise.all(apiNodeFull.children.map(async (s) => await apiNodeToInternal(s,
|
|
65
|
-
history: apiNodeFull.history.map((f) => apiDataToInternal(f,
|
|
54
|
+
children: await Promise.all(apiNodeFull.children.map(async (s) => await apiNodeToInternal(s, keyPair))),
|
|
55
|
+
history: apiNodeFull.history.map((f) => apiDataToInternal(f, keyPair)),
|
|
66
56
|
};
|
|
67
57
|
nodesCache.set(f.id, nodeFull);
|
|
68
58
|
return nodeFull;
|
|
@@ -70,19 +60,19 @@ export async function apiNodeFullToInternalFull(apiNodeFull, keyPairs) {
|
|
|
70
60
|
function internalNodeToNode(internal) {
|
|
71
61
|
const node = {
|
|
72
62
|
...internal,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
63
|
+
breadcrumb: internal.breadcrumb.map((b) => ({
|
|
64
|
+
id: b.id,
|
|
65
|
+
name: b.name,
|
|
66
|
+
})),
|
|
67
|
+
access: {
|
|
68
|
+
isRoot: internal.access.isRoot,
|
|
69
|
+
sharedByPubKey: internal.access.sharedByPubKey,
|
|
70
|
+
rights: internal.access.rights,
|
|
71
|
+
addAccess: internal.access.addAccess,
|
|
72
|
+
delAccess: internal.access.delAccess,
|
|
73
|
+
sharingAddAccess: internal.access.sharingAddAccess,
|
|
74
|
+
sharingDelAccess: internal.access.sharingDelAccess,
|
|
75
|
+
},
|
|
86
76
|
};
|
|
87
77
|
return node;
|
|
88
78
|
}
|
|
@@ -97,18 +87,17 @@ export function internalNodeFullToNodeFull(internal) {
|
|
|
97
87
|
: undefined,
|
|
98
88
|
};
|
|
99
89
|
}
|
|
100
|
-
export async function apiNodeToExternalNodeFull(apiNodeFull,
|
|
101
|
-
const apiNode = await apiNodeFullToInternalFull(apiNodeFull,
|
|
90
|
+
export async function apiNodeToExternalNodeFull(apiNodeFull, keyPair) {
|
|
91
|
+
const apiNode = await apiNodeFullToInternalFull(apiNodeFull, keyPair);
|
|
102
92
|
return internalNodeFullToNodeFull(apiNode);
|
|
103
93
|
}
|
|
104
|
-
export async function apiNodeToExternal(apiNode,
|
|
105
|
-
const internal = await apiNodeToInternal(apiNode,
|
|
94
|
+
export async function apiNodeToExternal(apiNode, keyPair) {
|
|
95
|
+
const internal = await apiNodeToInternal(apiNode, keyPair);
|
|
106
96
|
return internalNodeToNode(internal);
|
|
107
97
|
}
|
|
108
|
-
export async function apiNodeForEncryptionToInternal(apiNode,
|
|
98
|
+
export async function apiNodeForEncryptionToInternal(apiNode, keyPair) {
|
|
109
99
|
const history = apiNode.history.map((history) => {
|
|
110
|
-
const
|
|
111
|
-
const key = decryptCryptoBox(sodium.from_hex(history.access.key), history.access.sharedByPublicKey, pk);
|
|
100
|
+
const key = decryptCryptoBox(sodium.from_hex(history.access.key), history.access.sharedByPublicKey, keyPair.privateKey);
|
|
112
101
|
return {
|
|
113
102
|
id: history.id,
|
|
114
103
|
key: sodium.to_hex(key),
|
|
@@ -123,8 +112,7 @@ export async function apiNodeForEncryptionToInternal(apiNode, keyPairs) {
|
|
|
123
112
|
};
|
|
124
113
|
internal.access = { ...apiNode.access };
|
|
125
114
|
if (apiNode.access.nameKey !== null) {
|
|
126
|
-
const
|
|
127
|
-
const key = decryptCryptoBox(sodium.from_hex(apiNode.access.nameKey), apiNode.access.sharedByPublicKey, pk);
|
|
115
|
+
const key = decryptCryptoBox(sodium.from_hex(apiNode.access.nameKey), apiNode.access.sharedByPublicKey, keyPair.privateKey);
|
|
128
116
|
internal.name = sodium.to_string(await decryptSecretStream(key, sodium.from_hex(internal.name)));
|
|
129
117
|
internal.access.nameKey = sodium.to_hex(key);
|
|
130
118
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { buildBytesFromDataLink } from '../crypto/domain';
|
|
3
|
+
import { sodium } from '../sodium';
|
|
4
|
+
import { derivePassword } from '../crypto/helpers';
|
|
5
|
+
import { decryptSecretBox } from '../crypto';
|
|
6
|
+
import { decrypt } from '../worker/sodium';
|
|
7
|
+
import { md5 } from '../worker/md5';
|
|
8
|
+
import { decompress } from '../minify';
|
|
9
|
+
const downloadDataLinkS3Schema = z.object({
|
|
10
|
+
name: z.string(),
|
|
11
|
+
md5: z.string(),
|
|
12
|
+
md5Encrypted: z.string().nullable(),
|
|
13
|
+
size: z.coerce.bigint().gte(0n),
|
|
14
|
+
parts: z.array(z.object({ order: z.number(), md5: z.string(), contentUrl: z.string() })),
|
|
15
|
+
mime: z.string(),
|
|
16
|
+
isEncrypted: z.boolean(),
|
|
17
|
+
});
|
|
18
|
+
const downloadDataLinkLiteSchema = z.object({
|
|
19
|
+
name: z.string(),
|
|
20
|
+
md5: z.string(),
|
|
21
|
+
md5Encrypted: z.string().nullable(),
|
|
22
|
+
size: z.coerce.bigint().gte(0n),
|
|
23
|
+
bytes: z.string(),
|
|
24
|
+
mime: z.string(),
|
|
25
|
+
isEncrypted: z.boolean(),
|
|
26
|
+
});
|
|
27
|
+
export const downloadDataLinkSchema = z.union([
|
|
28
|
+
downloadDataLinkS3Schema,
|
|
29
|
+
downloadDataLinkLiteSchema,
|
|
30
|
+
]);
|
|
31
|
+
// TODO: Add an opt header for authed users!
|
|
32
|
+
export async function downloadDataFromLink(opts) {
|
|
33
|
+
let dataUrl = opts.dataUrl ?? 'https://data.secrecy.tech/';
|
|
34
|
+
dataUrl = dataUrl.endsWith('/') ? dataUrl : `${dataUrl}/`;
|
|
35
|
+
const rawDataLink = await fetch(`${dataUrl}${opts.dataLinkSlug}/json`)
|
|
36
|
+
.then((res) => res.json())
|
|
37
|
+
.catch((err) => {
|
|
38
|
+
throw new Error(`Unable to fetch "${`${dataUrl}${opts.dataLinkSlug}/json"`}`, { cause: err });
|
|
39
|
+
});
|
|
40
|
+
const dataLink = downloadDataLinkSchema.safeParse(rawDataLink);
|
|
41
|
+
if (dataLink.error) {
|
|
42
|
+
throw new Error(`Should not happen!`, { cause: dataLink.error });
|
|
43
|
+
}
|
|
44
|
+
if (dataLink.data.isEncrypted && !opts.crypto) {
|
|
45
|
+
throw new Error('Unable to read encrypted data without password!');
|
|
46
|
+
}
|
|
47
|
+
const bytes = await buildBytesFromDataLink({
|
|
48
|
+
dataLink: dataLink.data,
|
|
49
|
+
totalBytes: Number(dataLink.data.size),
|
|
50
|
+
signal: opts.signal,
|
|
51
|
+
onDownloadProgress: opts.downloadProgress,
|
|
52
|
+
});
|
|
53
|
+
if (!dataLink.data.isEncrypted) {
|
|
54
|
+
return bytes;
|
|
55
|
+
}
|
|
56
|
+
if (!opts.crypto) {
|
|
57
|
+
throw new Error('Unable to read encrypted data without password!');
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const salt = sodium.crypto_generichash(sodium.crypto_pwhash_SALTBYTES, opts.crypto.password + dataLink.data.md5);
|
|
61
|
+
const derivedPassword = derivePassword(opts.crypto.password, salt);
|
|
62
|
+
const decryptedSharingDataKey = decryptSecretBox(sodium.from_hex(opts.crypto.key), derivedPassword);
|
|
63
|
+
const decryptedBytes = await decrypt(decryptedSharingDataKey, bytes, opts.decryptProgress, opts.signal);
|
|
64
|
+
const md5Content = await md5(decryptedBytes);
|
|
65
|
+
if (md5Content !== dataLink.data.md5) {
|
|
66
|
+
throw new Error(`Content does not match`);
|
|
67
|
+
}
|
|
68
|
+
return decompress(decryptedBytes);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
console.error(err);
|
|
72
|
+
if (opts.crypto.password) {
|
|
73
|
+
throw new Error('Unable to decrypt the data! The password is not valid!');
|
|
74
|
+
}
|
|
75
|
+
throw new Error('Unable to decrypt the data!');
|
|
76
|
+
}
|
|
77
|
+
}
|