@protontech/drive-sdk 0.9.9 → 0.11.0
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 +19 -16
- package/dist/crypto/driveCrypto.js +23 -1
- package/dist/crypto/driveCrypto.js.map +1 -1
- package/dist/crypto/driveCrypto.test.js +2 -1
- package/dist/crypto/driveCrypto.test.js.map +1 -1
- package/dist/crypto/hmac.d.ts +3 -3
- package/dist/crypto/hmac.js.map +1 -1
- package/dist/crypto/interface.d.ts +45 -25
- package/dist/crypto/interface.js.map +1 -1
- package/dist/crypto/openPGPCrypto.d.ts +37 -37
- package/dist/crypto/openPGPCrypto.js.map +1 -1
- package/dist/crypto/utils.d.ts +1 -1
- package/dist/diagnostic/telemetry.js +3 -0
- package/dist/diagnostic/telemetry.js.map +1 -1
- package/dist/interface/index.d.ts +4 -3
- package/dist/interface/index.js +3 -1
- package/dist/interface/index.js.map +1 -1
- package/dist/interface/nodes.d.ts +8 -0
- package/dist/interface/photos.d.ts +31 -2
- package/dist/interface/photos.js +14 -0
- package/dist/interface/photos.js.map +1 -1
- package/dist/interface/sharing.d.ts +2 -0
- package/dist/interface/telemetry.d.ts +13 -1
- package/dist/interface/telemetry.js.map +1 -1
- package/dist/interface/thumbnail.d.ts +2 -2
- package/dist/internal/apiService/apiService.d.ts +1 -1
- package/dist/internal/apiService/apiService.js +27 -14
- package/dist/internal/apiService/apiService.js.map +1 -1
- package/dist/internal/apiService/apiService.test.js +33 -5
- package/dist/internal/apiService/apiService.test.js.map +1 -1
- package/dist/internal/apiService/driveTypes.d.ts +2942 -3187
- package/dist/internal/apiService/errors.test.js +17 -7
- package/dist/internal/apiService/errors.test.js.map +1 -1
- package/dist/internal/devices/manager.d.ts +1 -0
- package/dist/internal/devices/manager.js +11 -0
- package/dist/internal/devices/manager.js.map +1 -1
- package/dist/internal/download/apiService.d.ts +1 -1
- package/dist/internal/download/cryptoService.d.ts +4 -4
- package/dist/internal/download/cryptoService.js.map +1 -1
- package/dist/internal/download/fileDownloader.js.map +1 -1
- package/dist/internal/download/fileDownloader.test.js.map +1 -1
- package/dist/internal/download/thumbnailDownloader.js.map +1 -1
- package/dist/internal/nodes/apiService.js.map +1 -1
- package/dist/internal/nodes/cryptoService.d.ts +4 -4
- package/dist/internal/nodes/cryptoService.js +5 -3
- package/dist/internal/nodes/cryptoService.js.map +1 -1
- package/dist/internal/nodes/cryptoService.test.js.map +1 -1
- package/dist/internal/nodes/interface.d.ts +1 -1
- package/dist/internal/nodes/nodesAccess.js +1 -1
- package/dist/internal/nodes/nodesAccess.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.js +0 -1
- package/dist/internal/nodes/nodesManagement.js.map +1 -1
- package/dist/internal/photos/addToAlbum.d.ts +42 -0
- package/dist/internal/photos/addToAlbum.js +178 -0
- package/dist/internal/photos/addToAlbum.js.map +1 -0
- package/dist/internal/photos/addToAlbum.test.js +409 -0
- package/dist/internal/photos/addToAlbum.test.js.map +1 -0
- package/dist/internal/photos/albumsCrypto.d.ts +20 -3
- package/dist/internal/photos/albumsCrypto.js +27 -0
- package/dist/internal/photos/albumsCrypto.js.map +1 -1
- package/dist/internal/photos/{albums.d.ts → albumsManager.d.ts} +6 -4
- package/dist/internal/photos/{albums.js → albumsManager.js} +17 -5
- package/dist/internal/photos/albumsManager.js.map +1 -0
- package/dist/internal/photos/albumsManager.test.d.ts +1 -0
- package/dist/internal/photos/{albums.test.js → albumsManager.test.js} +4 -3
- package/dist/internal/photos/albumsManager.test.js.map +1 -0
- package/dist/internal/photos/apiService.d.ts +22 -2
- package/dist/internal/photos/apiService.js +136 -5
- package/dist/internal/photos/apiService.js.map +1 -1
- package/dist/internal/photos/apiService.test.d.ts +1 -0
- package/dist/internal/photos/apiService.test.js +199 -0
- package/dist/internal/photos/apiService.test.js.map +1 -0
- package/dist/internal/photos/errors.d.ts +4 -0
- package/dist/internal/photos/errors.js +17 -0
- package/dist/internal/photos/errors.js.map +1 -0
- package/dist/internal/photos/index.d.ts +5 -3
- package/dist/internal/photos/index.js +5 -2
- package/dist/internal/photos/index.js.map +1 -1
- package/dist/internal/photos/interface.d.ts +6 -15
- package/dist/internal/photos/interface.js +0 -14
- package/dist/internal/photos/interface.js.map +1 -1
- package/dist/internal/photos/nodes.js +33 -3
- package/dist/internal/photos/nodes.js.map +1 -1
- package/dist/internal/photos/nodes.test.js +25 -5
- package/dist/internal/photos/nodes.test.js.map +1 -1
- package/dist/internal/photos/photosManager.d.ts +22 -0
- package/dist/internal/photos/photosManager.js +101 -0
- package/dist/internal/photos/photosManager.js.map +1 -0
- package/dist/internal/photos/photosManager.test.d.ts +1 -0
- package/dist/internal/photos/photosManager.test.js +222 -0
- package/dist/internal/photos/photosManager.test.js.map +1 -0
- package/dist/internal/photos/photosTransferPayloadBuilder.d.ts +57 -0
- package/dist/internal/photos/photosTransferPayloadBuilder.js +113 -0
- package/dist/internal/photos/photosTransferPayloadBuilder.js.map +1 -0
- package/dist/internal/photos/photosTransferPayloadBuilder.test.d.ts +1 -0
- package/dist/internal/photos/photosTransferPayloadBuilder.test.js +289 -0
- package/dist/internal/photos/photosTransferPayloadBuilder.test.js.map +1 -0
- package/dist/internal/photos/upload.d.ts +2 -2
- package/dist/internal/photos/upload.js +1 -1
- package/dist/internal/photos/upload.js.map +1 -1
- package/dist/internal/shares/apiService.js +1 -0
- package/dist/internal/shares/apiService.js.map +1 -1
- package/dist/internal/shares/interface.d.ts +1 -0
- package/dist/internal/sharing/apiService.d.ts +8 -1
- package/dist/internal/sharing/apiService.js +23 -1
- package/dist/internal/sharing/apiService.js.map +1 -1
- package/dist/internal/sharing/cryptoService.js +8 -4
- package/dist/internal/sharing/cryptoService.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.d.ts +1 -0
- package/dist/internal/sharing/sharingManagement.js +15 -2
- package/dist/internal/sharing/sharingManagement.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.test.js +30 -5
- package/dist/internal/sharing/sharingManagement.test.js.map +1 -1
- package/dist/internal/sharingPublic/nodes.d.ts +2 -2
- package/dist/internal/sharingPublic/nodes.js.map +1 -1
- package/dist/internal/upload/apiService.d.ts +3 -7
- package/dist/internal/upload/apiService.js +0 -4
- package/dist/internal/upload/apiService.js.map +1 -1
- package/dist/internal/upload/blockVerifier.d.ts +2 -2
- package/dist/internal/upload/blockVerifier.js.map +1 -1
- package/dist/internal/upload/chunkStreamReader.d.ts +2 -2
- package/dist/internal/upload/chunkStreamReader.js.map +1 -1
- package/dist/internal/upload/chunkStreamReader.test.js.map +1 -1
- package/dist/internal/upload/cryptoService.d.ts +7 -7
- package/dist/internal/upload/cryptoService.js +4 -4
- package/dist/internal/upload/cryptoService.js.map +1 -1
- package/dist/internal/upload/interface.d.ts +6 -6
- package/dist/internal/upload/manager.d.ts +1 -1
- package/dist/internal/upload/manager.js.map +1 -1
- package/dist/internal/upload/streamUploader.d.ts +1 -1
- package/dist/internal/upload/streamUploader.js +12 -13
- package/dist/internal/upload/streamUploader.js.map +1 -1
- package/dist/internal/upload/streamUploader.test.js +28 -4
- package/dist/internal/upload/streamUploader.test.js.map +1 -1
- package/dist/internal/utils.d.ts +1 -1
- package/dist/protonDriveClient.d.ts +8 -0
- package/dist/protonDriveClient.js +12 -1
- package/dist/protonDriveClient.js.map +1 -1
- package/dist/protonDrivePhotosClient.d.ts +35 -3
- package/dist/protonDrivePhotosClient.js +42 -2
- package/dist/protonDrivePhotosClient.js.map +1 -1
- package/dist/protonDrivePublicLinkClient.js +1 -1
- package/dist/protonDrivePublicLinkClient.js.map +1 -1
- package/dist/transformers.js +2 -0
- package/dist/transformers.js.map +1 -1
- package/package.json +4 -4
- package/src/crypto/driveCrypto.test.ts +2 -1
- package/src/crypto/driveCrypto.ts +50 -16
- package/src/crypto/hmac.ts +4 -4
- package/src/crypto/interface.ts +58 -27
- package/src/crypto/openPGPCrypto.ts +26 -26
- package/src/diagnostic/telemetry.ts +3 -0
- package/src/interface/index.ts +11 -2
- package/src/interface/nodes.ts +1 -0
- package/src/interface/photos.ts +33 -2
- package/src/interface/sharing.ts +2 -0
- package/src/interface/telemetry.ts +15 -1
- package/src/interface/thumbnail.ts +2 -2
- package/src/internal/apiService/apiService.test.ts +38 -6
- package/src/internal/apiService/apiService.ts +39 -14
- package/src/internal/apiService/driveTypes.ts +2942 -3187
- package/src/internal/devices/manager.ts +14 -0
- package/src/internal/download/apiService.ts +1 -1
- package/src/internal/download/cryptoService.ts +4 -4
- package/src/internal/download/fileDownloader.test.ts +4 -4
- package/src/internal/download/fileDownloader.ts +6 -6
- package/src/internal/download/thumbnailDownloader.ts +4 -4
- package/src/internal/nodes/apiService.ts +2 -2
- package/src/internal/nodes/cryptoService.test.ts +2 -2
- package/src/internal/nodes/cryptoService.ts +11 -8
- package/src/internal/nodes/interface.ts +1 -1
- package/src/internal/nodes/nodesAccess.ts +1 -1
- package/src/internal/nodes/nodesManagement.ts +0 -1
- package/src/internal/photos/addToAlbum.test.ts +515 -0
- package/src/internal/photos/addToAlbum.ts +234 -0
- package/src/internal/photos/albumsCrypto.ts +54 -3
- package/src/internal/photos/{albums.test.ts → albumsManager.test.ts} +22 -25
- package/src/internal/photos/{albums.ts → albumsManager.ts} +32 -3
- package/src/internal/photos/apiService.test.ts +233 -0
- package/src/internal/photos/apiService.ts +228 -26
- package/src/internal/photos/errors.ts +11 -0
- package/src/internal/photos/index.ts +6 -3
- package/src/internal/photos/interface.ts +8 -18
- package/src/internal/photos/nodes.test.ts +27 -6
- package/src/internal/photos/nodes.ts +35 -3
- package/src/internal/photos/photosManager.test.ts +266 -0
- package/src/internal/photos/photosManager.ts +144 -0
- package/src/internal/photos/photosTransferPayloadBuilder.test.ts +380 -0
- package/src/internal/photos/photosTransferPayloadBuilder.ts +203 -0
- package/src/internal/photos/upload.ts +8 -3
- package/src/internal/shares/apiService.ts +1 -0
- package/src/internal/shares/interface.ts +1 -0
- package/src/internal/sharing/apiService.ts +49 -5
- package/src/internal/sharing/cryptoService.ts +10 -4
- package/src/internal/sharing/sharingManagement.test.ts +33 -5
- package/src/internal/sharing/sharingManagement.ts +28 -6
- package/src/internal/sharingPublic/nodes.ts +1 -1
- package/src/internal/upload/apiService.ts +10 -12
- package/src/internal/upload/blockVerifier.ts +3 -3
- package/src/internal/upload/chunkStreamReader.test.ts +7 -7
- package/src/internal/upload/chunkStreamReader.ts +3 -3
- package/src/internal/upload/cryptoService.ts +11 -12
- package/src/internal/upload/interface.ts +6 -6
- package/src/internal/upload/manager.ts +2 -2
- package/src/internal/upload/streamUploader.test.ts +33 -4
- package/src/internal/upload/streamUploader.ts +13 -13
- package/src/protonDriveClient.ts +16 -4
- package/src/protonDrivePhotosClient.ts +73 -17
- package/src/protonDrivePublicLinkClient.ts +1 -1
- package/src/transformers.ts +2 -0
- package/dist/internal/photos/albums.js.map +0 -1
- package/dist/internal/photos/albums.test.js.map +0 -1
- /package/dist/internal/photos/{albums.test.d.ts → addToAlbum.test.d.ts} +0 -0
|
@@ -36,6 +36,9 @@ type GetSharedNodesResponse =
|
|
|
36
36
|
type GetSharedWithMeNodesResponse =
|
|
37
37
|
drivePaths['/drive/v2/sharedwithme']['get']['responses']['200']['content']['application/json'];
|
|
38
38
|
|
|
39
|
+
type GetSharedAlbumsResponse =
|
|
40
|
+
drivePaths['/drive/photos/albums/shared-with-me']['get']['responses']['200']['content']['application/json'];
|
|
41
|
+
|
|
39
42
|
type GetInvitationsResponse =
|
|
40
43
|
drivePaths['/drive/v2/shares/invitations']['get']['responses']['200']['content']['application/json'];
|
|
41
44
|
|
|
@@ -61,8 +64,10 @@ type GetShareExternalInvitations =
|
|
|
61
64
|
type GetShareMembers =
|
|
62
65
|
drivePaths['/drive/v2/shares/{shareID}/members']['get']['responses']['200']['content']['application/json'];
|
|
63
66
|
|
|
64
|
-
type PostSharedBookmarksRequest =
|
|
65
|
-
|
|
67
|
+
type PostSharedBookmarksRequest = Extract<
|
|
68
|
+
drivePaths['/drive/v2/urls/{token}/bookmark']['post']['requestBody'],
|
|
69
|
+
{ content: object }
|
|
70
|
+
>['content']['application/json'];
|
|
66
71
|
type PostSharedBookmarksResponse =
|
|
67
72
|
drivePaths['/drive/v2/urls/{token}/bookmark']['post']['responses']['200']['content']['application/json'];
|
|
68
73
|
|
|
@@ -73,6 +78,14 @@ type PostCreateShareRequest = Extract<
|
|
|
73
78
|
type PostCreateShareResponse =
|
|
74
79
|
drivePaths['/drive/volumes/{volumeID}/shares']['post']['responses']['200']['content']['application/json'];
|
|
75
80
|
|
|
81
|
+
type PostChangeSharePropertiesRequest = Extract<
|
|
82
|
+
drivePaths['/drive/shares/{shareID}/property']['post']['requestBody'],
|
|
83
|
+
{ content: object }
|
|
84
|
+
>['content']['application/json'];
|
|
85
|
+
|
|
86
|
+
type PostChangeSharePropertiesResponse =
|
|
87
|
+
drivePaths['/drive/shares/{shareID}/property']['post']['responses']['200']['content']['application/json'];
|
|
88
|
+
|
|
76
89
|
type PostInviteProtonUserRequest = Extract<
|
|
77
90
|
drivePaths['/drive/v2/shares/{shareID}/invitations']['post']['requestBody'],
|
|
78
91
|
{ content: object }
|
|
@@ -184,6 +197,30 @@ export class SharingAPIService {
|
|
|
184
197
|
}
|
|
185
198
|
anchor = response.AnchorID;
|
|
186
199
|
}
|
|
200
|
+
|
|
201
|
+
if (this.shareTargetTypes.includes(ShareTargetType.Album)) {
|
|
202
|
+
yield* this.iterateSharedAlbumUids(signal);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// TODO: Sharing cannot know about albums. We should remove this and use
|
|
207
|
+
// ShareTargetTypes when it is supported by the API.
|
|
208
|
+
private async *iterateSharedAlbumUids(signal?: AbortSignal): AsyncGenerator<string> {
|
|
209
|
+
let anchor = '';
|
|
210
|
+
while (true) {
|
|
211
|
+
const response = await this.apiService.get<GetSharedAlbumsResponse>(
|
|
212
|
+
`drive/photos/albums/shared-with-me?${anchor ? `AnchorID=${anchor}` : ''}`,
|
|
213
|
+
signal,
|
|
214
|
+
);
|
|
215
|
+
for (const album of response.Albums) {
|
|
216
|
+
yield makeNodeUid(album.VolumeID, album.LinkID);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!response.More || !response.AnchorID) {
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
anchor = response.AnchorID;
|
|
223
|
+
}
|
|
187
224
|
}
|
|
188
225
|
|
|
189
226
|
async *iterateInvitationUids(signal?: AbortSignal): AsyncGenerator<string> {
|
|
@@ -304,7 +341,7 @@ export class SharingAPIService {
|
|
|
304
341
|
addressId: string;
|
|
305
342
|
addressKeyId: string;
|
|
306
343
|
}): Promise<void> {
|
|
307
|
-
|
|
344
|
+
await this.apiService.post<PostSharedBookmarksRequest, PostSharedBookmarksResponse>(
|
|
308
345
|
`drive/v2/urls/${bookmark.token}/bookmark`,
|
|
309
346
|
{
|
|
310
347
|
BookmarkShareURL: {
|
|
@@ -363,7 +400,7 @@ export class SharingAPIService {
|
|
|
363
400
|
base64PassphraseKeyPacket: string;
|
|
364
401
|
base64NameKeyPacket: string;
|
|
365
402
|
},
|
|
366
|
-
): Promise<string> {
|
|
403
|
+
): Promise<{ shareId: string; editorsCanShare: boolean }> {
|
|
367
404
|
const { volumeId, nodeId } = splitNodeUid(nodeUid);
|
|
368
405
|
const response = await this.apiService.post<PostCreateShareRequest, PostCreateShareResponse>(
|
|
369
406
|
`drive/volumes/${volumeId}/shares`,
|
|
@@ -378,13 +415,20 @@ export class SharingAPIService {
|
|
|
378
415
|
NameKeyPacket: node.base64NameKeyPacket,
|
|
379
416
|
},
|
|
380
417
|
);
|
|
381
|
-
return response.Share.ID;
|
|
418
|
+
return { shareId: response.Share.ID, editorsCanShare: response.Share.EditorsCanShare };
|
|
382
419
|
}
|
|
383
420
|
|
|
384
421
|
async deleteShare(shareId: string, force: boolean = false): Promise<void> {
|
|
385
422
|
await this.apiService.delete(`drive/shares/${shareId}?Force=${force ? 1 : 0}`);
|
|
386
423
|
}
|
|
387
424
|
|
|
425
|
+
async changeShareProperties(shareId: string, { editorsCanShare }: { editorsCanShare: boolean }) {
|
|
426
|
+
await this.apiService.post<PostChangeSharePropertiesRequest, PostChangeSharePropertiesResponse>(
|
|
427
|
+
`drive/shares/${shareId}/property`,
|
|
428
|
+
{ EditorsCanShare: editorsCanShare },
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
|
|
388
432
|
async inviteProtonUser(
|
|
389
433
|
shareId: string,
|
|
390
434
|
invitation: EncryptedInvitationRequest,
|
|
@@ -213,7 +213,7 @@ export class SharingCryptoService {
|
|
|
213
213
|
} catch (error: unknown) {
|
|
214
214
|
const message = getErrorMessage(error);
|
|
215
215
|
const errorMessage = c('Error').t`Failed to decrypt item name: ${message}`;
|
|
216
|
-
nodeName = resultError(new Error(errorMessage));
|
|
216
|
+
nodeName = resultError(new Error(errorMessage, { cause: error }));
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
return {
|
|
@@ -458,7 +458,10 @@ export class SharingCryptoService {
|
|
|
458
458
|
urlPassword = result.password;
|
|
459
459
|
customPassword = resultOk(result.customPassword);
|
|
460
460
|
} catch (originalError: unknown) {
|
|
461
|
-
const error =
|
|
461
|
+
const error =
|
|
462
|
+
originalError instanceof Error
|
|
463
|
+
? originalError
|
|
464
|
+
: new Error(c('Error').t`Unknown error`, { cause: originalError });
|
|
462
465
|
return {
|
|
463
466
|
url: resultError(error),
|
|
464
467
|
customPassword: resultError(error),
|
|
@@ -473,7 +476,10 @@ export class SharingCryptoService {
|
|
|
473
476
|
try {
|
|
474
477
|
shareKey = await this.decryptBookmarkKey(encryptedBookmark, password);
|
|
475
478
|
} catch (originalError: unknown) {
|
|
476
|
-
const error =
|
|
479
|
+
const error =
|
|
480
|
+
originalError instanceof Error
|
|
481
|
+
? originalError
|
|
482
|
+
: new Error(c('Error').t`Unknown error`, { cause: originalError });
|
|
477
483
|
return {
|
|
478
484
|
url,
|
|
479
485
|
customPassword,
|
|
@@ -577,7 +583,7 @@ export class SharingCryptoService {
|
|
|
577
583
|
|
|
578
584
|
const message = getErrorMessage(error);
|
|
579
585
|
const errorMessage = c('Error').t`Failed to decrypt bookmark name: ${message}`;
|
|
580
|
-
return resultError(new Error(errorMessage));
|
|
586
|
+
return resultError(new Error(errorMessage, { cause: error }));
|
|
581
587
|
}
|
|
582
588
|
}
|
|
583
589
|
}
|
|
@@ -18,6 +18,8 @@ import { SharingManagement } from './sharingManagement';
|
|
|
18
18
|
import { ValidationError } from '../../errors';
|
|
19
19
|
import { ErrorCode } from '../apiService';
|
|
20
20
|
|
|
21
|
+
const DEFAULT_SHARE_ID = 'shareId';
|
|
22
|
+
|
|
21
23
|
describe('SharingManagement', () => {
|
|
22
24
|
let logger: Logger;
|
|
23
25
|
let apiService: SharingAPIService;
|
|
@@ -34,7 +36,7 @@ describe('SharingManagement', () => {
|
|
|
34
36
|
|
|
35
37
|
// @ts-expect-error No need to implement all methods for mocking
|
|
36
38
|
apiService = {
|
|
37
|
-
createStandardShare: jest.fn().mockReturnValue('newShareId'),
|
|
39
|
+
createStandardShare: jest.fn().mockReturnValue({ shareId: 'newShareId', editorsCanShare: false }),
|
|
38
40
|
getShareInvitations: jest.fn().mockResolvedValue([]),
|
|
39
41
|
getShareExternalInvitations: jest.fn().mockResolvedValue([]),
|
|
40
42
|
getShareMembers: jest.fn().mockResolvedValue([]),
|
|
@@ -63,6 +65,7 @@ describe('SharingManagement', () => {
|
|
|
63
65
|
publicUrl: 'publicLinkUrl',
|
|
64
66
|
}),
|
|
65
67
|
updatePublicLink: jest.fn(),
|
|
68
|
+
changeShareProperties: jest.fn(),
|
|
66
69
|
};
|
|
67
70
|
// @ts-expect-error No need to implement all methods for mocking
|
|
68
71
|
cache = {
|
|
@@ -98,7 +101,7 @@ describe('SharingManagement', () => {
|
|
|
98
101
|
// @ts-expect-error No need to implement all methods for mocking
|
|
99
102
|
sharesService = {
|
|
100
103
|
loadEncryptedShare: jest.fn().mockResolvedValue({
|
|
101
|
-
id:
|
|
104
|
+
id: DEFAULT_SHARE_ID,
|
|
102
105
|
addressId: 'addressId',
|
|
103
106
|
creatorEmail: 'address@example.com',
|
|
104
107
|
passphraseSessionKey: 'sharePassphraseSessionKey',
|
|
@@ -106,9 +109,11 @@ describe('SharingManagement', () => {
|
|
|
106
109
|
};
|
|
107
110
|
// @ts-expect-error No need to implement all methods for mocking
|
|
108
111
|
nodesService = {
|
|
109
|
-
getNode: jest
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
getNode: jest.fn().mockImplementation((nodeUid) => ({
|
|
113
|
+
nodeUid,
|
|
114
|
+
shareId: DEFAULT_SHARE_ID,
|
|
115
|
+
name: { ok: true, value: 'name' },
|
|
116
|
+
})),
|
|
112
117
|
getNodeKeys: jest.fn().mockImplementation((nodeUid) => ({ key: 'node-key' })),
|
|
113
118
|
getNodePrivateAndSessionKeys: jest.fn().mockImplementation((nodeUid) => ({})),
|
|
114
119
|
getRootNodeEmailKey: jest.fn().mockResolvedValue({ email: 'volume-email', addressKey: 'volume-key' }),
|
|
@@ -225,6 +230,7 @@ describe('SharingManagement', () => {
|
|
|
225
230
|
nonProtonInvitations: [],
|
|
226
231
|
members: [],
|
|
227
232
|
publicLink: undefined,
|
|
233
|
+
editorsCanShare: false,
|
|
228
234
|
});
|
|
229
235
|
expect(apiService.updateInvitation).not.toHaveBeenCalled();
|
|
230
236
|
expect(apiService.inviteProtonUser).toHaveBeenCalled();
|
|
@@ -395,6 +401,28 @@ describe('SharingManagement', () => {
|
|
|
395
401
|
expect(cache.addSharedByMeNodeUid).not.toHaveBeenCalled();
|
|
396
402
|
});
|
|
397
403
|
|
|
404
|
+
it('should update editorsCanChange', async () => {
|
|
405
|
+
const sharingInfo = await sharingManagement.shareNode(nodeUid, {
|
|
406
|
+
editorsCanShare: true,
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
expect(sharingInfo).toEqual({
|
|
410
|
+
protonInvitations: [
|
|
411
|
+
{
|
|
412
|
+
...invitation,
|
|
413
|
+
role: 'viewer',
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
nonProtonInvitations: [externalInvitation],
|
|
417
|
+
members: [member],
|
|
418
|
+
publicLink: undefined,
|
|
419
|
+
editorsCanShare: true,
|
|
420
|
+
});
|
|
421
|
+
expect(apiService.changeShareProperties).toHaveBeenCalledWith(DEFAULT_SHARE_ID, {
|
|
422
|
+
editorsCanShare: true,
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
|
|
398
426
|
it('should be no-op if no change', async () => {
|
|
399
427
|
const sharingInfo = await sharingManagement.shareNode(nodeUid, {
|
|
400
428
|
users: [{ email: 'internal-email', role: MemberRole.Viewer }],
|
|
@@ -77,11 +77,12 @@ export class SharingManagement {
|
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
const [protonInvitations, nonProtonInvitations, members, publicLink] = await Promise.all([
|
|
80
|
+
const [protonInvitations, nonProtonInvitations, members, publicLink, share] = await Promise.all([
|
|
81
81
|
Array.fromAsync(this.iterateShareInvitations(node.shareId)),
|
|
82
82
|
Array.fromAsync(this.iterateShareExternalInvitations(node.shareId)),
|
|
83
83
|
Array.fromAsync(this.iterateShareMembers(node.shareId)),
|
|
84
84
|
this.getPublicLink(node.shareId),
|
|
85
|
+
this.sharesService.loadEncryptedShare(node.shareId),
|
|
85
86
|
]);
|
|
86
87
|
|
|
87
88
|
return {
|
|
@@ -89,6 +90,7 @@ export class SharingManagement {
|
|
|
89
90
|
nonProtonInvitations,
|
|
90
91
|
members,
|
|
91
92
|
publicLink,
|
|
93
|
+
editorsCanShare: share.editorsCanShare,
|
|
92
94
|
};
|
|
93
95
|
}
|
|
94
96
|
|
|
@@ -161,6 +163,7 @@ export class SharingManagement {
|
|
|
161
163
|
nonProtonInvitations: [],
|
|
162
164
|
members: [],
|
|
163
165
|
publicLink: undefined,
|
|
166
|
+
editorsCanShare: result.editorsCanShare,
|
|
164
167
|
};
|
|
165
168
|
contextShareAddress = result.contextShareAddress;
|
|
166
169
|
} catch (error: unknown) {
|
|
@@ -184,6 +187,11 @@ export class SharingManagement {
|
|
|
184
187
|
contextShareAddress = await this.nodesService.getRootNodeEmailKey(nodeUid);
|
|
185
188
|
}
|
|
186
189
|
|
|
190
|
+
if (settings.editorsCanShare !== undefined) {
|
|
191
|
+
await this.setEditorsCanShare(currentSharing.share.shareId, settings.editorsCanShare);
|
|
192
|
+
currentSharing.editorsCanShare = settings.editorsCanShare;
|
|
193
|
+
}
|
|
194
|
+
|
|
187
195
|
const emailOptions: EmailOptions = {
|
|
188
196
|
message: settings.emailOptions?.message,
|
|
189
197
|
nodeName: settings.emailOptions?.includeNodeName ? currentSharing.nodeName : undefined,
|
|
@@ -294,6 +302,7 @@ export class SharingManagement {
|
|
|
294
302
|
nonProtonInvitations: currentSharing.nonProtonInvitations,
|
|
295
303
|
members: currentSharing.members,
|
|
296
304
|
publicLink: currentSharing.publicLink,
|
|
305
|
+
editorsCanShare: currentSharing.editorsCanShare,
|
|
297
306
|
};
|
|
298
307
|
}
|
|
299
308
|
|
|
@@ -385,6 +394,7 @@ export class SharingManagement {
|
|
|
385
394
|
nonProtonInvitations: currentSharing.nonProtonInvitations,
|
|
386
395
|
members: currentSharing.members,
|
|
387
396
|
publicLink: currentSharing.publicLink,
|
|
397
|
+
editorsCanShare: currentSharing.editorsCanShare,
|
|
388
398
|
};
|
|
389
399
|
}
|
|
390
400
|
|
|
@@ -415,7 +425,9 @@ export class SharingManagement {
|
|
|
415
425
|
};
|
|
416
426
|
}
|
|
417
427
|
|
|
418
|
-
private async createShare(
|
|
428
|
+
private async createShare(
|
|
429
|
+
nodeUid: string,
|
|
430
|
+
): Promise<{ share: Share; contextShareAddress: ContextShareAddress; editorsCanShare: boolean }> {
|
|
419
431
|
const node = await this.nodesService.getNode(nodeUid);
|
|
420
432
|
if (!node.parentUid) {
|
|
421
433
|
throw new ValidationError(c('Error').t`Cannot share root folder`);
|
|
@@ -426,10 +438,15 @@ export class SharingManagement {
|
|
|
426
438
|
|
|
427
439
|
const nodeKeys = await this.nodesService.getNodePrivateAndSessionKeys(nodeUid);
|
|
428
440
|
const keys = await this.cryptoService.generateShareKeys(nodeKeys, addressKey);
|
|
429
|
-
const shareId = await this.apiService.createStandardShare(
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
441
|
+
const { shareId, editorsCanShare } = await this.apiService.createStandardShare(
|
|
442
|
+
nodeUid,
|
|
443
|
+
addressId,
|
|
444
|
+
keys.shareKey.encrypted,
|
|
445
|
+
{
|
|
446
|
+
base64PassphraseKeyPacket: keys.base64PpassphraseKeyPacket,
|
|
447
|
+
base64NameKeyPacket: keys.base64NameKeyPacket,
|
|
448
|
+
},
|
|
449
|
+
);
|
|
433
450
|
await this.nodesService.notifyNodeChanged(nodeUid);
|
|
434
451
|
if (await this.cache.hasSharedByMeNodeUidsLoaded()) {
|
|
435
452
|
await this.cache.addSharedByMeNodeUid(nodeUid);
|
|
@@ -449,9 +466,14 @@ export class SharingManagement {
|
|
|
449
466
|
return {
|
|
450
467
|
share,
|
|
451
468
|
contextShareAddress,
|
|
469
|
+
editorsCanShare,
|
|
452
470
|
};
|
|
453
471
|
}
|
|
454
472
|
|
|
473
|
+
private async setEditorsCanShare(shareId: string, editorsCanShare: boolean) {
|
|
474
|
+
await this.apiService.changeShareProperties(shareId, { editorsCanShare });
|
|
475
|
+
}
|
|
476
|
+
|
|
455
477
|
/**
|
|
456
478
|
* Deletes the share even if it is not empty.
|
|
457
479
|
*/
|
|
@@ -18,7 +18,7 @@ import { SharingPublicSharesManager } from './shares';
|
|
|
18
18
|
|
|
19
19
|
export class SharingPublicNodesCryptoService extends NodesCryptoService {
|
|
20
20
|
async generateDocument(
|
|
21
|
-
parentKeys: { key: PrivateKey; hashKey: Uint8Array },
|
|
21
|
+
parentKeys: { key: PrivateKey; hashKey: Uint8Array<ArrayBuffer> },
|
|
22
22
|
signingKeys: NodeSigningKeys,
|
|
23
23
|
name: string,
|
|
24
24
|
) {
|
|
@@ -142,7 +142,7 @@ export class UploadAPIService {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
async getVerificationData(draftNodeRevisionUid: string): Promise<{
|
|
145
|
-
verificationCode: Uint8Array
|
|
145
|
+
verificationCode: Uint8Array<ArrayBuffer>;
|
|
146
146
|
base64ContentKeyPacket: string;
|
|
147
147
|
}> {
|
|
148
148
|
const { volumeId, nodeId, revisionId } = splitNodeRevisionUid(draftNodeRevisionUid);
|
|
@@ -162,22 +162,24 @@ export class UploadAPIService {
|
|
|
162
162
|
blocks: {
|
|
163
163
|
contentBlocks: {
|
|
164
164
|
index: number;
|
|
165
|
-
hash: Uint8Array;
|
|
166
|
-
encryptedSize: number;
|
|
167
165
|
armoredSignature: string;
|
|
168
|
-
verificationToken: Uint8Array
|
|
166
|
+
verificationToken: Uint8Array<ArrayBuffer>;
|
|
169
167
|
}[];
|
|
170
168
|
thumbnails?: {
|
|
171
169
|
type: ThumbnailType;
|
|
172
|
-
hash: Uint8Array;
|
|
173
|
-
encryptedSize: number;
|
|
174
170
|
}[];
|
|
175
171
|
},
|
|
176
172
|
): Promise<UploadTokens> {
|
|
177
173
|
const { volumeId, nodeId, revisionId } = splitNodeRevisionUid(draftNodeRevisionUid);
|
|
178
174
|
const result = await this.apiService.post<
|
|
179
175
|
// TODO: Deprected fields but not properly marked in the types.
|
|
180
|
-
Omit<
|
|
176
|
+
Omit<
|
|
177
|
+
PostRequestBlockUploadRequest,
|
|
178
|
+
'ShareID' | 'Thumbnail' | 'ThumbnailHash' | 'ThumbnailSize' | 'BlockList' | 'ThumbnailList'
|
|
179
|
+
> & {
|
|
180
|
+
BlockList: Omit<PostRequestBlockUploadRequest['BlockList'][0], 'Hash' | 'Size'>[];
|
|
181
|
+
ThumbnailList: Omit<PostRequestBlockUploadRequest['ThumbnailList'][0], 'Hash' | 'Size'>[];
|
|
182
|
+
},
|
|
181
183
|
PostRequestBlockUploadResponse
|
|
182
184
|
>('drive/blocks', {
|
|
183
185
|
AddressID: addressId,
|
|
@@ -186,16 +188,12 @@ export class UploadAPIService {
|
|
|
186
188
|
RevisionID: revisionId,
|
|
187
189
|
BlockList: blocks.contentBlocks.map((block) => ({
|
|
188
190
|
Index: block.index,
|
|
189
|
-
Hash: uint8ArrayToBase64String(block.hash),
|
|
190
191
|
EncSignature: block.armoredSignature,
|
|
191
|
-
Size: block.encryptedSize,
|
|
192
192
|
Verifier: {
|
|
193
193
|
Token: uint8ArrayToBase64String(block.verificationToken),
|
|
194
194
|
},
|
|
195
195
|
})),
|
|
196
196
|
ThumbnailList: (blocks.thumbnails || []).map((block) => ({
|
|
197
|
-
Hash: uint8ArrayToBase64String(block.hash),
|
|
198
|
-
Size: block.encryptedSize,
|
|
199
197
|
Type: block.type,
|
|
200
198
|
})),
|
|
201
199
|
});
|
|
@@ -260,7 +258,7 @@ export class UploadAPIService {
|
|
|
260
258
|
async uploadBlock(
|
|
261
259
|
url: string,
|
|
262
260
|
token: string,
|
|
263
|
-
block: Uint8Array
|
|
261
|
+
block: Uint8Array<ArrayBuffer>,
|
|
264
262
|
onProgress?: (uploadedBytes: number) => void,
|
|
265
263
|
signal?: AbortSignal,
|
|
266
264
|
): Promise<void> {
|
|
@@ -3,7 +3,7 @@ import { UploadAPIService } from './apiService';
|
|
|
3
3
|
import { UploadCryptoService } from './cryptoService';
|
|
4
4
|
|
|
5
5
|
export class BlockVerifier {
|
|
6
|
-
private verificationCode?: Uint8Array
|
|
6
|
+
private verificationCode?: Uint8Array<ArrayBuffer>;
|
|
7
7
|
private contentKeyPacketSessionKey?: SessionKey;
|
|
8
8
|
|
|
9
9
|
constructor(
|
|
@@ -26,8 +26,8 @@ export class BlockVerifier {
|
|
|
26
26
|
);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
async verifyBlock(encryptedBlock: Uint8Array): Promise<{
|
|
30
|
-
verificationToken: Uint8Array
|
|
29
|
+
async verifyBlock(encryptedBlock: Uint8Array<ArrayBuffer>): Promise<{
|
|
30
|
+
verificationToken: Uint8Array<ArrayBuffer>;
|
|
31
31
|
}> {
|
|
32
32
|
if (!this.verificationCode || !this.contentKeyPacketSessionKey) {
|
|
33
33
|
throw new Error('Verifying block before loading verification data');
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ChunkStreamReader } from './chunkStreamReader';
|
|
2
2
|
|
|
3
3
|
describe('ChunkStreamReader', () => {
|
|
4
|
-
let stream: ReadableStream<Uint8Array
|
|
4
|
+
let stream: ReadableStream<Uint8Array<ArrayBuffer>>;
|
|
5
5
|
|
|
6
6
|
beforeEach(() => {
|
|
7
|
-
stream = new ReadableStream<Uint8Array
|
|
7
|
+
stream = new ReadableStream<Uint8Array<ArrayBuffer>>({
|
|
8
8
|
start(controller) {
|
|
9
9
|
controller.enqueue(new Uint8Array([1, 2, 3]));
|
|
10
10
|
controller.enqueue(new Uint8Array([4, 5, 6]));
|
|
@@ -18,7 +18,7 @@ describe('ChunkStreamReader', () => {
|
|
|
18
18
|
it('should yield chunks as enqueued if matching the size', async () => {
|
|
19
19
|
const reader = new ChunkStreamReader(stream, 3);
|
|
20
20
|
|
|
21
|
-
const chunks: Uint8Array[] = [];
|
|
21
|
+
const chunks: Uint8Array<ArrayBuffer>[] = [];
|
|
22
22
|
for await (const chunk of reader.iterateChunks()) {
|
|
23
23
|
chunks.push(new Uint8Array(chunk));
|
|
24
24
|
}
|
|
@@ -33,7 +33,7 @@ describe('ChunkStreamReader', () => {
|
|
|
33
33
|
it('should yield smaller chunks than enqueued chunks', async () => {
|
|
34
34
|
const reader = new ChunkStreamReader(stream, 2);
|
|
35
35
|
|
|
36
|
-
const chunks: Uint8Array[] = [];
|
|
36
|
+
const chunks: Uint8Array<ArrayBuffer>[] = [];
|
|
37
37
|
for await (const chunk of reader.iterateChunks()) {
|
|
38
38
|
chunks.push(new Uint8Array(chunk));
|
|
39
39
|
}
|
|
@@ -50,7 +50,7 @@ describe('ChunkStreamReader', () => {
|
|
|
50
50
|
it('should yield bigger chunks than enqueued chunks', async () => {
|
|
51
51
|
const reader = new ChunkStreamReader(stream, 4);
|
|
52
52
|
|
|
53
|
-
const chunks: Uint8Array[] = [];
|
|
53
|
+
const chunks: Uint8Array<ArrayBuffer>[] = [];
|
|
54
54
|
for await (const chunk of reader.iterateChunks()) {
|
|
55
55
|
chunks.push(new Uint8Array(chunk));
|
|
56
56
|
}
|
|
@@ -64,7 +64,7 @@ describe('ChunkStreamReader', () => {
|
|
|
64
64
|
it('should yield last incomplete chunk', async () => {
|
|
65
65
|
const reader = new ChunkStreamReader(stream, 5);
|
|
66
66
|
|
|
67
|
-
const chunks: Uint8Array[] = [];
|
|
67
|
+
const chunks: Uint8Array<ArrayBuffer>[] = [];
|
|
68
68
|
for await (const chunk of reader.iterateChunks()) {
|
|
69
69
|
chunks.push(new Uint8Array(chunk));
|
|
70
70
|
}
|
|
@@ -78,7 +78,7 @@ describe('ChunkStreamReader', () => {
|
|
|
78
78
|
it('should yield as one big chunk', async () => {
|
|
79
79
|
const reader = new ChunkStreamReader(stream, 100);
|
|
80
80
|
|
|
81
|
-
const chunks: Uint8Array[] = [];
|
|
81
|
+
const chunks: Uint8Array<ArrayBuffer>[] = [];
|
|
82
82
|
for await (const chunk of reader.iterateChunks()) {
|
|
83
83
|
chunks.push(new Uint8Array(chunk));
|
|
84
84
|
}
|
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
* If you need to keep previous chunks, copy them to a new array.
|
|
7
7
|
*/
|
|
8
8
|
export class ChunkStreamReader {
|
|
9
|
-
private reader: ReadableStreamDefaultReader<Uint8Array
|
|
9
|
+
private reader: ReadableStreamDefaultReader<Uint8Array<ArrayBuffer>>;
|
|
10
10
|
|
|
11
11
|
private chunkSize: number;
|
|
12
12
|
|
|
13
|
-
constructor(stream: ReadableStream<Uint8Array
|
|
13
|
+
constructor(stream: ReadableStream<Uint8Array<ArrayBuffer>>, chunkSize: number) {
|
|
14
14
|
this.reader = stream.getReader();
|
|
15
15
|
this.chunkSize = chunkSize;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
async *iterateChunks(): AsyncGenerator<Uint8Array
|
|
18
|
+
async *iterateChunks(): AsyncGenerator<Uint8Array<ArrayBuffer>> {
|
|
19
19
|
const buffer = new Uint8Array(this.chunkSize);
|
|
20
20
|
|
|
21
21
|
let position = 0;
|
|
@@ -23,7 +23,7 @@ export class UploadCryptoService {
|
|
|
23
23
|
|
|
24
24
|
async generateFileCrypto(
|
|
25
25
|
parentUid: string,
|
|
26
|
-
parentKeys: { key: PrivateKey; hashKey: Uint8Array },
|
|
26
|
+
parentKeys: { key: PrivateKey; hashKey: Uint8Array<ArrayBuffer> },
|
|
27
27
|
name: string,
|
|
28
28
|
): Promise<NodeCrypto> {
|
|
29
29
|
const signingKeys = await this.getSigningKeys({ parentNodeUid: parentUid });
|
|
@@ -111,21 +111,21 @@ export class UploadCryptoService {
|
|
|
111
111
|
nodeRevisionDraftKeys.signingKeys.contentSigningKey,
|
|
112
112
|
);
|
|
113
113
|
|
|
114
|
-
const
|
|
114
|
+
const digestPromise = crypto.subtle.digest('SHA-256', encryptedData);
|
|
115
115
|
|
|
116
116
|
return {
|
|
117
117
|
type: thumbnail.type,
|
|
118
118
|
encryptedData: encryptedData,
|
|
119
119
|
originalSize: thumbnail.thumbnail.length,
|
|
120
120
|
encryptedSize: encryptedData.length,
|
|
121
|
-
|
|
121
|
+
hashPromise: digestPromise.then((digest) => new Uint8Array<ArrayBuffer>(digest)),
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
async encryptBlock(
|
|
126
|
-
verifyBlock: (encryptedBlock: Uint8Array) => Promise<{ verificationToken: Uint8Array }>,
|
|
126
|
+
verifyBlock: (encryptedBlock: Uint8Array<ArrayBuffer>) => Promise<{ verificationToken: Uint8Array<ArrayBuffer> }>,
|
|
127
127
|
nodeRevisionDraftKeys: NodeRevisionDraftKeys,
|
|
128
|
-
block: Uint8Array
|
|
128
|
+
block: Uint8Array<ArrayBuffer>,
|
|
129
129
|
index: number,
|
|
130
130
|
): Promise<EncryptedBlock> {
|
|
131
131
|
const { encryptedData, armoredSignature } = await this.driveCrypto.encryptBlock(
|
|
@@ -134,8 +134,7 @@ export class UploadCryptoService {
|
|
|
134
134
|
nodeRevisionDraftKeys.contentKeyPacketSessionKey,
|
|
135
135
|
nodeRevisionDraftKeys.signingKeys.contentSigningKey,
|
|
136
136
|
);
|
|
137
|
-
|
|
138
|
-
const digest = await crypto.subtle.digest('SHA-256', encryptedData);
|
|
137
|
+
const digestPromise = crypto.subtle.digest('SHA-256', encryptedData);
|
|
139
138
|
const { verificationToken } = await verifyBlock(encryptedData);
|
|
140
139
|
|
|
141
140
|
return {
|
|
@@ -145,13 +144,13 @@ export class UploadCryptoService {
|
|
|
145
144
|
verificationToken,
|
|
146
145
|
originalSize: block.length,
|
|
147
146
|
encryptedSize: encryptedData.length,
|
|
148
|
-
|
|
147
|
+
hashPromise: digestPromise.then((digest) => new Uint8Array<ArrayBuffer>(digest)),
|
|
149
148
|
};
|
|
150
149
|
}
|
|
151
150
|
|
|
152
151
|
async commitFile(
|
|
153
152
|
nodeRevisionDraftKeys: NodeRevisionDraftKeys,
|
|
154
|
-
manifest: Uint8Array
|
|
153
|
+
manifest: Uint8Array<ArrayBuffer>,
|
|
155
154
|
extendedAttributes?: string,
|
|
156
155
|
): Promise<{
|
|
157
156
|
armoredManifestSignature: string;
|
|
@@ -190,10 +189,10 @@ export class UploadCryptoService {
|
|
|
190
189
|
|
|
191
190
|
async verifyBlock(
|
|
192
191
|
contentKeyPacketSessionKey: SessionKey,
|
|
193
|
-
verificationCode: Uint8Array
|
|
194
|
-
encryptedData: Uint8Array
|
|
192
|
+
verificationCode: Uint8Array<ArrayBuffer>,
|
|
193
|
+
encryptedData: Uint8Array<ArrayBuffer>,
|
|
195
194
|
): Promise<{
|
|
196
|
-
verificationToken: Uint8Array
|
|
195
|
+
verificationToken: Uint8Array<ArrayBuffer>;
|
|
197
196
|
}> {
|
|
198
197
|
// Attempt to decrypt data block, to try to detect bitflips / bad hardware
|
|
199
198
|
//
|
|
@@ -8,7 +8,7 @@ export type NodeRevisionDraft = {
|
|
|
8
8
|
nodeRevisionUid: string;
|
|
9
9
|
nodeKeys: NodeRevisionDraftKeys;
|
|
10
10
|
parentNodeKeys?: {
|
|
11
|
-
hashKey: Uint8Array
|
|
11
|
+
hashKey: Uint8Array<ArrayBuffer>;
|
|
12
12
|
};
|
|
13
13
|
// newNodeInfo is set only when revision is created with the new node.
|
|
14
14
|
newNodeInfo?: {
|
|
@@ -64,19 +64,19 @@ export type NodeCryptoSigningKeys = {
|
|
|
64
64
|
export type EncryptedBlockMetadata = {
|
|
65
65
|
encryptedSize: number;
|
|
66
66
|
originalSize: number;
|
|
67
|
-
|
|
67
|
+
hashPromise: Promise<Uint8Array<ArrayBuffer>>;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
export type EncryptedBlock = EncryptedBlockMetadata & {
|
|
71
71
|
index: number;
|
|
72
|
-
encryptedData: Uint8Array
|
|
72
|
+
encryptedData: Uint8Array<ArrayBuffer>;
|
|
73
73
|
armoredSignature: string;
|
|
74
|
-
verificationToken: Uint8Array
|
|
74
|
+
verificationToken: Uint8Array<ArrayBuffer>;
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
export type EncryptedThumbnail = EncryptedBlockMetadata & {
|
|
78
78
|
type: ThumbnailType;
|
|
79
|
-
encryptedData: Uint8Array
|
|
79
|
+
encryptedData: Uint8Array<ArrayBuffer>;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
82
|
export type UploadTokens = {
|
|
@@ -101,7 +101,7 @@ export interface NodesService {
|
|
|
101
101
|
key: PrivateKey;
|
|
102
102
|
passphraseSessionKey: SessionKey;
|
|
103
103
|
contentKeyPacketSessionKey?: SessionKey;
|
|
104
|
-
hashKey?: Uint8Array
|
|
104
|
+
hashKey?: Uint8Array<ArrayBuffer>;
|
|
105
105
|
}>;
|
|
106
106
|
getNodeSigningKeys(
|
|
107
107
|
uids: { nodeUid: string; parentNodeUid?: string } | { nodeUid?: string; parentNodeUid: string },
|
|
@@ -73,7 +73,7 @@ export class UploadManager {
|
|
|
73
73
|
|
|
74
74
|
private async createDraftOnAPI(
|
|
75
75
|
parentFolderUid: string,
|
|
76
|
-
parentHashKey: Uint8Array
|
|
76
|
+
parentHashKey: Uint8Array<ArrayBuffer>,
|
|
77
77
|
name: string,
|
|
78
78
|
metadata: UploadMetadata,
|
|
79
79
|
generatedNodeCrypto: NodeCrypto,
|
|
@@ -226,7 +226,7 @@ export class UploadManager {
|
|
|
226
226
|
|
|
227
227
|
async commitDraft(
|
|
228
228
|
nodeRevisionDraft: NodeRevisionDraft,
|
|
229
|
-
manifest: Uint8Array
|
|
229
|
+
manifest: Uint8Array<ArrayBuffer>,
|
|
230
230
|
extendedAttributes: {
|
|
231
231
|
modificationTime?: Date;
|
|
232
232
|
size: number;
|