@protontech/drive-sdk 0.3.0 → 0.3.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.
- package/dist/crypto/driveCrypto.d.ts +1 -1
- package/dist/crypto/driveCrypto.js.map +1 -1
- package/dist/crypto/interface.d.ts +6 -1
- package/dist/crypto/openPGPCrypto.d.ts +1 -1
- package/dist/crypto/openPGPCrypto.js +4 -1
- package/dist/crypto/openPGPCrypto.js.map +1 -1
- package/dist/diagnostic/httpClient.d.ts +3 -3
- package/dist/interface/httpClient.d.ts +5 -5
- package/dist/interface/index.d.ts +15 -5
- package/dist/internal/apiService/apiService.js +1 -1
- package/dist/internal/apiService/apiService.js.map +1 -1
- package/dist/internal/apiService/errorCodes.d.ts +1 -0
- package/dist/internal/apiService/errorCodes.js.map +1 -1
- package/dist/internal/apiService/errors.d.ts +4 -3
- package/dist/internal/apiService/errors.js +7 -4
- package/dist/internal/apiService/errors.js.map +1 -1
- package/dist/internal/apiService/errors.test.js +2 -1
- package/dist/internal/apiService/errors.test.js.map +1 -1
- package/dist/internal/download/cryptoService.js +2 -2
- package/dist/internal/download/cryptoService.js.map +1 -1
- package/dist/internal/download/fileDownloader.js +2 -2
- package/dist/internal/download/fileDownloader.js.map +1 -1
- package/dist/internal/download/fileDownloader.test.js +3 -1
- package/dist/internal/download/fileDownloader.test.js.map +1 -1
- package/dist/internal/events/index.d.ts +1 -1
- package/dist/internal/nodes/cache.js +3 -1
- package/dist/internal/nodes/cache.js.map +1 -1
- package/dist/internal/nodes/cryptoCache.js +6 -7
- package/dist/internal/nodes/cryptoCache.js.map +1 -1
- package/dist/internal/nodes/cryptoCache.test.js +4 -7
- package/dist/internal/nodes/cryptoCache.test.js.map +1 -1
- package/dist/internal/nodes/cryptoReporter.d.ts +20 -0
- package/dist/internal/nodes/cryptoReporter.js +96 -0
- package/dist/internal/nodes/cryptoReporter.js.map +1 -0
- package/dist/internal/nodes/cryptoService.d.ts +17 -12
- package/dist/internal/nodes/cryptoService.js +17 -97
- package/dist/internal/nodes/cryptoService.js.map +1 -1
- package/dist/internal/nodes/cryptoService.test.js +3 -1
- package/dist/internal/nodes/cryptoService.test.js.map +1 -1
- package/dist/internal/nodes/index.js +3 -1
- package/dist/internal/nodes/index.js.map +1 -1
- package/dist/internal/nodes/interface.d.ts +1 -1
- package/dist/internal/nodes/nodesAccess.d.ts +2 -2
- package/dist/internal/nodes/nodesAccess.js +52 -54
- package/dist/internal/nodes/nodesAccess.js.map +1 -1
- package/dist/internal/shares/cryptoCache.d.ts +4 -3
- package/dist/internal/shares/cryptoCache.js +23 -6
- package/dist/internal/shares/cryptoCache.js.map +1 -1
- package/dist/internal/shares/cryptoCache.test.js +3 -2
- package/dist/internal/shares/cryptoCache.test.js.map +1 -1
- package/dist/internal/shares/index.js +1 -1
- package/dist/internal/shares/index.js.map +1 -1
- package/dist/internal/sharing/cache.d.ts +3 -0
- package/dist/internal/sharing/cache.js +17 -2
- package/dist/internal/sharing/cache.js.map +1 -1
- package/dist/internal/sharing/cryptoService.js +8 -6
- package/dist/internal/sharing/cryptoService.js.map +1 -1
- package/dist/internal/sharing/cryptoService.test.js +13 -0
- package/dist/internal/sharing/cryptoService.test.js.map +1 -1
- package/dist/internal/sharing/index.js +1 -1
- package/dist/internal/sharing/index.js.map +1 -1
- package/dist/internal/sharing/interface.d.ts +1 -1
- package/dist/internal/sharing/interface.js +1 -1
- package/dist/internal/sharing/sharingAccess.js +6 -0
- package/dist/internal/sharing/sharingAccess.js.map +1 -1
- package/dist/internal/sharing/sharingAccess.test.js +242 -33
- package/dist/internal/sharing/sharingAccess.test.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.d.ts +3 -1
- package/dist/internal/sharing/sharingManagement.js +10 -1
- package/dist/internal/sharing/sharingManagement.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.test.js +32 -1
- package/dist/internal/sharing/sharingManagement.test.js.map +1 -1
- package/dist/internal/sharingPublic/apiService.d.ts +19 -0
- package/dist/internal/sharingPublic/apiService.js +141 -0
- package/dist/internal/sharingPublic/apiService.js.map +1 -0
- package/dist/internal/sharingPublic/cryptoCache.d.ts +19 -0
- package/dist/internal/sharingPublic/cryptoCache.js +72 -0
- package/dist/internal/sharingPublic/cryptoCache.js.map +1 -0
- package/dist/internal/sharingPublic/cryptoService.d.ts +9 -0
- package/dist/internal/sharingPublic/cryptoService.js +57 -0
- package/dist/internal/sharingPublic/cryptoService.js.map +1 -0
- package/dist/internal/sharingPublic/index.d.ts +15 -0
- package/dist/internal/sharingPublic/index.js +27 -0
- package/dist/internal/sharingPublic/index.js.map +1 -0
- package/dist/internal/sharingPublic/interface.d.ts +6 -0
- package/dist/internal/sharingPublic/interface.js +3 -0
- package/dist/internal/sharingPublic/interface.js.map +1 -0
- package/dist/internal/sharingPublic/manager.d.ts +19 -0
- package/dist/internal/sharingPublic/manager.js +81 -0
- package/dist/internal/sharingPublic/manager.js.map +1 -0
- package/dist/internal/sharingPublic/session/apiService.d.ts +28 -0
- package/dist/internal/sharingPublic/session/apiService.js +55 -0
- package/dist/internal/sharingPublic/session/apiService.js.map +1 -0
- package/dist/internal/sharingPublic/session/httpClient.d.ts +16 -0
- package/dist/internal/sharingPublic/session/httpClient.js +41 -0
- package/dist/internal/sharingPublic/session/httpClient.js.map +1 -0
- package/dist/internal/sharingPublic/session/index.d.ts +1 -0
- package/dist/internal/sharingPublic/session/index.js +6 -0
- package/dist/internal/sharingPublic/session/index.js.map +1 -0
- package/dist/internal/sharingPublic/session/interface.d.ts +18 -0
- package/dist/internal/sharingPublic/session/interface.js +3 -0
- package/dist/internal/sharingPublic/session/interface.js.map +1 -0
- package/dist/internal/sharingPublic/session/manager.d.ts +49 -0
- package/dist/internal/sharingPublic/session/manager.js +75 -0
- package/dist/internal/sharingPublic/session/manager.js.map +1 -0
- package/dist/internal/sharingPublic/session/session.d.ts +34 -0
- package/dist/internal/sharingPublic/session/session.js +67 -0
- package/dist/internal/sharingPublic/session/session.js.map +1 -0
- package/dist/internal/sharingPublic/session/url.d.ts +12 -0
- package/dist/internal/sharingPublic/session/url.js +23 -0
- package/dist/internal/sharingPublic/session/url.js.map +1 -0
- package/dist/internal/sharingPublic/session/url.test.d.ts +1 -0
- package/dist/internal/sharingPublic/session/url.test.js +59 -0
- package/dist/internal/sharingPublic/session/url.test.js.map +1 -0
- package/dist/internal/upload/streamUploader.js +1 -1
- package/dist/internal/upload/streamUploader.js.map +1 -1
- package/dist/internal/upload/streamUploader.test.js +3 -1
- package/dist/internal/upload/streamUploader.test.js.map +1 -1
- package/dist/protonDriveClient.d.ts +18 -3
- package/dist/protonDriveClient.js +31 -8
- package/dist/protonDriveClient.js.map +1 -1
- package/dist/protonDrivePublicLinkClient.d.ts +57 -0
- package/dist/protonDrivePublicLinkClient.js +73 -0
- package/dist/protonDrivePublicLinkClient.js.map +1 -0
- package/package.json +1 -1
- package/src/crypto/driveCrypto.ts +1 -1
- package/src/crypto/interface.ts +12 -1
- package/src/crypto/openPGPCrypto.ts +5 -2
- package/src/diagnostic/httpClient.ts +4 -4
- package/src/interface/httpClient.ts +5 -5
- package/src/interface/index.ts +18 -6
- package/src/internal/apiService/apiService.ts +1 -1
- package/src/internal/apiService/errorCodes.ts +1 -0
- package/src/internal/apiService/errors.test.ts +2 -1
- package/src/internal/apiService/errors.ts +15 -4
- package/src/internal/download/cryptoService.ts +2 -2
- package/src/internal/download/fileDownloader.test.ts +3 -1
- package/src/internal/download/fileDownloader.ts +2 -2
- package/src/internal/events/index.ts +1 -1
- package/src/internal/nodes/cache.ts +3 -1
- package/src/internal/nodes/cryptoCache.test.ts +4 -7
- package/src/internal/nodes/cryptoCache.ts +6 -7
- package/src/internal/nodes/cryptoReporter.ts +145 -0
- package/src/internal/nodes/cryptoService.test.ts +3 -1
- package/src/internal/nodes/cryptoService.ts +44 -137
- package/src/internal/nodes/index.ts +3 -1
- package/src/internal/nodes/interface.ts +3 -1
- package/src/internal/nodes/nodesAccess.ts +59 -61
- package/src/internal/shares/cryptoCache.test.ts +3 -2
- package/src/internal/shares/cryptoCache.ts +26 -7
- package/src/internal/shares/index.ts +1 -1
- package/src/internal/sharing/cache.ts +19 -2
- package/src/internal/sharing/cryptoService.test.ts +22 -1
- package/src/internal/sharing/cryptoService.ts +8 -6
- package/src/internal/sharing/index.ts +1 -0
- package/src/internal/sharing/interface.ts +1 -1
- package/src/internal/sharing/sharingAccess.test.ts +282 -34
- package/src/internal/sharing/sharingAccess.ts +6 -0
- package/src/internal/sharing/sharingManagement.test.ts +33 -0
- package/src/internal/sharing/sharingManagement.ts +9 -0
- package/src/internal/sharingPublic/apiService.ts +173 -0
- package/src/internal/sharingPublic/cryptoCache.ts +79 -0
- package/src/internal/sharingPublic/cryptoService.ts +98 -0
- package/src/internal/sharingPublic/index.ts +41 -0
- package/src/internal/sharingPublic/interface.ts +14 -0
- package/src/internal/sharingPublic/manager.ts +86 -0
- package/src/internal/sharingPublic/session/apiService.ts +74 -0
- package/src/internal/sharingPublic/session/httpClient.ts +48 -0
- package/src/internal/sharingPublic/session/index.ts +1 -0
- package/src/internal/sharingPublic/session/interface.ts +20 -0
- package/src/internal/sharingPublic/session/manager.ts +97 -0
- package/src/internal/sharingPublic/session/session.ts +78 -0
- package/src/internal/sharingPublic/session/url.test.ts +72 -0
- package/src/internal/sharingPublic/session/url.ts +23 -0
- package/src/internal/upload/streamUploader.test.ts +3 -1
- package/src/internal/upload/streamUploader.ts +1 -1
- package/src/protonDriveClient.ts +48 -11
- package/src/protonDrivePublicLinkClient.ts +135 -0
|
@@ -10,12 +10,14 @@ import {
|
|
|
10
10
|
resultOk,
|
|
11
11
|
} from '../../interface';
|
|
12
12
|
import { SharingAPIService } from './apiService';
|
|
13
|
+
import { SharingCache } from './cache';
|
|
13
14
|
import { SharingCryptoService } from './cryptoService';
|
|
14
15
|
import { SharesService, NodesService } from './interface';
|
|
15
16
|
import { SharingManagement } from './sharingManagement';
|
|
16
17
|
|
|
17
18
|
describe('SharingManagement', () => {
|
|
18
19
|
let apiService: SharingAPIService;
|
|
20
|
+
let cache: SharingCache;
|
|
19
21
|
let cryptoService: SharingCryptoService;
|
|
20
22
|
let accountService: ProtonDriveAccount;
|
|
21
23
|
let sharesService: SharesService;
|
|
@@ -57,6 +59,12 @@ describe('SharingManagement', () => {
|
|
|
57
59
|
updatePublicLink: jest.fn(),
|
|
58
60
|
};
|
|
59
61
|
// @ts-expect-error No need to implement all methods for mocking
|
|
62
|
+
cache = {
|
|
63
|
+
hasSharedByMeNodeUidsLoaded: jest.fn().mockResolvedValue(true),
|
|
64
|
+
addSharedByMeNodeUid: jest.fn(),
|
|
65
|
+
removeSharedByMeNodeUid: jest.fn(),
|
|
66
|
+
};
|
|
67
|
+
// @ts-expect-error No need to implement all methods for mocking
|
|
60
68
|
cryptoService = {
|
|
61
69
|
generateShareKeys: jest.fn().mockResolvedValue({
|
|
62
70
|
shareKey: { encrypted: 'encrypted-key', decrypted: { passphraseSessionKey: 'pass-session-key' } },
|
|
@@ -104,6 +112,7 @@ describe('SharingManagement', () => {
|
|
|
104
112
|
sharingManagement = new SharingManagement(
|
|
105
113
|
getMockLogger(),
|
|
106
114
|
apiService,
|
|
115
|
+
cache,
|
|
107
116
|
cryptoService,
|
|
108
117
|
accountService,
|
|
109
118
|
sharesService,
|
|
@@ -214,6 +223,7 @@ describe('SharingManagement', () => {
|
|
|
214
223
|
expect(apiService.updateInvitation).not.toHaveBeenCalled();
|
|
215
224
|
expect(apiService.inviteProtonUser).toHaveBeenCalled();
|
|
216
225
|
expect(nodesService.notifyNodeChanged).toHaveBeenCalledWith(nodeUid);
|
|
226
|
+
expect(cache.addSharedByMeNodeUid).toHaveBeenCalledWith(nodeUid);
|
|
217
227
|
});
|
|
218
228
|
});
|
|
219
229
|
|
|
@@ -279,6 +289,7 @@ describe('SharingManagement', () => {
|
|
|
279
289
|
});
|
|
280
290
|
expect(apiService.updateInvitation).not.toHaveBeenCalled();
|
|
281
291
|
expect(apiService.inviteProtonUser).toHaveBeenCalled();
|
|
292
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
282
293
|
});
|
|
283
294
|
|
|
284
295
|
it('should share node with proton email with specific role', async () => {
|
|
@@ -302,6 +313,7 @@ describe('SharingManagement', () => {
|
|
|
302
313
|
});
|
|
303
314
|
expect(apiService.updateInvitation).not.toHaveBeenCalled();
|
|
304
315
|
expect(apiService.inviteProtonUser).toHaveBeenCalled();
|
|
316
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
305
317
|
});
|
|
306
318
|
|
|
307
319
|
it('should update existing role', async () => {
|
|
@@ -322,6 +334,7 @@ describe('SharingManagement', () => {
|
|
|
322
334
|
});
|
|
323
335
|
expect(apiService.updateInvitation).toHaveBeenCalled();
|
|
324
336
|
expect(apiService.inviteProtonUser).not.toHaveBeenCalled();
|
|
337
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
325
338
|
});
|
|
326
339
|
|
|
327
340
|
it('should be no-op if no change', async () => {
|
|
@@ -337,6 +350,7 @@ describe('SharingManagement', () => {
|
|
|
337
350
|
});
|
|
338
351
|
expect(apiService.updateInvitation).not.toHaveBeenCalled();
|
|
339
352
|
expect(apiService.inviteProtonUser).not.toHaveBeenCalled();
|
|
353
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
340
354
|
});
|
|
341
355
|
|
|
342
356
|
it('should use address from the root node context share', async () => {
|
|
@@ -383,6 +397,7 @@ describe('SharingManagement', () => {
|
|
|
383
397
|
});
|
|
384
398
|
expect(apiService.updateExternalInvitation).not.toHaveBeenCalled();
|
|
385
399
|
expect(apiService.inviteExternalUser).toHaveBeenCalled();
|
|
400
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
386
401
|
});
|
|
387
402
|
|
|
388
403
|
it('should share node with external email with specific role', async () => {
|
|
@@ -407,6 +422,7 @@ describe('SharingManagement', () => {
|
|
|
407
422
|
});
|
|
408
423
|
expect(apiService.updateExternalInvitation).not.toHaveBeenCalled();
|
|
409
424
|
expect(apiService.inviteExternalUser).toHaveBeenCalled();
|
|
425
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
410
426
|
});
|
|
411
427
|
|
|
412
428
|
it('should update existing role', async () => {
|
|
@@ -427,6 +443,7 @@ describe('SharingManagement', () => {
|
|
|
427
443
|
});
|
|
428
444
|
expect(apiService.updateExternalInvitation).toHaveBeenCalled();
|
|
429
445
|
expect(apiService.inviteExternalUser).not.toHaveBeenCalled();
|
|
446
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
430
447
|
});
|
|
431
448
|
|
|
432
449
|
it('should be no-op if no change', async () => {
|
|
@@ -442,6 +459,7 @@ describe('SharingManagement', () => {
|
|
|
442
459
|
});
|
|
443
460
|
expect(apiService.updateExternalInvitation).not.toHaveBeenCalled();
|
|
444
461
|
expect(apiService.inviteExternalUser).not.toHaveBeenCalled();
|
|
462
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
445
463
|
});
|
|
446
464
|
|
|
447
465
|
it('should use address from the root node context share', async () => {
|
|
@@ -512,6 +530,7 @@ describe('SharingManagement', () => {
|
|
|
512
530
|
}),
|
|
513
531
|
expect.anything(),
|
|
514
532
|
);
|
|
533
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
515
534
|
});
|
|
516
535
|
});
|
|
517
536
|
|
|
@@ -535,6 +554,7 @@ describe('SharingManagement', () => {
|
|
|
535
554
|
expect(apiService.updateMember).toHaveBeenCalled();
|
|
536
555
|
expect(apiService.updateInvitation).not.toHaveBeenCalled();
|
|
537
556
|
expect(apiService.inviteProtonUser).not.toHaveBeenCalled();
|
|
557
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
538
558
|
});
|
|
539
559
|
|
|
540
560
|
it('should be no-op if no change via proton user', async () => {
|
|
@@ -551,6 +571,7 @@ describe('SharingManagement', () => {
|
|
|
551
571
|
expect(apiService.updateMember).not.toHaveBeenCalled();
|
|
552
572
|
expect(apiService.updateInvitation).not.toHaveBeenCalled();
|
|
553
573
|
expect(apiService.inviteProtonUser).not.toHaveBeenCalled();
|
|
574
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
554
575
|
});
|
|
555
576
|
|
|
556
577
|
it('should update member via non-proton user', async () => {
|
|
@@ -572,6 +593,7 @@ describe('SharingManagement', () => {
|
|
|
572
593
|
expect(apiService.updateMember).toHaveBeenCalled();
|
|
573
594
|
expect(apiService.updateInvitation).not.toHaveBeenCalled();
|
|
574
595
|
expect(apiService.inviteProtonUser).not.toHaveBeenCalled();
|
|
596
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
575
597
|
});
|
|
576
598
|
|
|
577
599
|
it('should be no-op if no change via non-proton user', async () => {
|
|
@@ -588,6 +610,7 @@ describe('SharingManagement', () => {
|
|
|
588
610
|
expect(apiService.updateMember).not.toHaveBeenCalled();
|
|
589
611
|
expect(apiService.updateInvitation).not.toHaveBeenCalled();
|
|
590
612
|
expect(apiService.inviteProtonUser).not.toHaveBeenCalled();
|
|
613
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
591
614
|
});
|
|
592
615
|
});
|
|
593
616
|
|
|
@@ -635,6 +658,7 @@ describe('SharingManagement', () => {
|
|
|
635
658
|
srp: 'publicLinkSrp',
|
|
636
659
|
}),
|
|
637
660
|
);
|
|
661
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
638
662
|
});
|
|
639
663
|
|
|
640
664
|
it('should share node with custom password and expiration', async () => {
|
|
@@ -680,6 +704,7 @@ describe('SharingManagement', () => {
|
|
|
680
704
|
srp: 'publicLinkSrp',
|
|
681
705
|
}),
|
|
682
706
|
);
|
|
707
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
683
708
|
});
|
|
684
709
|
|
|
685
710
|
it('should update public link with custom password and expiration', async () => {
|
|
@@ -734,6 +759,7 @@ describe('SharingManagement', () => {
|
|
|
734
759
|
srp: 'publicLinkSrp',
|
|
735
760
|
}),
|
|
736
761
|
);
|
|
762
|
+
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
737
763
|
});
|
|
738
764
|
|
|
739
765
|
it('should not allow updating legacy public link', async () => {
|
|
@@ -839,6 +865,7 @@ describe('SharingManagement', () => {
|
|
|
839
865
|
expect(apiService.deleteExternalInvitation).not.toHaveBeenCalled();
|
|
840
866
|
expect(apiService.removeMember).not.toHaveBeenCalled();
|
|
841
867
|
expect(apiService.removePublicLink).not.toHaveBeenCalled();
|
|
868
|
+
expect(cache.removeSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
842
869
|
});
|
|
843
870
|
|
|
844
871
|
it('should delete external invitation', async () => {
|
|
@@ -855,6 +882,7 @@ describe('SharingManagement', () => {
|
|
|
855
882
|
expect(apiService.deleteExternalInvitation).toHaveBeenCalled();
|
|
856
883
|
expect(apiService.removeMember).not.toHaveBeenCalled();
|
|
857
884
|
expect(apiService.removePublicLink).not.toHaveBeenCalled();
|
|
885
|
+
expect(cache.removeSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
858
886
|
});
|
|
859
887
|
|
|
860
888
|
it('should remove member', async () => {
|
|
@@ -871,6 +899,7 @@ describe('SharingManagement', () => {
|
|
|
871
899
|
expect(apiService.deleteExternalInvitation).not.toHaveBeenCalled();
|
|
872
900
|
expect(apiService.removeMember).toHaveBeenCalled();
|
|
873
901
|
expect(apiService.removePublicLink).not.toHaveBeenCalled();
|
|
902
|
+
expect(cache.removeSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
874
903
|
});
|
|
875
904
|
|
|
876
905
|
it('should be no-op if not shared with email', async () => {
|
|
@@ -887,6 +916,7 @@ describe('SharingManagement', () => {
|
|
|
887
916
|
expect(apiService.deleteExternalInvitation).not.toHaveBeenCalled();
|
|
888
917
|
expect(apiService.removeMember).not.toHaveBeenCalled();
|
|
889
918
|
expect(apiService.removePublicLink).not.toHaveBeenCalled();
|
|
919
|
+
expect(cache.removeSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
890
920
|
});
|
|
891
921
|
|
|
892
922
|
it('should remove public link', async () => {
|
|
@@ -903,6 +933,7 @@ describe('SharingManagement', () => {
|
|
|
903
933
|
expect(apiService.deleteExternalInvitation).not.toHaveBeenCalled();
|
|
904
934
|
expect(apiService.removeMember).not.toHaveBeenCalled();
|
|
905
935
|
expect(apiService.removePublicLink).toHaveBeenCalled();
|
|
936
|
+
expect(cache.removeSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
906
937
|
});
|
|
907
938
|
|
|
908
939
|
it('should remove share if all is removed', async () => {
|
|
@@ -915,6 +946,7 @@ describe('SharingManagement', () => {
|
|
|
915
946
|
expect(apiService.removeMember).not.toHaveBeenCalled();
|
|
916
947
|
expect(apiService.removePublicLink).not.toHaveBeenCalled();
|
|
917
948
|
expect(nodesService.notifyNodeChanged).toHaveBeenCalled();
|
|
949
|
+
expect(cache.removeSharedByMeNodeUid).toHaveBeenCalledWith(nodeUid);
|
|
918
950
|
});
|
|
919
951
|
|
|
920
952
|
it('should remove share if everything is manually removed', async () => {
|
|
@@ -929,6 +961,7 @@ describe('SharingManagement', () => {
|
|
|
929
961
|
expect(apiService.deleteExternalInvitation).toHaveBeenCalled();
|
|
930
962
|
expect(apiService.removeMember).toHaveBeenCalled();
|
|
931
963
|
expect(apiService.removePublicLink).toHaveBeenCalled();
|
|
964
|
+
expect(cache.removeSharedByMeNodeUid).toHaveBeenCalledWith(nodeUid);
|
|
932
965
|
});
|
|
933
966
|
});
|
|
934
967
|
|
|
@@ -20,6 +20,7 @@ import { getErrorMessage } from '../errors';
|
|
|
20
20
|
import { SharingAPIService } from './apiService';
|
|
21
21
|
import { PUBLIC_LINK_GENERATED_PASSWORD_LENGTH, SharingCryptoService } from './cryptoService';
|
|
22
22
|
import { SharesService, NodesService, ShareResultWithCreatorEmail, PublicLinkWithCreatorEmail } from './interface';
|
|
23
|
+
import { SharingCache } from './cache';
|
|
23
24
|
|
|
24
25
|
interface InternalShareResult extends ShareResultWithCreatorEmail {
|
|
25
26
|
share: Share;
|
|
@@ -54,6 +55,7 @@ export class SharingManagement {
|
|
|
54
55
|
constructor(
|
|
55
56
|
private logger: Logger,
|
|
56
57
|
private apiService: SharingAPIService,
|
|
58
|
+
private cache: SharingCache,
|
|
57
59
|
private cryptoService: SharingCryptoService,
|
|
58
60
|
private account: ProtonDriveAccount,
|
|
59
61
|
private sharesService: SharesService,
|
|
@@ -61,6 +63,7 @@ export class SharingManagement {
|
|
|
61
63
|
) {
|
|
62
64
|
this.logger = logger;
|
|
63
65
|
this.apiService = apiService;
|
|
66
|
+
this.cache = cache;
|
|
64
67
|
this.cryptoService = cryptoService;
|
|
65
68
|
this.account = account;
|
|
66
69
|
this.sharesService = sharesService;
|
|
@@ -409,6 +412,9 @@ export class SharingManagement {
|
|
|
409
412
|
base64NameKeyPacket: keys.base64NameKeyPacket,
|
|
410
413
|
});
|
|
411
414
|
await this.nodesService.notifyNodeChanged(nodeUid);
|
|
415
|
+
if (await this.cache.hasSharedByMeNodeUidsLoaded()) {
|
|
416
|
+
await this.cache.addSharedByMeNodeUid(nodeUid);
|
|
417
|
+
}
|
|
412
418
|
|
|
413
419
|
const share = {
|
|
414
420
|
volumeId,
|
|
@@ -430,6 +436,9 @@ export class SharingManagement {
|
|
|
430
436
|
private async deleteShare(shareId: string, nodeUid: string): Promise<void> {
|
|
431
437
|
await this.apiService.deleteShare(shareId);
|
|
432
438
|
await this.nodesService.notifyNodeChanged(nodeUid);
|
|
439
|
+
if (await this.cache.hasSharedByMeNodeUidsLoaded()) {
|
|
440
|
+
await this.cache.removeSharedByMeNodeUid(nodeUid);
|
|
441
|
+
}
|
|
433
442
|
}
|
|
434
443
|
|
|
435
444
|
private async inviteProtonUser(
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { DriveAPIService, drivePaths, nodeTypeNumberToNodeType } from '../apiService';
|
|
2
|
+
import { Logger, MemberRole } from '../../interface';
|
|
3
|
+
import { makeNodeUid, splitNodeUid } from '../uids';
|
|
4
|
+
import { EncryptedShareCrypto, EncryptedNode } from './interface';
|
|
5
|
+
|
|
6
|
+
const PAGE_SIZE = 50;
|
|
7
|
+
|
|
8
|
+
type GetTokenInfoResponse = drivePaths['/drive/urls/{token}']['get']['responses']['200']['content']['application/json'];
|
|
9
|
+
|
|
10
|
+
type GetTokenFolderChildrenResponse =
|
|
11
|
+
drivePaths['/drive/urls/{token}/folders/{linkID}/children']['get']['responses']['200']['content']['application/json'];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Provides API communication for accessing public link data.
|
|
15
|
+
*
|
|
16
|
+
* The service is responsible for transforming local objects to API payloads
|
|
17
|
+
* and vice versa. It should not contain any business logic.
|
|
18
|
+
*/
|
|
19
|
+
export class SharingPublicAPIService {
|
|
20
|
+
constructor(
|
|
21
|
+
private logger: Logger,
|
|
22
|
+
private apiService: DriveAPIService,
|
|
23
|
+
) {
|
|
24
|
+
this.logger = logger;
|
|
25
|
+
this.apiService = apiService;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async getPublicLinkRoot(token: string): Promise<{
|
|
29
|
+
encryptedNode: EncryptedNode;
|
|
30
|
+
encryptedShare: EncryptedShareCrypto;
|
|
31
|
+
}> {
|
|
32
|
+
const response = await this.apiService.get<GetTokenInfoResponse>(`drive/urls/${token}`);
|
|
33
|
+
const encryptedNode = tokenToEncryptedNode(this.logger, response.Token);
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
encryptedNode: encryptedNode,
|
|
37
|
+
encryptedShare: {
|
|
38
|
+
base64UrlPasswordSalt: response.Token.SharePasswordSalt,
|
|
39
|
+
armoredKey: response.Token.ShareKey,
|
|
40
|
+
armoredPassphrase: response.Token.SharePassphrase,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async *iterateFolderChildren(parentUid: string, signal?: AbortSignal): AsyncGenerator<EncryptedNode> {
|
|
46
|
+
const { volumeId: token, nodeId } = splitNodeUid(parentUid);
|
|
47
|
+
|
|
48
|
+
let page = 0;
|
|
49
|
+
while (true) {
|
|
50
|
+
const response = await this.apiService.get<GetTokenFolderChildrenResponse>(
|
|
51
|
+
`drive/urls/${token}/folders/${nodeId}/children?Page=${page}&PageSize=${PAGE_SIZE}`,
|
|
52
|
+
signal,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
for (const link of response.Links) {
|
|
56
|
+
yield linkToEncryptedNode(this.logger, token, link);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (response.Links.length < PAGE_SIZE) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
page++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function tokenToEncryptedNode(logger: Logger, token: GetTokenInfoResponse['Token']): EncryptedNode {
|
|
68
|
+
const baseNodeMetadata = {
|
|
69
|
+
// Internal metadata
|
|
70
|
+
encryptedName: token.Name,
|
|
71
|
+
|
|
72
|
+
// Basic node metadata
|
|
73
|
+
uid: makeNodeUid(token.Token, token.LinkID),
|
|
74
|
+
parentUid: undefined,
|
|
75
|
+
type: nodeTypeNumberToNodeType(logger, token.LinkType),
|
|
76
|
+
creationTime: new Date(), // TODO
|
|
77
|
+
|
|
78
|
+
isShared: false,
|
|
79
|
+
directRole: MemberRole.Viewer, // TODO
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const baseCryptoNodeMetadata = {
|
|
83
|
+
signatureEmail: token.SignatureEmail || undefined,
|
|
84
|
+
armoredKey: token.NodeKey,
|
|
85
|
+
armoredNodePassphrase: token.NodePassphrase,
|
|
86
|
+
armoredNodePassphraseSignature: token.NodePassphraseSignature || undefined,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
if (token.LinkType === 1 && token.NodeHashKey) {
|
|
90
|
+
return {
|
|
91
|
+
...baseNodeMetadata,
|
|
92
|
+
encryptedCrypto: {
|
|
93
|
+
...baseCryptoNodeMetadata,
|
|
94
|
+
folder: {
|
|
95
|
+
armoredHashKey: token.NodeHashKey as string,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (token.LinkType === 2 && token.ContentKeyPacket) {
|
|
102
|
+
return {
|
|
103
|
+
...baseNodeMetadata,
|
|
104
|
+
totalStorageSize: token.Size || undefined,
|
|
105
|
+
mediaType: token.MIMEType || undefined,
|
|
106
|
+
encryptedCrypto: {
|
|
107
|
+
...baseCryptoNodeMetadata,
|
|
108
|
+
file: {
|
|
109
|
+
base64ContentKeyPacket: token.ContentKeyPacket,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
throw new Error(`Unknown node type: ${token.LinkType}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function linkToEncryptedNode(
|
|
119
|
+
logger: Logger,
|
|
120
|
+
token: string,
|
|
121
|
+
link: GetTokenFolderChildrenResponse['Links'][0],
|
|
122
|
+
): EncryptedNode {
|
|
123
|
+
const baseNodeMetadata = {
|
|
124
|
+
// Internal metadata
|
|
125
|
+
hash: link.Hash || undefined,
|
|
126
|
+
encryptedName: link.Name,
|
|
127
|
+
|
|
128
|
+
// Basic node metadata
|
|
129
|
+
uid: makeNodeUid(token, link.LinkID),
|
|
130
|
+
parentUid: link.ParentLinkID ? makeNodeUid(token, link.ParentLinkID) : undefined,
|
|
131
|
+
type: nodeTypeNumberToNodeType(logger, link.Type),
|
|
132
|
+
creationTime: new Date(), // TODO
|
|
133
|
+
totalStorageSize: link.TotalSize,
|
|
134
|
+
|
|
135
|
+
isShared: false,
|
|
136
|
+
directRole: MemberRole.Viewer, // TODO
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const baseCryptoNodeMetadata = {
|
|
140
|
+
signatureEmail: link.SignatureEmail || undefined,
|
|
141
|
+
armoredKey: link.NodeKey,
|
|
142
|
+
armoredNodePassphrase: link.NodePassphrase,
|
|
143
|
+
armoredNodePassphraseSignature: link.NodePassphraseSignature || undefined,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
if (link.Type === 1 && link.FolderProperties) {
|
|
147
|
+
return {
|
|
148
|
+
...baseNodeMetadata,
|
|
149
|
+
encryptedCrypto: {
|
|
150
|
+
...baseCryptoNodeMetadata,
|
|
151
|
+
folder: {
|
|
152
|
+
armoredHashKey: link.FolderProperties.NodeHashKey as string,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (link.Type === 2 && link.FileProperties?.ContentKeyPacket) {
|
|
159
|
+
return {
|
|
160
|
+
...baseNodeMetadata,
|
|
161
|
+
totalStorageSize: link.FileProperties.ActiveRevision?.Size || undefined,
|
|
162
|
+
mediaType: link.MIMEType || undefined,
|
|
163
|
+
encryptedCrypto: {
|
|
164
|
+
...baseCryptoNodeMetadata,
|
|
165
|
+
file: {
|
|
166
|
+
base64ContentKeyPacket: link.FileProperties.ContentKeyPacket,
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
throw new Error(`Unknown node type: ${link.Type}`);
|
|
173
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { PrivateKey } from '../../crypto';
|
|
2
|
+
import { ProtonDriveCryptoCache, Logger } from '../../interface';
|
|
3
|
+
import { DecryptedNodeKeys } from './interface';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Provides caching for public link crypto material.
|
|
7
|
+
*
|
|
8
|
+
* The cache is responsible for serialising and deserialising public link
|
|
9
|
+
* crypto material.
|
|
10
|
+
*/
|
|
11
|
+
export class SharingPublicCryptoCache {
|
|
12
|
+
constructor(
|
|
13
|
+
private logger: Logger,
|
|
14
|
+
private driveCache: ProtonDriveCryptoCache,
|
|
15
|
+
) {
|
|
16
|
+
this.logger = logger;
|
|
17
|
+
this.driveCache = driveCache;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async setShareKey(shareKey: PrivateKey): Promise<void> {
|
|
21
|
+
await this.driveCache.setEntity(getShareKeyCacheKey(), {
|
|
22
|
+
publicShareKey: {
|
|
23
|
+
key: shareKey,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async getShareKey(): Promise<PrivateKey> {
|
|
29
|
+
const shareKeyData = await this.driveCache.getEntity(getShareKeyCacheKey());
|
|
30
|
+
if (!shareKeyData.publicShareKey) {
|
|
31
|
+
try {
|
|
32
|
+
await this.driveCache.removeEntities([getShareKeyCacheKey()]);
|
|
33
|
+
} catch (removingError: unknown) {
|
|
34
|
+
this.logger.warn(
|
|
35
|
+
`Failed to remove corrupted public share key from the cache: ${removingError instanceof Error ? removingError.message : removingError}`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
throw new Error('Failed to deserialize public share key');
|
|
39
|
+
}
|
|
40
|
+
return shareKeyData.publicShareKey.key;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async setNodeKeys(nodeUid: string, keys: DecryptedNodeKeys): Promise<void> {
|
|
44
|
+
const cacheUid = getNodeCacheKey(nodeUid);
|
|
45
|
+
await this.driveCache.setEntity(cacheUid, {
|
|
46
|
+
nodeKeys: keys,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async getNodeKeys(nodeUid: string): Promise<DecryptedNodeKeys> {
|
|
51
|
+
const nodeKeysData = await this.driveCache.getEntity(getNodeCacheKey(nodeUid));
|
|
52
|
+
if (!nodeKeysData.nodeKeys) {
|
|
53
|
+
try {
|
|
54
|
+
await this.removeNodeKeys([nodeUid]);
|
|
55
|
+
} catch (removingError: unknown) {
|
|
56
|
+
// The node keys will not be returned, thus SDK will re-fetch
|
|
57
|
+
// and re-cache it. Setting it again should then fix the problem.
|
|
58
|
+
this.logger.warn(
|
|
59
|
+
`Failed to remove corrupted public node keys from the cache: ${removingError instanceof Error ? removingError.message : removingError}`,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
throw new Error(`Failed to deserialize public node keys`);
|
|
63
|
+
}
|
|
64
|
+
return nodeKeysData.nodeKeys;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async removeNodeKeys(nodeUids: string[]): Promise<void> {
|
|
68
|
+
const cacheUids = nodeUids.map(getNodeCacheKey);
|
|
69
|
+
await this.driveCache.removeEntities(cacheUids);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getShareKeyCacheKey() {
|
|
74
|
+
return 'publicShareKey';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getNodeCacheKey(nodeUid: string) {
|
|
78
|
+
return `publicNodeKeys-${nodeUid}`;
|
|
79
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { c } from 'ttag';
|
|
2
|
+
|
|
3
|
+
import { DriveCrypto, PrivateKey, VERIFICATION_STATUS } from '../../crypto';
|
|
4
|
+
import { getVerificationMessage } from '../errors';
|
|
5
|
+
import {
|
|
6
|
+
resultOk,
|
|
7
|
+
resultError,
|
|
8
|
+
Author,
|
|
9
|
+
AnonymousUser,
|
|
10
|
+
ProtonDriveTelemetry,
|
|
11
|
+
MetricVerificationErrorField,
|
|
12
|
+
MetricVolumeType,
|
|
13
|
+
MetricsDecryptionErrorField,
|
|
14
|
+
Logger,
|
|
15
|
+
ProtonDriveAccount,
|
|
16
|
+
} from '../../interface';
|
|
17
|
+
import { NodesCryptoService } from '../nodes/cryptoService';
|
|
18
|
+
import { EncryptedShareCrypto } from './interface';
|
|
19
|
+
|
|
20
|
+
export class SharingPublicCryptoService extends NodesCryptoService {
|
|
21
|
+
constructor(
|
|
22
|
+
telemetry: ProtonDriveTelemetry,
|
|
23
|
+
driveCrypto: DriveCrypto,
|
|
24
|
+
account: ProtonDriveAccount,
|
|
25
|
+
private password: string,
|
|
26
|
+
) {
|
|
27
|
+
super(telemetry, driveCrypto, account, new SharingPublicCryptoReporter(telemetry));
|
|
28
|
+
this.password = password;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async decryptPublicLinkShareKey(encryptedShare: EncryptedShareCrypto): Promise<PrivateKey> {
|
|
32
|
+
const { key: shareKey } = await this.driveCrypto.decryptKeyWithSrpPassword(
|
|
33
|
+
this.password,
|
|
34
|
+
encryptedShare.base64UrlPasswordSalt,
|
|
35
|
+
encryptedShare.armoredKey,
|
|
36
|
+
encryptedShare.armoredPassphrase,
|
|
37
|
+
);
|
|
38
|
+
return shareKey;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
class SharingPublicCryptoReporter {
|
|
43
|
+
private logger: Logger;
|
|
44
|
+
private telemetry: ProtonDriveTelemetry;
|
|
45
|
+
|
|
46
|
+
constructor(telemetry: ProtonDriveTelemetry) {
|
|
47
|
+
this.telemetry = telemetry;
|
|
48
|
+
this.logger = telemetry.getLogger('sharingPublic-crypto');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async handleClaimedAuthor(
|
|
52
|
+
node: { uid: string; creationTime: Date },
|
|
53
|
+
field: MetricVerificationErrorField,
|
|
54
|
+
signatureType: string,
|
|
55
|
+
verified: VERIFICATION_STATUS,
|
|
56
|
+
verificationErrors?: Error[],
|
|
57
|
+
claimedAuthor?: string,
|
|
58
|
+
notAvailableVerificationKeys = false,
|
|
59
|
+
): Promise<Author> {
|
|
60
|
+
if (verified === VERIFICATION_STATUS.SIGNED_AND_VALID) {
|
|
61
|
+
return resultOk(claimedAuthor || (null as AnonymousUser));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return resultError({
|
|
65
|
+
claimedAuthor,
|
|
66
|
+
error: !claimedAuthor
|
|
67
|
+
? c('Info').t`Author is not provided on public link`
|
|
68
|
+
: getVerificationMessage(verified, verificationErrors, signatureType, notAvailableVerificationKeys),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
reportDecryptionError(
|
|
73
|
+
node: { uid: string; creationTime: Date },
|
|
74
|
+
field: MetricsDecryptionErrorField,
|
|
75
|
+
error: unknown,
|
|
76
|
+
) {
|
|
77
|
+
const fromBefore2024 = node.creationTime < new Date('2024-01-01');
|
|
78
|
+
|
|
79
|
+
this.logger.error(
|
|
80
|
+
`Failed to decrypt public link node ${node.uid} (from before 2024: ${fromBefore2024})`,
|
|
81
|
+
error,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
this.telemetry.recordMetric({
|
|
85
|
+
eventName: 'decryptionError',
|
|
86
|
+
volumeType: MetricVolumeType.SharedPublic,
|
|
87
|
+
field,
|
|
88
|
+
fromBefore2024,
|
|
89
|
+
error,
|
|
90
|
+
uid: node.uid,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
reportVerificationError() {
|
|
95
|
+
// Authors or signatures are not provided on public links.
|
|
96
|
+
// We do not report any signature verification errors at this moment.
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { DriveCrypto } from '../../crypto';
|
|
2
|
+
import { ProtonDriveCryptoCache, ProtonDriveTelemetry, ProtonDriveAccount } from '../../interface';
|
|
3
|
+
import { DriveAPIService } from '../apiService';
|
|
4
|
+
import { SharingPublicAPIService } from './apiService';
|
|
5
|
+
import { SharingPublicCryptoCache } from './cryptoCache';
|
|
6
|
+
import { SharingPublicCryptoService } from './cryptoService';
|
|
7
|
+
import { SharingPublicManager } from './manager';
|
|
8
|
+
|
|
9
|
+
export { SharingPublicSessionManager } from './session/manager';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Provides facade for the whole sharing public module.
|
|
13
|
+
*
|
|
14
|
+
* The sharing public module is responsible for handling public link data, including
|
|
15
|
+
* API communication, encryption, decryption, and caching.
|
|
16
|
+
*
|
|
17
|
+
* This facade provides internal interface that other modules can use to
|
|
18
|
+
* interact with the public links.
|
|
19
|
+
*/
|
|
20
|
+
export function initSharingPublicModule(
|
|
21
|
+
telemetry: ProtonDriveTelemetry,
|
|
22
|
+
apiService: DriveAPIService,
|
|
23
|
+
driveCryptoCache: ProtonDriveCryptoCache,
|
|
24
|
+
driveCrypto: DriveCrypto,
|
|
25
|
+
account: ProtonDriveAccount,
|
|
26
|
+
token: string,
|
|
27
|
+
password: string,
|
|
28
|
+
) {
|
|
29
|
+
const api = new SharingPublicAPIService(telemetry.getLogger('sharingPublic-api'), apiService);
|
|
30
|
+
const cryptoCache = new SharingPublicCryptoCache(telemetry.getLogger('sharingPublic-crypto'), driveCryptoCache);
|
|
31
|
+
const cryptoService = new SharingPublicCryptoService(telemetry, driveCrypto, account, password);
|
|
32
|
+
const manager = new SharingPublicManager(
|
|
33
|
+
telemetry.getLogger('sharingPublic-nodes'),
|
|
34
|
+
api,
|
|
35
|
+
cryptoCache,
|
|
36
|
+
cryptoService,
|
|
37
|
+
token,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return manager;
|
|
41
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// TODO: use them directly, or avoid them completely
|
|
2
|
+
export type {
|
|
3
|
+
EncryptedNode,
|
|
4
|
+
EncryptedNodeFolderCrypto,
|
|
5
|
+
EncryptedNodeFileCrypto,
|
|
6
|
+
DecryptedNode,
|
|
7
|
+
DecryptedNodeKeys,
|
|
8
|
+
} from '../nodes/interface';
|
|
9
|
+
|
|
10
|
+
export interface EncryptedShareCrypto {
|
|
11
|
+
base64UrlPasswordSalt: string;
|
|
12
|
+
armoredKey: string;
|
|
13
|
+
armoredPassphrase: string;
|
|
14
|
+
}
|