@protontech/drive-sdk 0.9.6 → 0.9.8
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/upload.d.ts +10 -0
- package/dist/internal/nodes/mediaTypes.d.ts +2 -0
- package/dist/internal/nodes/mediaTypes.js +3 -0
- package/dist/internal/nodes/mediaTypes.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.js +2 -1
- package/dist/internal/nodes/nodesManagement.js.map +1 -1
- package/dist/internal/photos/albums.d.ts +12 -1
- package/dist/internal/photos/albums.js +80 -1
- package/dist/internal/photos/albums.js.map +1 -1
- package/dist/internal/photos/albums.test.d.ts +1 -0
- package/dist/internal/photos/albums.test.js +193 -0
- package/dist/internal/photos/albums.test.js.map +1 -0
- package/dist/internal/photos/albumsCrypto.d.ts +35 -0
- package/dist/internal/photos/albumsCrypto.js +66 -0
- package/dist/internal/photos/albumsCrypto.js.map +1 -0
- package/dist/internal/photos/albumsCrypto.test.d.ts +1 -0
- package/dist/internal/photos/albumsCrypto.test.js +134 -0
- package/dist/internal/photos/albumsCrypto.test.js.map +1 -0
- package/dist/internal/photos/apiService.d.ts +18 -0
- package/dist/internal/photos/apiService.js +48 -0
- package/dist/internal/photos/apiService.js.map +1 -1
- package/dist/internal/photos/index.d.ts +3 -3
- package/dist/internal/photos/index.js +5 -3
- package/dist/internal/photos/index.js.map +1 -1
- package/dist/internal/photos/upload.js +3 -2
- package/dist/internal/photos/upload.js.map +1 -1
- package/dist/internal/upload/streamUploader.d.ts +3 -1
- package/dist/internal/upload/streamUploader.js +10 -3
- package/dist/internal/upload/streamUploader.js.map +1 -1
- package/dist/internal/upload/streamUploader.test.js +10 -0
- package/dist/internal/upload/streamUploader.test.js.map +1 -1
- package/dist/protonDrivePhotosClient.d.ts +39 -3
- package/dist/protonDrivePhotosClient.js +49 -5
- package/dist/protonDrivePhotosClient.js.map +1 -1
- package/dist/protonDrivePublicLinkClient.d.ts +6 -0
- package/dist/protonDrivePublicLinkClient.js +8 -0
- package/dist/protonDrivePublicLinkClient.js.map +1 -1
- package/package.json +1 -1
- package/src/interface/upload.ts +10 -0
- package/src/internal/nodes/mediaTypes.ts +3 -0
- package/src/internal/nodes/nodesManagement.ts +2 -1
- package/src/internal/photos/albums.test.ts +241 -0
- package/src/internal/photos/albums.ts +119 -0
- package/src/internal/photos/albumsCrypto.test.ts +181 -0
- package/src/internal/photos/albumsCrypto.ts +100 -0
- package/src/internal/photos/apiService.ts +94 -2
- package/src/internal/photos/index.ts +6 -4
- package/src/internal/photos/upload.ts +3 -2
- package/src/internal/upload/streamUploader.test.ts +38 -0
- package/src/internal/upload/streamUploader.ts +10 -3
- package/src/protonDrivePhotosClient.ts +67 -6
- package/src/protonDrivePublicLinkClient.ts +14 -0
|
@@ -219,13 +219,14 @@ export class StreamUploader {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
protected async commitFile(thumbnails: Thumbnail[]) {
|
|
222
|
-
this.
|
|
222
|
+
const digests = this.digests.digests();
|
|
223
|
+
this.verifyIntegrity(thumbnails, digests);
|
|
223
224
|
|
|
224
225
|
const extendedAttributes = {
|
|
225
226
|
modificationTime: this.metadata.modificationTime,
|
|
226
227
|
size: this.metadata.expectedSize,
|
|
227
228
|
blockSizes: this.uploadedBlockSizes,
|
|
228
|
-
digests
|
|
229
|
+
digests,
|
|
229
230
|
};
|
|
230
231
|
await this.uploadManager.commitDraft(
|
|
231
232
|
this.revisionDraft,
|
|
@@ -607,7 +608,7 @@ export class StreamUploader {
|
|
|
607
608
|
}
|
|
608
609
|
}
|
|
609
610
|
|
|
610
|
-
protected verifyIntegrity(thumbnails: Thumbnail[]) {
|
|
611
|
+
protected verifyIntegrity(thumbnails: Thumbnail[], digests: { sha1: string }) {
|
|
611
612
|
const expectedBlockCount =
|
|
612
613
|
Math.ceil(this.metadata.expectedSize / FILE_CHUNK_SIZE) + (thumbnails ? thumbnails?.length : 0);
|
|
613
614
|
if (this.uploadedBlockCount !== expectedBlockCount) {
|
|
@@ -622,6 +623,12 @@ export class StreamUploader {
|
|
|
622
623
|
expectedFileSize: this.metadata.expectedSize,
|
|
623
624
|
});
|
|
624
625
|
}
|
|
626
|
+
if (this.metadata.expectedSha1 && digests.sha1 !== this.metadata.expectedSha1) {
|
|
627
|
+
throw new IntegrityError(c('Error').t`File hash does not match expected hash`, {
|
|
628
|
+
uploadedSha1: digests.sha1,
|
|
629
|
+
expectedSha1: this.metadata.expectedSha1,
|
|
630
|
+
});
|
|
631
|
+
}
|
|
625
632
|
}
|
|
626
633
|
|
|
627
634
|
/**
|
|
@@ -117,7 +117,13 @@ export class ProtonDrivePhotosClient {
|
|
|
117
117
|
this.photoShares,
|
|
118
118
|
fullConfig.clientUid,
|
|
119
119
|
);
|
|
120
|
-
this.photos = initPhotosModule(
|
|
120
|
+
this.photos = initPhotosModule(
|
|
121
|
+
telemetry,
|
|
122
|
+
apiService,
|
|
123
|
+
cryptoModule,
|
|
124
|
+
this.photoShares,
|
|
125
|
+
this.nodes.access,
|
|
126
|
+
);
|
|
121
127
|
this.sharing = initSharingModule(
|
|
122
128
|
telemetry,
|
|
123
129
|
apiService,
|
|
@@ -299,13 +305,11 @@ export class ProtonDrivePhotosClient {
|
|
|
299
305
|
}
|
|
300
306
|
|
|
301
307
|
/**
|
|
302
|
-
* Empty the trash.
|
|
303
|
-
*
|
|
304
|
-
* See `ProtonDriveClient.emptyTrash` for more information.
|
|
308
|
+
* Empty the trash for the photos volume.
|
|
305
309
|
*/
|
|
306
310
|
async emptyTrash(): Promise<void> {
|
|
307
|
-
this.logger.info('Emptying trash');
|
|
308
|
-
|
|
311
|
+
this.logger.info('Emptying photo volume trash');
|
|
312
|
+
return this.nodes.management.emptyTrash();
|
|
309
313
|
}
|
|
310
314
|
|
|
311
315
|
/**
|
|
@@ -509,6 +513,63 @@ export class ProtonDrivePhotosClient {
|
|
|
509
513
|
return this.photos.timeline.findPhotoDuplicates(name, generateSha1, signal);
|
|
510
514
|
}
|
|
511
515
|
|
|
516
|
+
/**
|
|
517
|
+
* Creates a new album with the given name.
|
|
518
|
+
*
|
|
519
|
+
* @param name - The name for the new album.
|
|
520
|
+
* @returns The created album node.
|
|
521
|
+
*/
|
|
522
|
+
async createAlbum(name: string): Promise<MaybePhotoNode> {
|
|
523
|
+
this.logger.info('Creating album');
|
|
524
|
+
return convertInternalPhotoNodePromise(this.photos.albums.createAlbum(name));
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Updates an existing album.
|
|
529
|
+
*
|
|
530
|
+
* Updates can include a new name and/or a cover photo.
|
|
531
|
+
*
|
|
532
|
+
* @param nodeUid - The UID of the album to edit.
|
|
533
|
+
* @param updates - The updates to apply.
|
|
534
|
+
* @returns The updated album node.
|
|
535
|
+
*/
|
|
536
|
+
async updateAlbum(
|
|
537
|
+
nodeUid: NodeOrUid,
|
|
538
|
+
updates: {
|
|
539
|
+
name?: string;
|
|
540
|
+
coverPhotoNodeUid?: NodeOrUid;
|
|
541
|
+
},
|
|
542
|
+
): Promise<MaybePhotoNode> {
|
|
543
|
+
this.logger.info(`Updating album ${getUid(nodeUid)}`);
|
|
544
|
+
const coverPhotoNodeUid = updates.coverPhotoNodeUid ? getUid(updates.coverPhotoNodeUid) : undefined;
|
|
545
|
+
return convertInternalPhotoNodePromise(
|
|
546
|
+
this.photos.albums.updateAlbum(getUid(nodeUid), {
|
|
547
|
+
name: updates.name,
|
|
548
|
+
coverPhotoNodeUid,
|
|
549
|
+
}),
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Deletes an album.
|
|
555
|
+
*
|
|
556
|
+
* Photos in the timeline will not be deleted. If the album has photos
|
|
557
|
+
* that are not in the timeline (uploaded by another user), the method
|
|
558
|
+
* will throw an error. The photos must be moved to the timeline, or
|
|
559
|
+
* the album must be deleted with `force` option that deletes the photos
|
|
560
|
+
* not in the timeline as well.
|
|
561
|
+
*
|
|
562
|
+
* This operation is irreversible. Both the album and the photos will be
|
|
563
|
+
* permanently deleted, skipping the trash.
|
|
564
|
+
*
|
|
565
|
+
* @param nodeUid - The UID of the album to delete.
|
|
566
|
+
* @param force - Whether to force the deletion.
|
|
567
|
+
*/
|
|
568
|
+
async deleteAlbum(nodeUid: NodeOrUid, options: { force?: boolean } = {}): Promise<void> {
|
|
569
|
+
this.logger.info(`Deleting album ${getUid(nodeUid)}`);
|
|
570
|
+
await this.photos.albums.deleteAlbum(getUid(nodeUid), options);
|
|
571
|
+
}
|
|
572
|
+
|
|
512
573
|
/**
|
|
513
574
|
* Iterates the albums.
|
|
514
575
|
*
|
|
@@ -70,6 +70,12 @@ export class ProtonDrivePublicLinkClient {
|
|
|
70
70
|
* This is used by Docs app to encrypt and decrypt document updates.
|
|
71
71
|
*/
|
|
72
72
|
getDocsKey: (nodeUid: NodeOrUid) => Promise<SessionKey>;
|
|
73
|
+
/**
|
|
74
|
+
* Experimental feature to get the passphrase for a node.
|
|
75
|
+
*
|
|
76
|
+
* This is used by public link page to report abuse.
|
|
77
|
+
*/
|
|
78
|
+
getNodePassphrase: (nodeUid: NodeOrUid) => Promise<string>;
|
|
73
79
|
/**
|
|
74
80
|
* Experimental feature to check if hashes match the malware database.
|
|
75
81
|
*/
|
|
@@ -175,6 +181,14 @@ export class ProtonDrivePublicLinkClient {
|
|
|
175
181
|
}
|
|
176
182
|
return keys.contentKeyPacketSessionKey;
|
|
177
183
|
},
|
|
184
|
+
getNodePassphrase: async (nodeUid: NodeOrUid) => {
|
|
185
|
+
this.logger.debug(`Getting node passphrase for ${getUid(nodeUid)}`);
|
|
186
|
+
const keys = await this.sharingPublic.nodes.access.getNodeKeys(getUid(nodeUid));
|
|
187
|
+
if (!keys.passphrase) {
|
|
188
|
+
throw new Error('Node does not have a passphrase');
|
|
189
|
+
}
|
|
190
|
+
return keys.passphrase
|
|
191
|
+
},
|
|
178
192
|
scanHashes: async (hashes: string[]): Promise<NodesSecurityScanResult> => {
|
|
179
193
|
this.logger.debug(`Scanning ${hashes.length} hashes`);
|
|
180
194
|
return this.sharingPublic.nodes.security.scanHashes(hashes);
|