@protontech/drive-sdk 0.6.2 → 0.7.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/interface/index.d.ts +1 -0
- package/dist/interface/index.js.map +1 -1
- package/dist/interface/nodes.d.ts +14 -10
- package/dist/interface/nodes.js +5 -8
- package/dist/interface/nodes.js.map +1 -1
- package/dist/interface/photos.d.ts +62 -0
- package/dist/interface/photos.js +3 -0
- package/dist/interface/photos.js.map +1 -0
- package/dist/internal/apiService/apiService.d.ts +2 -2
- package/dist/internal/apiService/apiService.js.map +1 -1
- package/dist/internal/apiService/driveTypes.d.ts +1294 -517
- package/dist/internal/apiService/errors.js +4 -3
- package/dist/internal/apiService/errors.js.map +1 -1
- package/dist/internal/download/cryptoService.js +8 -6
- package/dist/internal/download/cryptoService.js.map +1 -1
- package/dist/internal/download/fileDownloader.d.ts +2 -1
- package/dist/internal/download/fileDownloader.js +6 -3
- package/dist/internal/download/fileDownloader.js.map +1 -1
- package/dist/internal/download/index.d.ts +1 -1
- package/dist/internal/download/index.js +3 -3
- package/dist/internal/download/index.js.map +1 -1
- package/dist/internal/errors.d.ts +1 -0
- package/dist/internal/errors.js +4 -0
- package/dist/internal/errors.js.map +1 -1
- package/dist/internal/nodes/apiService.d.ts +68 -16
- package/dist/internal/nodes/apiService.js +138 -85
- package/dist/internal/nodes/apiService.js.map +1 -1
- package/dist/internal/nodes/apiService.test.js +7 -5
- package/dist/internal/nodes/apiService.test.js.map +1 -1
- package/dist/internal/nodes/cache.d.ts +16 -8
- package/dist/internal/nodes/cache.js +19 -5
- package/dist/internal/nodes/cache.js.map +1 -1
- package/dist/internal/nodes/cache.test.js +1 -0
- package/dist/internal/nodes/cache.test.js.map +1 -1
- package/dist/internal/nodes/cryptoReporter.d.ts +3 -3
- package/dist/internal/nodes/cryptoReporter.js.map +1 -1
- package/dist/internal/nodes/cryptoService.d.ts +13 -22
- package/dist/internal/nodes/cryptoService.js +47 -16
- package/dist/internal/nodes/cryptoService.js.map +1 -1
- package/dist/internal/nodes/cryptoService.test.js +262 -17
- package/dist/internal/nodes/cryptoService.test.js.map +1 -1
- package/dist/internal/nodes/events.d.ts +2 -2
- package/dist/internal/nodes/events.js.map +1 -1
- package/dist/internal/nodes/index.test.js +1 -0
- package/dist/internal/nodes/index.test.js.map +1 -1
- package/dist/internal/nodes/interface.d.ts +14 -3
- package/dist/internal/nodes/nodesAccess.d.ts +36 -20
- package/dist/internal/nodes/nodesAccess.js +54 -29
- package/dist/internal/nodes/nodesAccess.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.d.ts +34 -14
- package/dist/internal/nodes/nodesManagement.js +44 -31
- package/dist/internal/nodes/nodesManagement.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.test.js +60 -14
- package/dist/internal/nodes/nodesManagement.test.js.map +1 -1
- package/dist/internal/nodes/nodesRevisions.d.ts +2 -2
- package/dist/internal/nodes/nodesRevisions.js.map +1 -1
- package/dist/internal/photos/albums.d.ts +2 -2
- package/dist/internal/photos/albums.js.map +1 -1
- package/dist/internal/photos/index.d.ts +19 -3
- package/dist/internal/photos/index.js +38 -8
- package/dist/internal/photos/index.js.map +1 -1
- package/dist/internal/photos/interface.d.ts +18 -9
- package/dist/internal/photos/nodes.d.ts +57 -0
- package/dist/internal/photos/nodes.js +165 -0
- package/dist/internal/photos/nodes.js.map +1 -0
- package/dist/internal/photos/timeline.d.ts +2 -2
- package/dist/internal/photos/timeline.js.map +1 -1
- package/dist/internal/photos/timeline.test.js.map +1 -1
- package/dist/internal/photos/upload.d.ts +2 -2
- package/dist/internal/photos/upload.js.map +1 -1
- package/dist/internal/sharingPublic/index.d.ts +6 -6
- package/dist/internal/sharingPublic/index.js +8 -7
- package/dist/internal/sharingPublic/index.js.map +1 -1
- package/dist/internal/sharingPublic/nodes.d.ts +16 -3
- package/dist/internal/sharingPublic/nodes.js +34 -2
- package/dist/internal/sharingPublic/nodes.js.map +1 -1
- package/dist/internal/sharingPublic/unauthApiService.d.ts +17 -0
- package/dist/internal/sharingPublic/unauthApiService.js +31 -0
- package/dist/internal/sharingPublic/unauthApiService.js.map +1 -0
- package/dist/internal/sharingPublic/unauthApiService.test.d.ts +1 -0
- package/dist/internal/sharingPublic/unauthApiService.test.js +27 -0
- package/dist/internal/sharingPublic/unauthApiService.test.js.map +1 -0
- package/dist/internal/upload/apiService.d.ts +4 -3
- package/dist/internal/upload/apiService.js.map +1 -1
- package/dist/internal/upload/cryptoService.d.ts +8 -3
- package/dist/internal/upload/cryptoService.js +45 -9
- package/dist/internal/upload/cryptoService.js.map +1 -1
- package/dist/internal/upload/fileUploader.test.js +1 -1
- package/dist/internal/upload/fileUploader.test.js.map +1 -1
- package/dist/internal/upload/interface.d.ts +25 -13
- package/dist/internal/upload/manager.js +7 -4
- package/dist/internal/upload/manager.js.map +1 -1
- package/dist/internal/upload/manager.test.js +5 -4
- package/dist/internal/upload/manager.test.js.map +1 -1
- package/dist/internal/upload/streamUploader.js +9 -4
- package/dist/internal/upload/streamUploader.js.map +1 -1
- package/dist/internal/upload/streamUploader.test.js +8 -5
- package/dist/internal/upload/streamUploader.test.js.map +1 -1
- package/dist/protonDriveClient.d.ts +11 -2
- package/dist/protonDriveClient.js +20 -4
- package/dist/protonDriveClient.js.map +1 -1
- package/dist/protonDrivePhotosClient.d.ts +8 -8
- package/dist/protonDrivePhotosClient.js +8 -9
- package/dist/protonDrivePhotosClient.js.map +1 -1
- package/dist/protonDrivePublicLinkClient.d.ts +9 -2
- package/dist/protonDrivePublicLinkClient.js +16 -5
- package/dist/protonDrivePublicLinkClient.js.map +1 -1
- package/dist/transformers.d.ts +7 -2
- package/dist/transformers.js +37 -0
- package/dist/transformers.js.map +1 -1
- package/package.json +1 -1
- package/src/interface/index.ts +1 -0
- package/src/interface/nodes.ts +14 -11
- package/src/interface/photos.ts +67 -0
- package/src/internal/apiService/apiService.ts +2 -2
- package/src/internal/apiService/driveTypes.ts +1294 -517
- package/src/internal/apiService/errors.ts +5 -4
- package/src/internal/download/cryptoService.ts +13 -6
- package/src/internal/download/fileDownloader.ts +4 -2
- package/src/internal/download/index.ts +3 -0
- package/src/internal/errors.ts +4 -0
- package/src/internal/nodes/apiService.test.ts +7 -5
- package/src/internal/nodes/apiService.ts +210 -124
- package/src/internal/nodes/cache.test.ts +1 -0
- package/src/internal/nodes/cache.ts +32 -13
- package/src/internal/nodes/cryptoReporter.ts +3 -3
- package/src/internal/nodes/cryptoService.test.ts +380 -18
- package/src/internal/nodes/cryptoService.ts +77 -36
- package/src/internal/nodes/events.ts +2 -2
- package/src/internal/nodes/index.test.ts +1 -0
- package/src/internal/nodes/interface.ts +17 -2
- package/src/internal/nodes/nodesAccess.ts +99 -54
- package/src/internal/nodes/nodesManagement.test.ts +69 -14
- package/src/internal/nodes/nodesManagement.ts +94 -48
- package/src/internal/nodes/nodesRevisions.ts +3 -3
- package/src/internal/photos/albums.ts +2 -2
- package/src/internal/photos/index.ts +45 -3
- package/src/internal/photos/interface.ts +21 -9
- package/src/internal/photos/nodes.ts +233 -0
- package/src/internal/photos/timeline.test.ts +2 -2
- package/src/internal/photos/timeline.ts +2 -2
- package/src/internal/photos/upload.ts +3 -3
- package/src/internal/sharingPublic/index.ts +7 -3
- package/src/internal/sharingPublic/nodes.ts +43 -2
- package/src/internal/sharingPublic/unauthApiService.test.ts +29 -0
- package/src/internal/sharingPublic/unauthApiService.ts +32 -0
- package/src/internal/upload/apiService.ts +4 -3
- package/src/internal/upload/cryptoService.ts +73 -12
- package/src/internal/upload/fileUploader.test.ts +1 -1
- package/src/internal/upload/interface.ts +24 -13
- package/src/internal/upload/manager.test.ts +5 -4
- package/src/internal/upload/manager.ts +7 -4
- package/src/internal/upload/streamUploader.test.ts +8 -5
- package/src/internal/upload/streamUploader.ts +10 -4
- package/src/protonDriveClient.ts +27 -5
- package/src/protonDrivePhotosClient.ts +23 -23
- package/src/protonDrivePublicLinkClient.ts +19 -3
- package/src/transformers.ts +49 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PrivateKey, SessionKey } from '../../crypto';
|
|
2
2
|
|
|
3
|
-
import { MetricVolumeType, ThumbnailType, Result, Revision } from '../../interface';
|
|
3
|
+
import { MetricVolumeType, ThumbnailType, Result, Revision, AnonymousUser } from '../../interface';
|
|
4
4
|
import { DecryptedNode } from '../nodes';
|
|
5
5
|
|
|
6
6
|
export type NodeRevisionDraft = {
|
|
@@ -22,7 +22,7 @@ export type NodeRevisionDraft = {
|
|
|
22
22
|
export type NodeRevisionDraftKeys = {
|
|
23
23
|
key: PrivateKey;
|
|
24
24
|
contentKeyPacketSessionKey: SessionKey;
|
|
25
|
-
|
|
25
|
+
signingKeys: NodeCryptoSigningKeys;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
export type NodeCrypto = {
|
|
@@ -51,13 +51,14 @@ export type NodeCrypto = {
|
|
|
51
51
|
encryptedName: string;
|
|
52
52
|
hash: string;
|
|
53
53
|
};
|
|
54
|
-
|
|
54
|
+
signingKeys: NodeCryptoSigningKeys;
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
export type
|
|
58
|
-
email: string;
|
|
59
|
-
addressId: string;
|
|
60
|
-
|
|
57
|
+
export type NodeCryptoSigningKeys = {
|
|
58
|
+
email: string | AnonymousUser;
|
|
59
|
+
addressId: string | AnonymousUser;
|
|
60
|
+
nameAndPassphraseSigningKey: PrivateKey;
|
|
61
|
+
contentSigningKey: PrivateKey;
|
|
61
62
|
};
|
|
62
63
|
|
|
63
64
|
export type EncryptedBlockMetadata = {
|
|
@@ -102,12 +103,9 @@ export interface NodesService {
|
|
|
102
103
|
contentKeyPacketSessionKey?: SessionKey;
|
|
103
104
|
hashKey?: Uint8Array;
|
|
104
105
|
}>;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
addressKey: PrivateKey;
|
|
109
|
-
addressKeyId: string;
|
|
110
|
-
}>;
|
|
106
|
+
getNodeSigningKeys(
|
|
107
|
+
uids: { nodeUid: string; parentNodeUid?: string } | { nodeUid?: string; parentNodeUid: string },
|
|
108
|
+
): Promise<NodeSigningKeys>;
|
|
111
109
|
notifyChildCreated(nodeUid: string): Promise<void>;
|
|
112
110
|
notifyNodeChanged(nodeUid: string): Promise<void>;
|
|
113
111
|
}
|
|
@@ -126,6 +124,19 @@ export interface NodesServiceNode {
|
|
|
126
124
|
activeRevision?: Result<Revision, Error>;
|
|
127
125
|
}
|
|
128
126
|
|
|
127
|
+
export type NodeSigningKeys =
|
|
128
|
+
| {
|
|
129
|
+
type: 'userAddress';
|
|
130
|
+
email: string;
|
|
131
|
+
addressId: string;
|
|
132
|
+
key: PrivateKey;
|
|
133
|
+
}
|
|
134
|
+
| {
|
|
135
|
+
type: 'nodeKey';
|
|
136
|
+
nodeKey?: PrivateKey;
|
|
137
|
+
parentNodeKey?: PrivateKey;
|
|
138
|
+
};
|
|
139
|
+
|
|
129
140
|
/**
|
|
130
141
|
* Interface describing the dependencies to the shares module.
|
|
131
142
|
*/
|
|
@@ -50,7 +50,7 @@ describe('UploadManager', () => {
|
|
|
50
50
|
encryptedName: 'newNode:encryptedName',
|
|
51
51
|
hash: 'newNode:hash',
|
|
52
52
|
},
|
|
53
|
-
|
|
53
|
+
signingKeys: {
|
|
54
54
|
email: 'signatureEmail',
|
|
55
55
|
},
|
|
56
56
|
}),
|
|
@@ -69,7 +69,8 @@ describe('UploadManager', () => {
|
|
|
69
69
|
hashKey: 'parentNode:hashKey',
|
|
70
70
|
key: 'parentNode:nodekey',
|
|
71
71
|
}),
|
|
72
|
-
|
|
72
|
+
getNodeSigningKeys: jest.fn().mockResolvedValue({
|
|
73
|
+
type: 'userAddress',
|
|
73
74
|
email: 'signatureEmail',
|
|
74
75
|
addressId: 'addressId',
|
|
75
76
|
}),
|
|
@@ -100,7 +101,7 @@ describe('UploadManager', () => {
|
|
|
100
101
|
nodeKeys: {
|
|
101
102
|
key: 'newNode:key',
|
|
102
103
|
contentKeyPacketSessionKey: 'newNode:ContentKeyPacketSessionKey',
|
|
103
|
-
|
|
104
|
+
signingKeys: {
|
|
104
105
|
email: 'signatureEmail',
|
|
105
106
|
},
|
|
106
107
|
},
|
|
@@ -153,7 +154,7 @@ describe('UploadManager', () => {
|
|
|
153
154
|
nodeKeys: {
|
|
154
155
|
key: 'newNode:key',
|
|
155
156
|
contentKeyPacketSessionKey: 'newNode:ContentKeyPacketSessionKey',
|
|
156
|
-
|
|
157
|
+
signingKeys: {
|
|
157
158
|
email: 'signatureEmail',
|
|
158
159
|
},
|
|
159
160
|
},
|
|
@@ -57,7 +57,7 @@ export class UploadManager {
|
|
|
57
57
|
nodeKeys: {
|
|
58
58
|
key: generatedNodeCrypto.nodeKeys.decrypted.key,
|
|
59
59
|
contentKeyPacketSessionKey: generatedNodeCrypto.contentKey.decrypted.contentKeyPacketSessionKey,
|
|
60
|
-
|
|
60
|
+
signingKeys: generatedNodeCrypto.signingKeys,
|
|
61
61
|
},
|
|
62
62
|
parentNodeKeys: {
|
|
63
63
|
hashKey: parentKeys.hashKey,
|
|
@@ -93,7 +93,7 @@ export class UploadManager {
|
|
|
93
93
|
base64ContentKeyPacket: generatedNodeCrypto.contentKey.encrypted.base64ContentKeyPacket,
|
|
94
94
|
armoredContentKeyPacketSignature:
|
|
95
95
|
generatedNodeCrypto.contentKey.encrypted.armoredContentKeyPacketSignature,
|
|
96
|
-
signatureEmail: generatedNodeCrypto.
|
|
96
|
+
signatureEmail: generatedNodeCrypto.signingKeys.email,
|
|
97
97
|
});
|
|
98
98
|
return result;
|
|
99
99
|
} catch (error: unknown) {
|
|
@@ -192,7 +192,10 @@ export class UploadManager {
|
|
|
192
192
|
throw new ValidationError(c('Error').t`Creating revisions in non-files is not allowed`);
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
const
|
|
195
|
+
const signingKeys = await this.cryptoService.getSigningKeysForExistingNode({
|
|
196
|
+
nodeUid,
|
|
197
|
+
parentNodeUid: node.parentUid,
|
|
198
|
+
});
|
|
196
199
|
|
|
197
200
|
const { nodeRevisionUid } = await this.apiService.createDraftRevision(nodeUid, {
|
|
198
201
|
currentRevisionUid: node.activeRevision.value.uid,
|
|
@@ -205,7 +208,7 @@ export class UploadManager {
|
|
|
205
208
|
nodeKeys: {
|
|
206
209
|
key: nodeKeys.key,
|
|
207
210
|
contentKeyPacketSessionKey: nodeKeys.contentKeyPacketSessionKey,
|
|
208
|
-
|
|
211
|
+
signingKeys,
|
|
209
212
|
},
|
|
210
213
|
};
|
|
211
214
|
}
|
|
@@ -110,7 +110,9 @@ describe('StreamUploader', () => {
|
|
|
110
110
|
nodeRevisionUid: 'revisionUid',
|
|
111
111
|
nodeUid: 'nodeUid',
|
|
112
112
|
nodeKeys: {
|
|
113
|
-
|
|
113
|
+
signingKeys: {
|
|
114
|
+
addressId: 'addressId',
|
|
115
|
+
},
|
|
114
116
|
},
|
|
115
117
|
} as NodeRevisionDraft;
|
|
116
118
|
|
|
@@ -312,8 +314,9 @@ describe('StreamUploader', () => {
|
|
|
312
314
|
throw new Error('Failed to encrypt block');
|
|
313
315
|
});
|
|
314
316
|
|
|
315
|
-
//
|
|
316
|
-
|
|
317
|
+
// Thumbnail are uploaded with the first content block. If the
|
|
318
|
+
// content block fails to encrypt, nothing is uploaded.
|
|
319
|
+
await verifyFailure('Failed to encrypt block', 0);
|
|
317
320
|
// 1 block + 1 retry, others are skipped
|
|
318
321
|
expect(cryptoService.encryptBlock).toHaveBeenCalledTimes(2);
|
|
319
322
|
});
|
|
@@ -415,7 +418,7 @@ describe('StreamUploader', () => {
|
|
|
415
418
|
expect(apiService.requestBlockUpload).toHaveBeenCalledTimes(2);
|
|
416
419
|
expect(apiService.requestBlockUpload).toHaveBeenCalledWith(
|
|
417
420
|
revisionDraft.nodeRevisionUid,
|
|
418
|
-
revisionDraft.nodeKeys.
|
|
421
|
+
revisionDraft.nodeKeys.signingKeys.addressId,
|
|
419
422
|
{
|
|
420
423
|
contentBlocks: [
|
|
421
424
|
{
|
|
@@ -436,7 +439,7 @@ describe('StreamUploader', () => {
|
|
|
436
439
|
describe('verifyIntegrity', () => {
|
|
437
440
|
it('should report block verification error', async () => {
|
|
438
441
|
blockVerifier.verifyBlock = jest.fn().mockRejectedValue(new IntegrityError('Block verification error'));
|
|
439
|
-
await verifyFailure('Block verification error',
|
|
442
|
+
await verifyFailure('Block verification error', 0);
|
|
440
443
|
expect(telemetry.logBlockVerificationError).toHaveBeenCalledWith(false);
|
|
441
444
|
});
|
|
442
445
|
|
|
@@ -319,7 +319,7 @@ export class StreamUploader {
|
|
|
319
319
|
this.logger.info(`Requesting upload tokens for ${this.encryptedBlocks.size} blocks`);
|
|
320
320
|
const uploadTokens = await this.apiService.requestBlockUpload(
|
|
321
321
|
this.revisionDraft.nodeRevisionUid,
|
|
322
|
-
this.revisionDraft.nodeKeys.
|
|
322
|
+
this.revisionDraft.nodeKeys.signingKeys.addressId,
|
|
323
323
|
{
|
|
324
324
|
contentBlocks: Array.from(
|
|
325
325
|
this.encryptedBlocks.values().map((block) => ({
|
|
@@ -340,6 +340,12 @@ export class StreamUploader {
|
|
|
340
340
|
},
|
|
341
341
|
);
|
|
342
342
|
|
|
343
|
+
// If the upload was aborted while requesting next upload tokens,
|
|
344
|
+
// do not schedule any next upload.
|
|
345
|
+
if (this.isUploadAborted) {
|
|
346
|
+
throw this.error || new AbortError();
|
|
347
|
+
}
|
|
348
|
+
|
|
343
349
|
for (const thumbnailToken of uploadTokens.thumbnailTokens) {
|
|
344
350
|
let encryptedThumbnail = this.encryptedThumbnails.get(thumbnailToken.type);
|
|
345
351
|
if (!encryptedThumbnail) {
|
|
@@ -418,7 +424,7 @@ export class StreamUploader {
|
|
|
418
424
|
break;
|
|
419
425
|
} catch (error: unknown) {
|
|
420
426
|
// Do not retry or report anything if the upload was aborted.
|
|
421
|
-
if (error instanceof AbortError) {
|
|
427
|
+
if (error instanceof AbortError || this.isUploadAborted) {
|
|
422
428
|
throw error;
|
|
423
429
|
}
|
|
424
430
|
|
|
@@ -485,7 +491,7 @@ export class StreamUploader {
|
|
|
485
491
|
break;
|
|
486
492
|
} catch (error: unknown) {
|
|
487
493
|
// Do not retry or report anything if the upload was aborted.
|
|
488
|
-
if (error instanceof AbortError) {
|
|
494
|
+
if (error instanceof AbortError || this.isUploadAborted) {
|
|
489
495
|
throw error;
|
|
490
496
|
}
|
|
491
497
|
|
|
@@ -501,7 +507,7 @@ export class StreamUploader {
|
|
|
501
507
|
logger.warn(`Token expired, fetching new token and retrying`);
|
|
502
508
|
const uploadTokens = await this.apiService.requestBlockUpload(
|
|
503
509
|
this.revisionDraft.nodeRevisionUid,
|
|
504
|
-
this.revisionDraft.nodeKeys.
|
|
510
|
+
this.revisionDraft.nodeKeys.signingKeys.addressId,
|
|
505
511
|
{
|
|
506
512
|
contentBlocks: [
|
|
507
513
|
{
|
package/src/protonDriveClient.ts
CHANGED
|
@@ -106,7 +106,11 @@ export class ProtonDriveClient {
|
|
|
106
106
|
* Experimental feature to authenticate a public link and
|
|
107
107
|
* return the client for the public link to access it.
|
|
108
108
|
*/
|
|
109
|
-
authPublicLink: (
|
|
109
|
+
authPublicLink: (
|
|
110
|
+
url: string,
|
|
111
|
+
customPassword?: string,
|
|
112
|
+
isAnonymousContext?: boolean,
|
|
113
|
+
) => Promise<ProtonDrivePublicLinkClient>;
|
|
110
114
|
};
|
|
111
115
|
|
|
112
116
|
constructor({
|
|
@@ -222,7 +226,7 @@ export class ProtonDriveClient {
|
|
|
222
226
|
this.logger.info(`Getting info for public link ${url}`);
|
|
223
227
|
return this.publicSessionManager.getInfo(url);
|
|
224
228
|
},
|
|
225
|
-
authPublicLink: async (url: string, customPassword?: string) => {
|
|
229
|
+
authPublicLink: async (url: string, customPassword?: string, isAnonymousContext: boolean = false) => {
|
|
226
230
|
this.logger.info(`Authenticating public link ${url}`);
|
|
227
231
|
const { httpClient, token, shareKey, rootUid } = await this.publicSessionManager.auth(
|
|
228
232
|
url,
|
|
@@ -239,6 +243,7 @@ export class ProtonDriveClient {
|
|
|
239
243
|
token,
|
|
240
244
|
publicShareKey: shareKey,
|
|
241
245
|
publicRootNodeUid: rootUid,
|
|
246
|
+
isAnonymousContext,
|
|
242
247
|
});
|
|
243
248
|
},
|
|
244
249
|
};
|
|
@@ -419,6 +424,12 @@ export class ProtonDriveClient {
|
|
|
419
424
|
* The operation is performed node by node and the results are yielded
|
|
420
425
|
* as they are available. Order of the results is not guaranteed.
|
|
421
426
|
*
|
|
427
|
+
* The `nodeUids` can be a list of node entities or their UIDs, or a list
|
|
428
|
+
* of objects with `uid` and `name` properties where the name is the new
|
|
429
|
+
* name of the copied node. By default, the name is the same as the
|
|
430
|
+
* original node. Use `getAvailableName` to get the available name for the
|
|
431
|
+
* new node in the target parent node in case of a name conflict.
|
|
432
|
+
*
|
|
422
433
|
* If one of the nodes fails to copy, the operation continues with the
|
|
423
434
|
* rest of the nodes. Use `NodeResult` to check the status of the action.
|
|
424
435
|
*
|
|
@@ -428,12 +439,23 @@ export class ProtonDriveClient {
|
|
|
428
439
|
* @returns An async generator of the results of the copy operation
|
|
429
440
|
*/
|
|
430
441
|
async *copyNodes(
|
|
431
|
-
|
|
442
|
+
nodesOrNodeUidsOrWithNames: (NodeOrUid | { uid: string; name: string })[],
|
|
432
443
|
newParentNodeUid: NodeOrUid,
|
|
433
444
|
signal?: AbortSignal,
|
|
434
445
|
): AsyncGenerator<NodeResultWithNewUid> {
|
|
435
|
-
this.logger.info(`Copying ${
|
|
436
|
-
|
|
446
|
+
this.logger.info(`Copying ${nodesOrNodeUidsOrWithNames.length} nodes to ${getUid(newParentNodeUid)}`);
|
|
447
|
+
|
|
448
|
+
const nodeUidsOrWithNames = nodesOrNodeUidsOrWithNames.map((param) => {
|
|
449
|
+
if (typeof param === 'string') {
|
|
450
|
+
return param;
|
|
451
|
+
}
|
|
452
|
+
if ('uid' in param && 'name' in param && typeof param.uid === 'string' && typeof param.name === 'string') {
|
|
453
|
+
return { uid: param.uid, name: param.name };
|
|
454
|
+
}
|
|
455
|
+
return getUid(param);
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
yield* this.nodes.management.copyNodes(nodeUidsOrWithNames, getUid(newParentNodeUid), signal);
|
|
437
459
|
}
|
|
438
460
|
|
|
439
461
|
/**
|
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
Logger,
|
|
3
3
|
ProtonDriveClientContructorParameters,
|
|
4
4
|
NodeOrUid,
|
|
5
|
-
|
|
5
|
+
MaybeMissingPhotoNode,
|
|
6
6
|
UploadMetadata,
|
|
7
7
|
FileDownloader,
|
|
8
8
|
FileUploader,
|
|
9
9
|
SDKEvent,
|
|
10
|
-
|
|
10
|
+
MaybePhotoNode,
|
|
11
11
|
ThumbnailType,
|
|
12
12
|
ThumbnailResult,
|
|
13
13
|
ShareNodeSettings,
|
|
@@ -22,22 +22,22 @@ import { getConfig } from './config';
|
|
|
22
22
|
import { DriveCrypto } from './crypto';
|
|
23
23
|
import { Telemetry } from './telemetry';
|
|
24
24
|
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
convertInternalMissingPhotoNodeIterator,
|
|
26
|
+
convertInternalPhotoNode,
|
|
27
|
+
convertInternalPhotoNodeIterator,
|
|
28
|
+
convertInternalPhotoNodePromise,
|
|
29
29
|
getUid,
|
|
30
30
|
getUids,
|
|
31
31
|
} from './transformers';
|
|
32
32
|
import { DriveAPIService } from './internal/apiService';
|
|
33
33
|
import { initDownloadModule } from './internal/download';
|
|
34
34
|
import { DriveEventsService, DriveListener, EventSubscription } from './internal/events';
|
|
35
|
-
import { initNodesModule } from './internal/nodes';
|
|
36
35
|
import {
|
|
37
36
|
PHOTOS_SHARE_TARGET_TYPES,
|
|
38
37
|
initPhotosModule,
|
|
39
38
|
initPhotoSharesModule,
|
|
40
39
|
initPhotoUploadModule,
|
|
40
|
+
initPhotosNodesModule,
|
|
41
41
|
} from './internal/photos';
|
|
42
42
|
import { SDKEvents } from './internal/sdkEvents';
|
|
43
43
|
import { initSharesModule } from './internal/shares';
|
|
@@ -56,7 +56,7 @@ export class ProtonDrivePhotosClient {
|
|
|
56
56
|
private sdkEvents: SDKEvents;
|
|
57
57
|
private events: DriveEventsService;
|
|
58
58
|
private photoShares: ReturnType<typeof initPhotoSharesModule>;
|
|
59
|
-
private nodes: ReturnType<typeof
|
|
59
|
+
private nodes: ReturnType<typeof initPhotosNodesModule>;
|
|
60
60
|
private sharing: ReturnType<typeof initSharingModule>;
|
|
61
61
|
private download: ReturnType<typeof initDownloadModule>;
|
|
62
62
|
private upload: ReturnType<typeof initPhotoUploadModule>;
|
|
@@ -107,7 +107,7 @@ export class ProtonDrivePhotosClient {
|
|
|
107
107
|
cryptoModule,
|
|
108
108
|
coreShares,
|
|
109
109
|
);
|
|
110
|
-
this.nodes =
|
|
110
|
+
this.nodes = initPhotosNodesModule(
|
|
111
111
|
telemetry,
|
|
112
112
|
apiService,
|
|
113
113
|
entitiesCache,
|
|
@@ -224,9 +224,9 @@ export class ProtonDrivePhotosClient {
|
|
|
224
224
|
*
|
|
225
225
|
* See `ProtonDriveClient.iterateTrashedNodes` for more information.
|
|
226
226
|
*/
|
|
227
|
-
async *iterateTrashedNodes(signal?: AbortSignal): AsyncGenerator<
|
|
227
|
+
async *iterateTrashedNodes(signal?: AbortSignal): AsyncGenerator<MaybePhotoNode> {
|
|
228
228
|
this.logger.info('Iterating trashed nodes');
|
|
229
|
-
yield*
|
|
229
|
+
yield * convertInternalPhotoNodeIterator(this.nodes.access.iterateTrashedNodes(signal));
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
/**
|
|
@@ -234,10 +234,10 @@ export class ProtonDrivePhotosClient {
|
|
|
234
234
|
*
|
|
235
235
|
* See `ProtonDriveClient.iterateNodes` for more information.
|
|
236
236
|
*/
|
|
237
|
-
async *iterateNodes(nodeUids: NodeOrUid[], signal?: AbortSignal): AsyncGenerator<
|
|
237
|
+
async *iterateNodes(nodeUids: NodeOrUid[], signal?: AbortSignal): AsyncGenerator<MaybeMissingPhotoNode> {
|
|
238
238
|
this.logger.info(`Iterating ${nodeUids.length} nodes`);
|
|
239
239
|
// TODO: expose photo type
|
|
240
|
-
yield*
|
|
240
|
+
yield * convertInternalMissingPhotoNodeIterator(this.nodes.access.iterateNodes(getUids(nodeUids), signal));
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
/**
|
|
@@ -245,9 +245,9 @@ export class ProtonDrivePhotosClient {
|
|
|
245
245
|
*
|
|
246
246
|
* See `ProtonDriveClient.getNode` for more information.
|
|
247
247
|
*/
|
|
248
|
-
async getNode(nodeUid: NodeOrUid): Promise<
|
|
248
|
+
async getNode(nodeUid: NodeOrUid): Promise<MaybePhotoNode> {
|
|
249
249
|
this.logger.info(`Getting node ${getUid(nodeUid)}`);
|
|
250
|
-
return
|
|
250
|
+
return convertInternalPhotoNodePromise(this.nodes.access.getNode(getUid(nodeUid)));
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
/**
|
|
@@ -255,9 +255,9 @@ export class ProtonDrivePhotosClient {
|
|
|
255
255
|
*
|
|
256
256
|
* See `ProtonDriveClient.renameNode` for more information.
|
|
257
257
|
*/
|
|
258
|
-
async renameNode(nodeUid: NodeOrUid, newName: string): Promise<
|
|
258
|
+
async renameNode(nodeUid: NodeOrUid, newName: string): Promise<MaybePhotoNode> {
|
|
259
259
|
this.logger.info(`Renaming node ${getUid(nodeUid)}`);
|
|
260
|
-
return
|
|
260
|
+
return convertInternalPhotoNodePromise(this.nodes.management.renameNode(getUid(nodeUid), newName));
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
/**
|
|
@@ -305,9 +305,9 @@ export class ProtonDrivePhotosClient {
|
|
|
305
305
|
*
|
|
306
306
|
* See `ProtonDriveClient.iterateSharedNodes` for more information.
|
|
307
307
|
*/
|
|
308
|
-
async *iterateSharedNodes(signal?: AbortSignal): AsyncGenerator<
|
|
308
|
+
async *iterateSharedNodes(signal?: AbortSignal): AsyncGenerator<MaybePhotoNode> {
|
|
309
309
|
this.logger.info('Iterating shared nodes by me');
|
|
310
|
-
yield*
|
|
310
|
+
yield * convertInternalPhotoNodeIterator(this.sharing.access.iterateSharedNodes(signal));
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
/**
|
|
@@ -315,11 +315,11 @@ export class ProtonDrivePhotosClient {
|
|
|
315
315
|
*
|
|
316
316
|
* See `ProtonDriveClient.iterateSharedNodesWithMe` for more information.
|
|
317
317
|
*/
|
|
318
|
-
async *iterateSharedNodesWithMe(signal?: AbortSignal): AsyncGenerator<
|
|
318
|
+
async *iterateSharedNodesWithMe(signal?: AbortSignal): AsyncGenerator<MaybePhotoNode> {
|
|
319
319
|
this.logger.info('Iterating shared nodes with me');
|
|
320
320
|
|
|
321
321
|
for await (const node of this.sharing.access.iterateSharedNodesWithMe(signal)) {
|
|
322
|
-
yield
|
|
322
|
+
yield convertInternalPhotoNode(node);
|
|
323
323
|
}
|
|
324
324
|
}
|
|
325
325
|
|
|
@@ -482,9 +482,9 @@ export class ProtonDrivePhotosClient {
|
|
|
482
482
|
*
|
|
483
483
|
* The output is not sorted and the order of the nodes is not guaranteed.
|
|
484
484
|
*/
|
|
485
|
-
async *iterateAlbums(signal?: AbortSignal): AsyncGenerator<
|
|
485
|
+
async *iterateAlbums(signal?: AbortSignal): AsyncGenerator<MaybePhotoNode> {
|
|
486
486
|
this.logger.info('Iterating albums');
|
|
487
487
|
// TODO: expose album type
|
|
488
|
-
yield*
|
|
488
|
+
yield * convertInternalPhotoNodeIterator(this.photos.albums.iterateAlbums(signal));
|
|
489
489
|
}
|
|
490
490
|
}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
UploadMetadata,
|
|
19
19
|
FileUploader,
|
|
20
20
|
NodeResult,
|
|
21
|
+
SDKEvent,
|
|
21
22
|
} from './interface';
|
|
22
23
|
import { Telemetry } from './telemetry';
|
|
23
24
|
import {
|
|
@@ -27,10 +28,9 @@ import {
|
|
|
27
28
|
convertInternalMissingNodeIterator,
|
|
28
29
|
getUids,
|
|
29
30
|
} from './transformers';
|
|
30
|
-
import { DriveAPIService } from './internal/apiService';
|
|
31
31
|
import { initDownloadModule } from './internal/download';
|
|
32
32
|
import { SDKEvents } from './internal/sdkEvents';
|
|
33
|
-
import { initSharingPublicModule } from './internal/sharingPublic';
|
|
33
|
+
import { initSharingPublicModule, UnauthDriveAPIService } from './internal/sharingPublic';
|
|
34
34
|
import { initUploadModule } from './internal/upload';
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -81,6 +81,7 @@ export class ProtonDrivePublicLinkClient {
|
|
|
81
81
|
token,
|
|
82
82
|
publicShareKey,
|
|
83
83
|
publicRootNodeUid,
|
|
84
|
+
isAnonymousContext,
|
|
84
85
|
}: {
|
|
85
86
|
httpClient: ProtonDriveHTTPClient;
|
|
86
87
|
account: ProtonDriveAccount;
|
|
@@ -92,6 +93,7 @@ export class ProtonDrivePublicLinkClient {
|
|
|
92
93
|
token: string;
|
|
93
94
|
publicShareKey: PrivateKey;
|
|
94
95
|
publicRootNodeUid: string;
|
|
96
|
+
isAnonymousContext: boolean;
|
|
95
97
|
}) {
|
|
96
98
|
if (!telemetry) {
|
|
97
99
|
telemetry = new Telemetry();
|
|
@@ -105,7 +107,7 @@ export class ProtonDrivePublicLinkClient {
|
|
|
105
107
|
const fullConfig = getConfig(config);
|
|
106
108
|
this.sdkEvents = new SDKEvents(telemetry);
|
|
107
109
|
|
|
108
|
-
const apiService = new
|
|
110
|
+
const apiService = new UnauthDriveAPIService(
|
|
109
111
|
telemetry,
|
|
110
112
|
this.sdkEvents,
|
|
111
113
|
httpClient,
|
|
@@ -124,6 +126,7 @@ export class ProtonDrivePublicLinkClient {
|
|
|
124
126
|
token,
|
|
125
127
|
publicShareKey,
|
|
126
128
|
publicRootNodeUid,
|
|
129
|
+
isAnonymousContext,
|
|
127
130
|
);
|
|
128
131
|
this.download = initDownloadModule(
|
|
129
132
|
telemetry,
|
|
@@ -133,6 +136,9 @@ export class ProtonDrivePublicLinkClient {
|
|
|
133
136
|
this.sharingPublic.shares,
|
|
134
137
|
this.sharingPublic.nodes.access,
|
|
135
138
|
this.sharingPublic.nodes.revisions,
|
|
139
|
+
// Ignore manifest integrity verifications for public links.
|
|
140
|
+
// Anonymous user on public page cannot load public keys of other users (yet).
|
|
141
|
+
true,
|
|
136
142
|
);
|
|
137
143
|
this.upload = initUploadModule(
|
|
138
144
|
telemetry,
|
|
@@ -159,6 +165,16 @@ export class ProtonDrivePublicLinkClient {
|
|
|
159
165
|
};
|
|
160
166
|
}
|
|
161
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Subscribes to the general SDK events.
|
|
170
|
+
*
|
|
171
|
+
* See `ProtonDriveClient.onMessage` for more information.
|
|
172
|
+
*/
|
|
173
|
+
onMessage(eventName: SDKEvent, callback: () => void): () => void {
|
|
174
|
+
this.logger.debug(`Subscribing to event ${eventName}`);
|
|
175
|
+
return this.sdkEvents.addListener(eventName, callback);
|
|
176
|
+
}
|
|
177
|
+
|
|
162
178
|
/**
|
|
163
179
|
* @returns The root folder to the public link.
|
|
164
180
|
*/
|
package/src/transformers.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MaybeNode as PublicMaybeNode,
|
|
3
3
|
MaybeMissingNode as PublicMaybeMissingNode,
|
|
4
|
-
NodeEntity as PublicNodeEntity,
|
|
5
4
|
DegradedNode as PublicDegradedNode,
|
|
6
5
|
Revision as PublicRevision,
|
|
7
6
|
Result,
|
|
8
7
|
resultOk,
|
|
9
8
|
resultError,
|
|
10
9
|
MissingNode,
|
|
10
|
+
MaybePhotoNode as PublicMaybePhotoNode,
|
|
11
|
+
MaybeMissingPhotoNode as PublicMaybeMissingPhotoNode,
|
|
12
|
+
PhotoNode as PublicPhotoNode,
|
|
13
|
+
DegradedPhotoNode as PublicDegradedPhotoNode,
|
|
11
14
|
} from './interface';
|
|
12
15
|
import { DecryptedNode as InternalNode, DecryptedRevision as InternalRevision } from './internal/nodes';
|
|
16
|
+
import { DecryptedPhotoNode as InternalPartialPhotoNode } from './internal/photos';
|
|
13
17
|
|
|
14
18
|
type InternalPartialNode = Pick<
|
|
15
19
|
InternalNode,
|
|
@@ -25,6 +29,7 @@ type InternalPartialNode = Pick<
|
|
|
25
29
|
| 'isShared'
|
|
26
30
|
| 'isSharedPublicly'
|
|
27
31
|
| 'creationTime'
|
|
32
|
+
| 'modificationTime'
|
|
28
33
|
| 'trashTime'
|
|
29
34
|
| 'activeRevision'
|
|
30
35
|
| 'folder'
|
|
@@ -93,6 +98,7 @@ export function convertInternalNode(node: InternalPartialNode): PublicMaybeNode
|
|
|
93
98
|
isShared: node.isShared,
|
|
94
99
|
isSharedPublicly: node.isSharedPublicly,
|
|
95
100
|
creationTime: node.creationTime,
|
|
101
|
+
modificationTime: node.modificationTime,
|
|
96
102
|
trashTime: node.trashTime,
|
|
97
103
|
totalStorageSize: node.totalStorageSize,
|
|
98
104
|
folder: node.folder,
|
|
@@ -118,7 +124,48 @@ export function convertInternalNode(node: InternalPartialNode): PublicMaybeNode
|
|
|
118
124
|
...baseNodeMetadata,
|
|
119
125
|
name: name.value,
|
|
120
126
|
activeRevision: activeRevision?.ok ? convertInternalRevision(activeRevision.value) : undefined,
|
|
121
|
-
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export async function* convertInternalPhotoNodeIterator(
|
|
131
|
+
photoNodeIterator: AsyncGenerator<InternalPartialPhotoNode>,
|
|
132
|
+
): AsyncGenerator<PublicMaybePhotoNode> {
|
|
133
|
+
for await (const photoNode of photoNodeIterator) {
|
|
134
|
+
yield convertInternalPhotoNode(photoNode);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export async function* convertInternalMissingPhotoNodeIterator(
|
|
139
|
+
photoNodeIterator: AsyncGenerator<InternalPartialPhotoNode | MissingNode>,
|
|
140
|
+
): AsyncGenerator<PublicMaybeMissingPhotoNode> {
|
|
141
|
+
for await (const photoNode of photoNodeIterator) {
|
|
142
|
+
if ('missingUid' in photoNode) {
|
|
143
|
+
yield resultError(photoNode);
|
|
144
|
+
} else {
|
|
145
|
+
yield convertInternalPhotoNode(photoNode);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export async function convertInternalPhotoNodePromise(
|
|
151
|
+
photoNodePromise: Promise<InternalPartialPhotoNode>,
|
|
152
|
+
): Promise<PublicMaybePhotoNode> {
|
|
153
|
+
const photoNode = await photoNodePromise;
|
|
154
|
+
return convertInternalPhotoNode(photoNode);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function convertInternalPhotoNode(photoNode: InternalPartialPhotoNode): PublicMaybePhotoNode {
|
|
158
|
+
const node = convertInternalNode(photoNode);
|
|
159
|
+
if (node.ok) {
|
|
160
|
+
return resultOk({
|
|
161
|
+
...node.value,
|
|
162
|
+
photo: photoNode.photo,
|
|
163
|
+
} as PublicPhotoNode);
|
|
164
|
+
}
|
|
165
|
+
return resultError({
|
|
166
|
+
...node.error,
|
|
167
|
+
photo: photoNode.photo,
|
|
168
|
+
} as PublicDegradedPhotoNode);
|
|
122
169
|
}
|
|
123
170
|
|
|
124
171
|
export async function* convertInternalRevisionIterator(
|