@secrecy/lib 1.74.6 → 1.75.0-feat-groups-identity.2

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.
Files changed (54) hide show
  1. package/dist/lib/base-client.js +26 -2
  2. package/dist/lib/client/SecrecyAppClient.js +14 -18
  3. package/dist/lib/client/SecrecyCloudClient.js +130 -135
  4. package/dist/lib/client/SecrecyDbClient.js +1 -8
  5. package/dist/lib/client/SecrecyMailClient.js +38 -48
  6. package/dist/lib/client/SecrecyOrganizationClient.js +10 -12
  7. package/dist/lib/client/SecrecyPayClient.js +1 -5
  8. package/dist/lib/client/SecrecyPseudonymClient.js +4 -8
  9. package/dist/lib/client/SecrecyUserClient.js +11 -11
  10. package/dist/lib/client/SecrecyWalletClient.js +0 -2
  11. package/dist/lib/client/convert/data.js +8 -4
  12. package/dist/lib/client/convert/mail.js +8 -6
  13. package/dist/lib/client/convert/node.js +59 -34
  14. package/dist/lib/client/data-link.js +4 -1
  15. package/dist/lib/client/helpers.js +17 -7
  16. package/dist/lib/client/index.js +48 -12
  17. package/dist/lib/client/storage.js +3 -2
  18. package/dist/lib/client/types/identity.js +19 -0
  19. package/dist/lib/client/types/index.js +3 -7
  20. package/dist/lib/client/upload.js +20 -17
  21. package/dist/lib/crypto/data.js +4 -4
  22. package/dist/lib/crypto/domain.js +10 -10
  23. package/dist/lib/index.js +1 -0
  24. package/dist/lib/minify/lz4.js +1 -0
  25. package/dist/lib/utils/links.js +5 -5
  26. package/dist/lib/utils.js +1 -1
  27. package/dist/lib/worker/sodium.js +2 -2
  28. package/dist/types/base-client.d.ts +3 -1
  29. package/dist/types/client/SecrecyAppClient.d.ts +2 -3
  30. package/dist/types/client/SecrecyCloudClient.d.ts +19 -19
  31. package/dist/types/client/SecrecyDbClient.d.ts +1 -4
  32. package/dist/types/client/SecrecyMailClient.d.ts +2 -3
  33. package/dist/types/client/SecrecyOrganizationClient.d.ts +2 -3
  34. package/dist/types/client/SecrecyPayClient.d.ts +1 -3
  35. package/dist/types/client/SecrecyPseudonymClient.d.ts +2 -3
  36. package/dist/types/client/SecrecyUserClient.d.ts +2 -3
  37. package/dist/types/client/convert/data.d.ts +3 -3
  38. package/dist/types/client/convert/mail.d.ts +3 -5
  39. package/dist/types/client/convert/node.d.ts +5 -5
  40. package/dist/types/client/data-link.d.ts +2 -2
  41. package/dist/types/client/index.d.ts +11 -3
  42. package/dist/types/client/storage.d.ts +3 -2
  43. package/dist/types/client/types/identity.d.ts +37 -0
  44. package/dist/types/client/types/index.d.ts +17 -9
  45. package/dist/types/client/types/mail.d.ts +2 -1
  46. package/dist/types/client/types/node.d.ts +12 -9
  47. package/dist/types/client/types/user.d.ts +15 -0
  48. package/dist/types/client/upload.d.ts +8 -7
  49. package/dist/types/client.d.ts +1438 -1050
  50. package/dist/types/crypto/data.d.ts +2 -2
  51. package/dist/types/crypto/domain.d.ts +6 -4
  52. package/dist/types/crypto/index.d.ts +3 -3
  53. package/dist/types/index.d.ts +2 -1
  54. package/package.json +21 -21
@@ -8,41 +8,32 @@ import { apiDataToExternal, apiDataToInternal } from './convert/data.js';
8
8
  import { apiNodeForEncryptionToInternal, apiNodeFullToInternalFull, apiNodeToExternal, apiNodeToExternalNodeFull, internalNodeFullToNodeFull, } from './convert/node.js';
9
9
  import { buildBytesFromApiData } from '../crypto/domain.js';
10
10
  import { chunkByTotalItems } from '../utils/object.js';
11
- import { createPublicDataLink, uploadData } from './upload.js';
11
+ import { uploadData } from './upload.js';
12
12
  import { encryptName, generateAndEncryptNameAndKey } from '../crypto/helpers.js';
13
13
  import { downloadDataFromLink, } from './data-link.js';
14
14
  export class SecrecyCloudClient {
15
15
  #client;
16
- #keys;
17
- #apiClient;
18
- constructor(client, keys, apiClient) {
16
+ constructor(client) {
19
17
  this.#client = client;
20
- this.#keys = keys;
21
- this.#apiClient = apiClient;
22
18
  }
23
19
  async addDataToHistory({ dataId, nodeId, }) {
24
- const addDataToHistory = await this.#apiClient.cloud.addDataToHistory.mutate({ dataId, nodeId });
25
- const node = await apiNodeFullToInternalFull(addDataToHistory, this.#keys);
20
+ const addDataToHistory = await this.#client.apiClient.cloud.addDataToHistory.mutate({
21
+ dataId,
22
+ nodeId,
23
+ });
24
+ const node = await apiNodeFullToInternalFull(addDataToHistory, this.#client.keyPairs);
26
25
  const data = node.history.find((d) => d.id === dataId);
27
26
  if (data !== undefined) {
28
- // TODO sad to have to make this extra request
29
- const me = await this.#client.me();
30
- const users = node.users.filter(([u]) => u.id !== me.id);
31
- const userIds = users.map(([user]) => user.id);
32
- const userKeys = await this.#client.app.userPublicKey(userIds);
33
- const shares = users.map(([user]) => {
34
- const publicKey = userKeys[user.id];
35
- if (!publicKey) {
36
- throw new Error('Unable to retrieve share by public key!');
37
- }
27
+ const othersIdentities = Object.entries(node.identities).filter(([id]) => id !== this.#client.uaIdentity.identityPubKey);
28
+ const shares = othersIdentities.map(([publicKey]) => {
38
29
  return {
39
- id: user.id,
30
+ pubKey: publicKey,
40
31
  key: data.key
41
- ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(data.key), publicKey, this.#keys.privateKey))
32
+ ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(data.key), publicKey, this.#client.uaPrivateKey))
42
33
  : null,
43
34
  };
44
35
  });
45
- await this.#apiClient.cloud.shareDataInHistory.mutate({
36
+ await this.#client.apiClient.cloud.shareDataInHistory.mutate({
46
37
  dataId: data.id,
47
38
  nodeId,
48
39
  users: shares,
@@ -53,8 +44,9 @@ export class SecrecyCloudClient {
53
44
  async uploadData(opts) {
54
45
  return uploadData({
55
46
  ...opts,
56
- keyPair: this.#keys,
57
- apiClient: this.#apiClient,
47
+ uaIdentity: this.#client.uaIdentity,
48
+ keyPairs: this.#client.keyPairs,
49
+ apiClient: this.#client.apiClient,
58
50
  });
59
51
  }
60
52
  async uploadDataInCloud({ data, name, nodeId, encryptProgress, uploadProgress, storageType = 's3', signal, }) {
@@ -68,21 +60,21 @@ export class SecrecyCloudClient {
68
60
  return await this.saveInCloud({ dataId: uploadedData.id, name, nodeId });
69
61
  }
70
62
  async deletedNodes() {
71
- const deletedNodes = await this.#apiClient.cloud.nodesDeleted.query({});
72
- return await Promise.all(deletedNodes.map(async (node) => await apiNodeToExternal(node, this.#keys)));
63
+ const deletedNodes = await this.#client.apiClient.cloud.nodesDeleted.query({});
64
+ return await Promise.all(deletedNodes.map(async (node) => await apiNodeToExternal(node, this.#client.keyPairs)));
73
65
  }
74
66
  async sharedNodes() {
75
- const nodesShared = await this.#apiClient.cloud.nodesShared.query();
76
- return await Promise.all(nodesShared.map(async (node) => await apiNodeToExternal(node, this.#keys)));
67
+ const nodesShared = await this.#client.apiClient.cloud.nodesShared.query({});
68
+ return await Promise.all(nodesShared.map(async (node) => await apiNodeToExternal(node, this.#client.keyPairs)));
77
69
  }
78
70
  async nodesSharedWithMe(type = 'FOLDER') {
79
- const nodesSharedWithMe = await this.#apiClient.cloud.nodesSharedWithMe.query({ type });
80
- return await Promise.all(nodesSharedWithMe.map(async (node) => await apiNodeToExternal(node, this.#keys)));
71
+ const nodesSharedWithMe = await this.#client.apiClient.cloud.nodesSharedWithMe.query({ type });
72
+ return await Promise.all(nodesSharedWithMe.map(async (node) => await apiNodeToExternal(node, this.#client.keyPairs)));
81
73
  }
82
- async deleteNodeSharing({ nodeId, userId, }) {
83
- const { isDeleted } = await this.#apiClient.cloud.deleteNodeSharing.mutate({
74
+ async deleteNodeSharing({ nodeId, destPubKey, }) {
75
+ const { isDeleted } = await this.#client.apiClient.cloud.deleteNodeSharing.mutate({
84
76
  nodeId,
85
- userId,
77
+ destPubKey,
86
78
  });
87
79
  return isDeleted;
88
80
  }
@@ -95,14 +87,14 @@ export class SecrecyCloudClient {
95
87
  throw new Error(`Node (${nodeId}) does not exists`);
96
88
  }
97
89
  }
98
- if (node.access?.nameKey === undefined) {
99
- throw new Error(`Can't have access to node ${nodeId}`);
90
+ if (!node.accesses[0]) {
91
+ throw new Error(`No access found for node ${nodeId}`);
100
92
  }
101
93
  name =
102
- typeof name === 'string' && node.access.nameKey !== null
103
- ? await encryptName(name, node.access.nameKey)
94
+ typeof name === 'string' && node.accesses[0].nameKey !== null
95
+ ? await encryptName(name, node.accesses[0].nameKey)
104
96
  : null;
105
- const { isDuplicated } = await this.#apiClient.cloud.duplicateNode.mutate({
97
+ const { isDuplicated } = await this.#client.apiClient.cloud.duplicateNode.mutate({
106
98
  nodeId,
107
99
  folderId: folderId ?? null,
108
100
  name,
@@ -110,50 +102,54 @@ export class SecrecyCloudClient {
110
102
  return isDuplicated;
111
103
  }
112
104
  async deleteNodeCloudTrash({ ids }) {
113
- const { isDeleted } = await this.#apiClient.cloud.deleteNodeCloudTrash.mutate({ ids });
105
+ const { isDeleted } = await this.#client.apiClient.cloud.deleteNodeCloudTrash.mutate({ ids });
114
106
  return isDeleted;
115
107
  }
116
108
  async createFolder({ name, parentFolderId, }) {
117
109
  const { encryptedNameKey, encryptedName } = await generateAndEncryptNameAndKey({
118
110
  name,
119
- privateKey: this.#keys.privateKey,
120
- publicKey: this.#keys.publicKey,
111
+ privateKey: this.#client.uaPrivateKey,
112
+ publicKey: this.#client.uaIdentity.identityPubKey,
121
113
  });
122
- const createdFolder = await this.#apiClient.cloud.createFolder.mutate({
114
+ const createdFolder = await this.#client.apiClient.cloud.createFolder.mutate({
123
115
  name: encryptedName,
124
116
  parentId: parentFolderId ?? null,
125
117
  nameKey: encryptedNameKey,
126
118
  });
127
- const folder = await apiNodeToExternalNodeFull(createdFolder, this.#keys);
128
- const users = folder.parent?.users?.filter(([u]) => u.id !== folder.owner.id) ?? [];
129
- if (users.length > 0) {
130
- await this.shareNode(users.map(([user, permissions]) => ({
131
- userId: user.id,
132
- nodeId: folder.id,
133
- rights: permissions.rights,
134
- addAccess: permissions.addAccess,
135
- delAccess: permissions.delAccess,
136
- sharingAddAccess: permissions.sharingAddAccess,
137
- sharingDelAccess: permissions.sharingDelAccess,
138
- })));
119
+ const folder = await apiNodeToExternalNodeFull(createdFolder, this.#client.keyPairs);
120
+ if (folder.parent) {
121
+ const othersIdentities = Object.entries(folder.parent.identities).filter(([id]) => id !== this.#client.uaIdentity.identityPubKey);
122
+ // TODO: ??
123
+ if (othersIdentities.length > 0) {
124
+ await this.shareNode(othersIdentities.map(([identityPubKey, permissions]) => ({
125
+ pubKey: identityPubKey,
126
+ nodeId: folder.id,
127
+ rights: permissions.rights,
128
+ addAccess: permissions.addAccess,
129
+ delAccess: permissions.delAccess,
130
+ sharingAddAccess: permissions.sharingAddAccess,
131
+ sharingDelAccess: permissions.sharingDelAccess,
132
+ })));
133
+ }
139
134
  }
140
135
  return folder;
141
136
  }
142
137
  async node({ id, deleted, } = {}) {
143
- const node = await this.#apiClient.cloud.nodeFullById.query({ id, deleted });
144
- return await apiNodeToExternalNodeFull(node, this.#keys);
138
+ const node = await this.#client.apiClient.cloud.nodeFullById.query({
139
+ id,
140
+ deleted,
141
+ });
142
+ return await apiNodeToExternalNodeFull(node, this.#client.keyPairs);
145
143
  }
146
144
  async dataMetadata({ id }) {
147
- const data = await this.#apiClient.cloud.dataById.query({ id });
148
- return apiDataToExternal(data, this.#keys);
145
+ const data = await this.#client.apiClient.cloud.dataById.query({ id });
146
+ return apiDataToExternal(data, this.#client.keyPairs);
149
147
  }
150
- async shareNode(input, progress) {
148
+ async shareNode(accesses, progress) {
151
149
  // TODO: Validate input
152
- const nodesMap = await this.#apiClient.cloud.shareNode.mutate(input);
153
- const neededUserKey = Object.entries(nodesMap)
154
- .filter(([, nodes]) => nodes.some((node) => node.includeKeys))
155
- .map(([userId]) => userId);
156
- const publicKeysMap = await this.#client.app.userPublicKey(neededUserKey);
150
+ const nodesMap = await this.#client.apiClient.cloud.shareNode.mutate({
151
+ accesses,
152
+ });
157
153
  const maxNodesBatchSize = 1000;
158
154
  const totalNodesToShare = Object.values(nodesMap).reduce((size, ids) => size + ids.length, 0);
159
155
  progress?.({ total: totalNodesToShare, current: 0, percent: 0 });
@@ -170,9 +166,9 @@ export class SecrecyCloudClient {
170
166
  return filtered.length > 0 ? [userId, filtered] : null;
171
167
  })
172
168
  .filter((entry) => entry !== null));
173
- const infos = await this.encryptNodesForUsers(nodesToEncrypt, publicKeysMap);
174
- const nodesToUpdateRights = Object.fromEntries(Object.entries(nodesMap).map(([userId, nodes]) => [
175
- userId,
169
+ const infos = await this.encryptNodesForIdentities(nodesToEncrypt);
170
+ const nodesToUpdateRights = Object.fromEntries(Object.entries(nodesMap).map(([pubKey, nodes]) => [
171
+ pubKey,
176
172
  nodes
177
173
  .filter((node) => !node.includeKeys)
178
174
  .map((node) => {
@@ -188,13 +184,13 @@ export class SecrecyCloudClient {
188
184
  };
189
185
  }),
190
186
  ]));
191
- const withKeys = Object.fromEntries(Object.entries(infos).map(([userId, nodes]) => {
187
+ const withKeys = Object.fromEntries(Object.entries(infos).map(([pubKey, nodes]) => {
192
188
  return [
193
- userId,
189
+ pubKey,
194
190
  {
195
- userId,
191
+ pubKey,
196
192
  nodes: nodes.map((node) => {
197
- const map = nodesMap[userId];
193
+ const map = nodesMap[pubKey];
198
194
  if (!map) {
199
195
  throw new Error('Unable to retrieve mapped nodes!');
200
196
  }
@@ -217,20 +213,22 @@ export class SecrecyCloudClient {
217
213
  ];
218
214
  }));
219
215
  const finishInput = [];
220
- for (const [userId, nodes] of Object.entries(withKeys)) {
216
+ for (const [pubKey, nodes] of Object.entries(withKeys)) {
221
217
  if (nodes.nodes.length === 0) {
222
218
  continue;
223
219
  }
224
- finishInput.push({ userId, nodes: nodes.nodes });
220
+ finishInput.push({ pubKey, nodes: nodes.nodes });
225
221
  }
226
- for (const [userId, nodes] of Object.entries(nodesToUpdateRights)) {
222
+ for (const [pubKey, nodes] of Object.entries(nodesToUpdateRights)) {
227
223
  if (nodes.length === 0) {
228
224
  continue;
229
225
  }
230
- finishInput.push({ userId, nodes });
226
+ finishInput.push({ pubKey, nodes });
231
227
  }
232
228
  const subState = finishInput.length > 0
233
- ? await this.#apiClient.cloud.shareNodeFinish.mutate(finishInput)
229
+ ? await this.#client.apiClient.cloud.shareNodeFinish.mutate({
230
+ accesses: finishInput,
231
+ })
234
232
  : { isFinished: true, details: {} };
235
233
  const currentProgress = Math.min((index + 1) * maxNodesBatchSize, totalNodesToShare);
236
234
  progress?.({
@@ -277,27 +275,31 @@ export class SecrecyCloudClient {
277
275
  throw `Can't find Node ${nodeId}`;
278
276
  }
279
277
  }
280
- if (node.access?.nameKey === undefined) {
281
- throw new Error(`Can't have access to node ${nodeId}`);
278
+ if (node.accesses.find((a) => ['delete', 'write'].includes(a.rights)) ===
279
+ undefined) {
280
+ throw new Error(`No access to update node ${nodeId}`);
281
+ }
282
+ if (!node.accesses[0]) {
283
+ throw new Error(`No access found for node ${nodeId}`);
282
284
  }
283
285
  name =
284
- typeof name === 'string' && node.access.nameKey !== null
285
- ? await encryptName(name, node.access.nameKey)
286
+ typeof name === 'string' && node.accesses[0].nameKey !== null
287
+ ? await encryptName(name, node.accesses[0].nameKey)
286
288
  : null;
287
- const updateNode = await this.#apiClient.cloud.updateNode.mutate({
289
+ const updateNode = await this.#client.apiClient.cloud.updateNode.mutate({
288
290
  deletedAt: deletedAt ?? null,
289
291
  id: nodeId,
290
292
  isFavorite: isFavorite ?? null,
291
293
  name,
292
294
  });
293
- return await apiNodeToExternalNodeFull(updateNode, this.#keys);
295
+ return await apiNodeToExternalNodeFull(updateNode, this.#client.keyPairs);
294
296
  }
295
297
  async dataContent({ dataId, onDownloadProgress, progressDecrypt, signal, }) {
296
298
  const cached = dataContentCache.get(dataId);
297
299
  if (cached !== undefined) {
298
300
  return cached;
299
301
  }
300
- const dataContent = await this.#apiClient.cloud.dataContentById.query({
302
+ const dataContent = await this.#client.apiClient.cloud.dataContentById.query({
301
303
  id: dataId,
302
304
  });
303
305
  const totalBytes = Number(dataContent.sizeEncrypted ?? dataContent.size);
@@ -318,7 +320,7 @@ export class SecrecyCloudClient {
318
320
  if (cachedData.length === dataIds.length) {
319
321
  return cachedData;
320
322
  }
321
- const missingContents = await this.#apiClient.cloud.dataContentByIds.query({
323
+ const missingContents = await this.#client.apiClient.cloud.dataContentByIds.query({
322
324
  ids: dataIds.filter((dataId) => !cachedData.some((datum) => datum.id === dataId)),
323
325
  });
324
326
  const allDataContents = [
@@ -349,33 +351,33 @@ export class SecrecyCloudClient {
349
351
  }));
350
352
  }
351
353
  async deleteNodes({ nodeIds, }) {
352
- return this.#apiClient.cloud.deleteNodes.mutate({ ids: nodeIds });
354
+ return this.#client.apiClient.cloud.deleteNodes.mutate({ ids: nodeIds });
353
355
  }
354
356
  async deleteData({ dataId, nodeId, }) {
355
- const { isDeleted } = await this.#apiClient.cloud.deleteData.mutate({
357
+ const { isDeleted } = await this.#client.apiClient.cloud.deleteData.mutate({
356
358
  dataId,
357
359
  nodeId,
358
360
  });
359
361
  return isDeleted;
360
362
  }
361
363
  async deleteNode({ nodeId }) {
362
- const { isDeleted } = await this.#apiClient.cloud.deleteNode.mutate({
364
+ const { isDeleted } = await this.#client.apiClient.cloud.deleteNode.mutate({
363
365
  id: nodeId,
364
366
  });
365
367
  return isDeleted;
366
368
  }
367
369
  async emptyTrash() {
368
- const { isCleaned } = await this.#apiClient.cloud.emptyNodeCloudTrash.mutate({});
370
+ const { isCleaned } = await this.#client.apiClient.cloud.emptyNodeCloudTrash.mutate({});
369
371
  return isCleaned;
370
372
  }
371
373
  async recoverNode(id) {
372
- const { isRecovered } = await this.#apiClient.cloud.recoverNode.mutate({
374
+ const { isRecovered } = await this.#client.apiClient.cloud.recoverNode.mutate({
373
375
  id,
374
376
  });
375
377
  return isRecovered;
376
378
  }
377
379
  async moveNodes({ nodeIds, parentNodeId, }) {
378
- const { isMoved } = await this.#apiClient.cloud.moveNodes.mutate({
380
+ const { isMoved } = await this.#client.apiClient.cloud.moveNodes.mutate({
379
381
  ids: nodeIds,
380
382
  parentId: parentNodeId ?? null,
381
383
  });
@@ -420,7 +422,7 @@ export class SecrecyCloudClient {
420
422
  }
421
423
  const senderPubKey = await this.#client.app.userPublicKey(mail.sender.id);
422
424
  const dataKey = attachment.key
423
- ? decryptCryptoBox(sodium.from_hex(attachment.key), senderPubKey, this.#keys.privateKey)
425
+ ? decryptCryptoBox(sodium.from_hex(attachment.key), senderPubKey, this.#client.uaPrivateKey)
424
426
  : null;
425
427
  key = dataKey !== null ? sodium.to_hex(dataKey) : null;
426
428
  }
@@ -432,28 +434,27 @@ export class SecrecyCloudClient {
432
434
  key = data.key;
433
435
  }
434
436
  key = key
435
- ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(key), this.#keys.publicKey, this.#keys.privateKey))
437
+ ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(key), this.#client.uaIdentity.identityPubKey, this.#client.uaPrivateKey))
436
438
  : null;
437
439
  const { encryptedNameKey, encryptedName } = await generateAndEncryptNameAndKey({
438
440
  name,
439
- privateKey: this.#keys.privateKey,
440
- publicKey: this.#keys.publicKey,
441
+ privateKey: this.#client.uaPrivateKey,
442
+ publicKey: this.#client.uaIdentity.identityPubKey,
441
443
  });
442
- const saveInCloud = await this.#apiClient.cloud.saveInCloud.mutate({
444
+ const saveInCloud = await this.#client.apiClient.cloud.saveInCloud.mutate({
443
445
  dataId,
444
446
  key,
445
447
  nodeId: nodeId ?? null,
446
448
  fileName: encryptedName,
447
449
  nameKey: encryptedNameKey,
448
450
  });
449
- const node = await apiNodeToExternalNodeFull(saveInCloud, this.#keys);
450
- const me = node.parent?.users.find(([u]) => u.id === node.owner.id);
451
- // TODO: ??
452
- if (me !== undefined && ['delete', 'write'].includes(me[1].rights)) {
453
- const others = node.parent?.users.filter(([u]) => u.id !== node.owner.id) ?? [];
454
- if (others.length > 0) {
455
- await this.shareNode(others.map(([user, permissions]) => ({
456
- userId: user.id,
451
+ const node = await apiNodeToExternalNodeFull(saveInCloud, this.#client.keyPairs);
452
+ if (node.parent) {
453
+ const othersIdentities = Object.entries(node.parent.identities).filter(([id]) => id !== this.#client.uaIdentity.identityPubKey);
454
+ // TODO: ??
455
+ if (othersIdentities.length > 0) {
456
+ await this.shareNode(othersIdentities.map(([identityPubKey, permissions]) => ({
457
+ pubKey: identityPubKey,
457
458
  nodeId: node.id,
458
459
  ...permissions,
459
460
  })));
@@ -461,20 +462,12 @@ export class SecrecyCloudClient {
461
462
  }
462
463
  return node;
463
464
  }
464
- encryptNodesForUsers = async (userNodes, // { [userId]: nodeIds[] }
465
- userPublicKeys) => {
466
- const userIds = Object.keys(userNodes).map((userId) => userId);
467
- const nodeIds = Object.values(userNodes).flatMap((nodeIds) => nodeIds);
465
+ encryptNodesForIdentities = async (identityNodes) => {
466
+ const nodeIds = Object.values(identityNodes).flatMap((nodeIds) => nodeIds);
468
467
  if (nodeIds.length === 0) {
469
468
  return {};
470
469
  }
471
470
  const nodes = [];
472
- // Pre check to ensure we get all public keys for users!
473
- for (const userId of userIds) {
474
- if (userPublicKeys[userId] === undefined) {
475
- throw new Error(`Unable to retrieve some user public keys!`);
476
- }
477
- }
478
471
  // Retrieve and format nodes.
479
472
  for (const nodeId of nodeIds) {
480
473
  let node = nodesEncryptionCache.get(nodeId) ?? nodesCache.get(nodeId);
@@ -499,7 +492,7 @@ export class SecrecyCloudClient {
499
492
  // Retrieve all missing nodes from cache to api.
500
493
  const missingNodeIds = nodeIds.filter((nodeId) => !nodes.some((node) => node.id === nodeId));
501
494
  const fetchedNodes = missingNodeIds.length > 0
502
- ? await this.#apiClient.cloud.nodesForEncryption.query({
495
+ ? await this.#client.apiClient.cloud.nodesForEncryption.query({
503
496
  ids: missingNodeIds,
504
497
  })
505
498
  : [];
@@ -508,13 +501,13 @@ export class SecrecyCloudClient {
508
501
  throw new Error(`Unable to fetch some node infos (${diff.join(', ')})`);
509
502
  }
510
503
  const finalNodes = await Promise.all(fetchedNodes.map((node) => {
511
- return apiNodeForEncryptionToInternal(node, this.#keys);
504
+ return apiNodeForEncryptionToInternal(node, this.#client.keyPairs);
512
505
  }));
513
506
  nodes.push(...finalNodes);
514
507
  const nodesMappedUsers = {};
515
- for (const userId in userNodes) {
516
- nodesMappedUsers[userId] ??= [];
517
- for (const nodeId of userNodes[userId]) {
508
+ for (const pubKey in identityNodes) {
509
+ nodesMappedUsers[pubKey] ??= [];
510
+ for (const nodeId of identityNodes[pubKey]) {
518
511
  const node = nodes.find((node) => node.id === nodeId);
519
512
  if (!node) {
520
513
  throw new Error('Unable to retrieve node from ram');
@@ -524,17 +517,16 @@ export class SecrecyCloudClient {
524
517
  throw new Error(`Can't share a node without data (${node.id})!`);
525
518
  }
526
519
  const nameKey = node.access?.nameKey;
527
- const publicKey = userPublicKeys[userId];
528
- nodesMappedUsers[userId].push({
520
+ nodesMappedUsers[pubKey].push({
529
521
  id: node.id,
530
522
  nameKey: nameKey !== null
531
- ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(nameKey), publicKey, this.#keys.privateKey))
523
+ ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(nameKey), pubKey, this.#client.uaPrivateKey))
532
524
  : null,
533
525
  data: 'history' in node
534
526
  ? node.history.map((f) => ({
535
527
  id: f.id,
536
528
  key: f.key
537
- ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(f.key), publicKey, this.#keys.privateKey))
529
+ ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(f.key), pubKey, this.#client.uaPrivateKey))
538
530
  : null,
539
531
  }))
540
532
  : [],
@@ -545,15 +537,15 @@ export class SecrecyCloudClient {
545
537
  };
546
538
  async reportData({ id, reasons, }) {
547
539
  const [rawData, secrecy] = await Promise.all([
548
- this.#apiClient.cloud.dataById.query({ id }),
549
- this.#apiClient.misc.publicKey.query(),
540
+ this.#client.apiClient.cloud.dataById.query({ id }),
541
+ this.#client.apiClient.misc.publicKey.query(),
550
542
  ]);
551
- const data = apiDataToInternal(rawData, this.#keys);
552
- return this.#apiClient.cloud.reportData.mutate({
543
+ const data = apiDataToInternal(rawData, this.#client.keyPairs);
544
+ return this.#client.apiClient.cloud.reportData.mutate({
553
545
  id: id,
554
546
  reasons: reasons,
555
547
  encryptedDataKey: data.key
556
- ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(data.key), secrecy.publicKey, this.#keys.privateKey))
548
+ ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(data.key), secrecy.publicKey, this.#client.uaPrivateKey))
557
549
  : null,
558
550
  });
559
551
  }
@@ -567,25 +559,28 @@ export class SecrecyCloudClient {
567
559
  throw new Error("It's not possible to transfer a cold stored data to a lite storage!");
568
560
  }
569
561
  }
570
- return this.#apiClient.cloud.moveToStorageType.mutate(input);
562
+ return this.#client.apiClient.cloud.moveToStorageType.mutate(input);
571
563
  }
572
564
  getPublicDataLink(input) {
573
- return this.#apiClient.cloud.dataLink.query(input);
565
+ return this.#client.apiClient.cloud.dataLink.query(input);
574
566
  }
575
567
  getPublicDataLinks(input) {
576
- return this.#apiClient.cloud.dataLinks.query(input);
568
+ return this.#client.apiClient.cloud.dataLinks.query(input);
577
569
  }
578
570
  checkAccesses(input) {
579
- return this.#apiClient.cloud.checkAccesses.query(input);
571
+ return this.#client.apiClient.cloud.checkAccesses.query(input);
580
572
  }
581
573
  createPublicDataLink(input) {
582
- return createPublicDataLink({ ...input, apiClient: this.#apiClient });
574
+ if (input.expireAt && input.expireAt <= new Date()) {
575
+ throw new Error('Unable to create public link using a past expireAt date!');
576
+ }
577
+ return this.#client.apiClient.cloud.createDataLink.mutate(input);
583
578
  }
584
579
  updatePublicDataLink(input) {
585
- return this.#apiClient.cloud.updateDataLink.mutate(input);
580
+ return this.#client.apiClient.cloud.updateDataLink.mutate(input);
586
581
  }
587
582
  deletePublicDataLink(input) {
588
- return this.#apiClient.cloud.deleteDataLink.mutate(input);
583
+ return this.#client.apiClient.cloud.deleteDataLink.mutate(input);
589
584
  }
590
585
  downloadDataFromLink(input) {
591
586
  return downloadDataFromLink({
@@ -606,8 +601,8 @@ export class SecrecyCloudClient {
606
601
  ? decryptCryptoBox(sodium.from_hex(dataContent.key), dataContent.type === 'received_mail'
607
602
  ? dataContent.senderPublicKey
608
603
  : dataContent.type === 'cloud' || dataContent.type === 'lite'
609
- ? dataContent.publicKey
610
- : this.#keys.publicKey, this.#keys.privateKey)
604
+ ? dataContent.sharedByPublicKey
605
+ : this.#client.uaIdentity.identityPubKey, this.#client.uaPrivateKey)
611
606
  : null;
612
607
  const src = key
613
608
  ? await decrypt(key, encryptedContent, progressDecrypt, signal)
@@ -1,10 +1,3 @@
1
1
  export class SecrecyDbClient {
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;
9
- }
2
+ constructor(_client) { }
10
3
  }