@protontech/drive-sdk 0.0.12 → 0.1.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/cache/index.d.ts +1 -0
- package/dist/cache/index.js +3 -1
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/memoryCache.d.ts +1 -1
- package/dist/cache/nullCache.d.ts +14 -0
- package/dist/cache/nullCache.js +37 -0
- package/dist/cache/nullCache.js.map +1 -0
- package/dist/config.d.ts +16 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/crypto/openPGPCrypto.js +2 -0
- package/dist/crypto/openPGPCrypto.js.map +1 -1
- package/dist/diagnostic/eventsGenerator.d.ts +14 -0
- package/dist/diagnostic/eventsGenerator.js +49 -0
- package/dist/diagnostic/eventsGenerator.js.map +1 -0
- package/dist/diagnostic/httpClient.d.ts +16 -0
- package/dist/diagnostic/httpClient.js +81 -0
- package/dist/diagnostic/httpClient.js.map +1 -0
- package/dist/diagnostic/index.d.ts +10 -0
- package/dist/diagnostic/index.js +35 -0
- package/dist/diagnostic/index.js.map +1 -0
- package/dist/diagnostic/integrityVerificationStream.d.ts +21 -0
- package/dist/diagnostic/integrityVerificationStream.js +56 -0
- package/dist/diagnostic/integrityVerificationStream.js.map +1 -0
- package/dist/diagnostic/interface.d.ts +102 -0
- package/dist/diagnostic/interface.js +3 -0
- package/dist/diagnostic/interface.js.map +1 -0
- package/dist/diagnostic/sdkDiagnostic.d.ts +22 -0
- package/dist/diagnostic/sdkDiagnostic.js +216 -0
- package/dist/diagnostic/sdkDiagnostic.js.map +1 -0
- package/dist/diagnostic/sdkDiagnosticFull.d.ts +18 -0
- package/dist/diagnostic/sdkDiagnosticFull.js +35 -0
- package/dist/diagnostic/sdkDiagnosticFull.js.map +1 -0
- package/dist/diagnostic/telemetry.d.ts +25 -0
- package/dist/diagnostic/telemetry.js +70 -0
- package/dist/diagnostic/telemetry.js.map +1 -0
- package/dist/diagnostic/zipGenerators.d.ts +9 -0
- package/dist/diagnostic/zipGenerators.js +64 -0
- package/dist/diagnostic/zipGenerators.js.map +1 -0
- package/dist/diagnostic/zipGenerators.test.js +144 -0
- package/dist/diagnostic/zipGenerators.test.js.map +1 -0
- package/dist/errors.d.ts +8 -3
- package/dist/errors.js +11 -4
- package/dist/errors.js.map +1 -1
- package/dist/interface/config.d.ts +26 -0
- package/dist/interface/config.js +3 -0
- package/dist/interface/config.js.map +1 -0
- package/dist/interface/download.d.ts +2 -2
- package/dist/interface/events.d.ts +60 -20
- package/dist/interface/events.js +11 -1
- package/dist/interface/events.js.map +1 -1
- package/dist/interface/httpClient.d.ts +0 -14
- package/dist/interface/index.d.ts +9 -5
- package/dist/interface/index.js +2 -1
- package/dist/interface/index.js.map +1 -1
- package/dist/interface/nodes.d.ts +21 -1
- package/dist/interface/nodes.js +11 -0
- package/dist/interface/nodes.js.map +1 -1
- package/dist/interface/sharing.d.ts +1 -0
- package/dist/interface/upload.d.ts +57 -3
- package/dist/internal/apiService/driveTypes.d.ts +1341 -465
- package/dist/internal/apiService/errors.js +2 -2
- package/dist/internal/apiService/errors.js.map +1 -1
- package/dist/internal/apiService/transformers.js +2 -0
- package/dist/internal/apiService/transformers.js.map +1 -1
- package/dist/internal/asyncIteratorMap.d.ts +15 -0
- package/dist/internal/asyncIteratorMap.js +59 -0
- package/dist/internal/asyncIteratorMap.js.map +1 -0
- package/dist/internal/asyncIteratorMap.test.js +120 -0
- package/dist/internal/asyncIteratorMap.test.js.map +1 -0
- package/dist/internal/download/apiService.js +32 -31
- package/dist/internal/download/apiService.js.map +1 -1
- package/dist/internal/download/fileDownloader.d.ts +2 -2
- package/dist/internal/download/fileDownloader.js.map +1 -1
- package/dist/internal/events/apiService.d.ts +4 -6
- package/dist/internal/events/apiService.js +15 -22
- package/dist/internal/events/apiService.js.map +1 -1
- package/dist/internal/events/coreEventManager.d.ts +7 -10
- package/dist/internal/events/coreEventManager.js +19 -36
- package/dist/internal/events/coreEventManager.js.map +1 -1
- package/dist/internal/events/coreEventManager.test.d.ts +1 -0
- package/dist/internal/events/coreEventManager.test.js +87 -0
- package/dist/internal/events/coreEventManager.test.js.map +1 -0
- package/dist/internal/events/eventManager.d.ts +11 -36
- package/dist/internal/events/eventManager.js +59 -105
- package/dist/internal/events/eventManager.js.map +1 -1
- package/dist/internal/events/eventManager.test.js +167 -82
- package/dist/internal/events/eventManager.test.js.map +1 -1
- package/dist/internal/events/index.d.ts +13 -33
- package/dist/internal/events/index.js +56 -72
- package/dist/internal/events/index.js.map +1 -1
- package/dist/internal/events/interface.d.ts +59 -14
- package/dist/internal/events/interface.js +13 -3
- package/dist/internal/events/interface.js.map +1 -1
- package/dist/internal/events/volumeEventManager.d.ts +7 -17
- package/dist/internal/events/volumeEventManager.js +58 -45
- package/dist/internal/events/volumeEventManager.js.map +1 -1
- package/dist/internal/events/volumeEventManager.test.d.ts +1 -0
- package/dist/internal/events/volumeEventManager.test.js +203 -0
- package/dist/internal/events/volumeEventManager.test.js.map +1 -0
- package/dist/internal/nodes/apiService.d.ts +2 -2
- package/dist/internal/nodes/apiService.js +16 -6
- package/dist/internal/nodes/apiService.js.map +1 -1
- package/dist/internal/nodes/apiService.test.js +30 -8
- package/dist/internal/nodes/apiService.test.js.map +1 -1
- package/dist/internal/nodes/cache.d.ts +10 -1
- package/dist/internal/nodes/cache.js +18 -0
- 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/cryptoService.d.ts +1 -1
- package/dist/internal/nodes/cryptoService.js.map +1 -1
- package/dist/internal/nodes/cryptoService.test.js +34 -0
- package/dist/internal/nodes/cryptoService.test.js.map +1 -1
- package/dist/internal/nodes/events.d.ts +7 -83
- package/dist/internal/nodes/events.js +43 -217
- package/dist/internal/nodes/events.js.map +1 -1
- package/dist/internal/nodes/events.test.js +27 -277
- package/dist/internal/nodes/events.test.js.map +1 -1
- package/dist/internal/nodes/index.d.ts +3 -4
- package/dist/internal/nodes/index.js +5 -5
- package/dist/internal/nodes/index.js.map +1 -1
- package/dist/internal/nodes/interface.d.ts +3 -1
- package/dist/internal/nodes/nodesAccess.d.ts +15 -0
- package/dist/internal/nodes/nodesAccess.js +65 -7
- package/dist/internal/nodes/nodesAccess.js.map +1 -1
- package/dist/internal/nodes/nodesAccess.test.js +132 -93
- package/dist/internal/nodes/nodesAccess.test.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.d.ts +1 -3
- package/dist/internal/nodes/nodesManagement.js +12 -26
- package/dist/internal/nodes/nodesManagement.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.test.js +35 -14
- package/dist/internal/nodes/nodesManagement.test.js.map +1 -1
- package/dist/internal/shares/cache.d.ts +2 -0
- package/dist/internal/shares/cache.js +2 -0
- package/dist/internal/shares/cache.js.map +1 -1
- package/dist/internal/shares/manager.d.ts +1 -0
- package/dist/internal/shares/manager.js +3 -0
- package/dist/internal/shares/manager.js.map +1 -1
- package/dist/internal/sharing/apiService.js +20 -2
- package/dist/internal/sharing/apiService.js.map +1 -1
- package/dist/internal/sharing/cryptoService.js +1 -0
- package/dist/internal/sharing/cryptoService.js.map +1 -1
- package/dist/internal/sharing/events.d.ts +23 -55
- package/dist/internal/sharing/events.js +46 -138
- package/dist/internal/sharing/events.js.map +1 -1
- package/dist/internal/sharing/events.test.js +77 -180
- package/dist/internal/sharing/events.test.js.map +1 -1
- package/dist/internal/sharing/index.d.ts +4 -5
- package/dist/internal/sharing/index.js +5 -5
- package/dist/internal/sharing/index.js.map +1 -1
- package/dist/internal/sharing/interface.d.ts +3 -0
- package/dist/internal/sharing/sharingManagement.d.ts +2 -3
- package/dist/internal/sharing/sharingManagement.js +7 -9
- package/dist/internal/sharing/sharingManagement.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.test.js +9 -39
- package/dist/internal/sharing/sharingManagement.test.js.map +1 -1
- package/dist/internal/upload/apiService.d.ts +2 -3
- package/dist/internal/upload/apiService.js +7 -4
- package/dist/internal/upload/apiService.js.map +1 -1
- package/dist/internal/upload/fileUploader.d.ts +49 -53
- package/dist/internal/upload/fileUploader.js +91 -395
- package/dist/internal/upload/fileUploader.js.map +1 -1
- package/dist/internal/upload/fileUploader.test.js +38 -292
- package/dist/internal/upload/fileUploader.test.js.map +1 -1
- package/dist/internal/upload/index.d.ts +5 -5
- package/dist/internal/upload/index.js +23 -44
- package/dist/internal/upload/index.js.map +1 -1
- package/dist/internal/upload/interface.d.ts +2 -0
- package/dist/internal/upload/manager.d.ts +6 -6
- package/dist/internal/upload/manager.js +32 -66
- package/dist/internal/upload/manager.js.map +1 -1
- package/dist/internal/upload/manager.test.js +100 -117
- package/dist/internal/upload/manager.test.js.map +1 -1
- package/dist/internal/upload/streamUploader.d.ts +62 -0
- package/dist/internal/upload/streamUploader.js +440 -0
- package/dist/internal/upload/streamUploader.js.map +1 -0
- package/dist/internal/upload/streamUploader.test.d.ts +1 -0
- package/dist/internal/upload/streamUploader.test.js +358 -0
- package/dist/internal/upload/streamUploader.test.js.map +1 -0
- package/dist/protonDriveClient.d.ts +22 -165
- package/dist/protonDriveClient.js +27 -191
- package/dist/protonDriveClient.js.map +1 -1
- package/dist/protonDrivePhotosClient.js +3 -2
- package/dist/protonDrivePhotosClient.js.map +1 -1
- package/package.json +4 -4
- package/src/cache/index.ts +1 -0
- package/src/cache/memoryCache.ts +1 -1
- package/src/cache/nullCache.ts +38 -0
- package/src/config.ts +17 -2
- package/src/crypto/openPGPCrypto.ts +2 -0
- package/src/diagnostic/eventsGenerator.ts +48 -0
- package/src/diagnostic/httpClient.ts +80 -0
- package/src/diagnostic/index.ts +38 -0
- package/src/diagnostic/integrityVerificationStream.ts +56 -0
- package/src/diagnostic/interface.ts +158 -0
- package/src/diagnostic/sdkDiagnostic.ts +238 -0
- package/src/diagnostic/sdkDiagnosticFull.ts +40 -0
- package/src/diagnostic/telemetry.ts +71 -0
- package/src/diagnostic/zipGenerators.test.ts +177 -0
- package/src/diagnostic/zipGenerators.ts +70 -0
- package/src/errors.ts +13 -4
- package/src/interface/config.ts +28 -0
- package/src/interface/download.ts +2 -2
- package/src/interface/events.ts +66 -21
- package/src/interface/httpClient.ts +0 -16
- package/src/interface/index.ts +9 -5
- package/src/interface/nodes.ts +32 -12
- package/src/interface/sharing.ts +1 -0
- package/src/interface/upload.ts +59 -3
- package/src/internal/apiService/driveTypes.ts +1341 -465
- package/src/internal/apiService/errors.ts +3 -2
- package/src/internal/apiService/transformers.ts +2 -0
- package/src/internal/asyncIteratorMap.test.ts +150 -0
- package/src/internal/asyncIteratorMap.ts +64 -0
- package/src/internal/download/apiService.ts +11 -8
- package/src/internal/download/fileDownloader.ts +2 -2
- package/src/internal/events/apiService.ts +25 -28
- package/src/internal/events/coreEventManager.test.ts +101 -0
- package/src/internal/events/coreEventManager.ts +20 -45
- package/src/internal/events/eventManager.test.ts +201 -88
- package/src/internal/events/eventManager.ts +69 -115
- package/src/internal/events/index.ts +54 -84
- package/src/internal/events/interface.ts +70 -15
- package/src/internal/events/volumeEventManager.test.ts +243 -0
- package/src/internal/events/volumeEventManager.ts +55 -53
- package/src/internal/nodes/apiService.test.ts +36 -7
- package/src/internal/nodes/apiService.ts +19 -7
- package/src/internal/nodes/cache.test.ts +1 -0
- package/src/internal/nodes/cache.ts +21 -2
- package/src/internal/nodes/cryptoService.test.ts +38 -0
- package/src/internal/nodes/cryptoService.ts +1 -1
- package/src/internal/nodes/events.test.ts +29 -335
- package/src/internal/nodes/events.ts +45 -253
- package/src/internal/nodes/index.ts +6 -8
- package/src/internal/nodes/interface.ts +6 -3
- package/src/internal/nodes/nodesAccess.test.ts +133 -91
- package/src/internal/nodes/nodesAccess.ts +70 -8
- package/src/internal/nodes/nodesManagement.test.ts +39 -15
- package/src/internal/nodes/nodesManagement.ts +12 -30
- package/src/internal/shares/cache.ts +4 -2
- package/src/internal/shares/manager.ts +9 -5
- package/src/internal/sharing/apiService.ts +25 -2
- package/src/internal/sharing/cache.ts +1 -1
- package/src/internal/sharing/cryptoService.ts +1 -0
- package/src/internal/sharing/events.test.ts +89 -195
- package/src/internal/sharing/events.ts +42 -156
- package/src/internal/sharing/index.ts +6 -9
- package/src/internal/sharing/interface.ts +6 -2
- package/src/internal/sharing/sharingManagement.test.ts +10 -40
- package/src/internal/sharing/sharingManagement.ts +7 -11
- package/src/internal/upload/apiService.ts +5 -6
- package/src/internal/upload/fileUploader.test.ts +46 -376
- package/src/internal/upload/fileUploader.ts +114 -494
- package/src/internal/upload/index.ts +30 -54
- package/src/internal/upload/interface.ts +2 -0
- package/src/internal/upload/manager.test.ts +107 -124
- package/src/internal/upload/manager.ts +48 -80
- package/src/internal/upload/streamUploader.test.ts +468 -0
- package/src/internal/upload/streamUploader.ts +550 -0
- package/src/protonDriveClient.ts +80 -248
- package/src/protonDrivePhotosClient.ts +4 -3
- package/dist/internal/events/cache.d.ts +0 -28
- package/dist/internal/events/cache.js +0 -67
- package/dist/internal/events/cache.js.map +0 -1
- package/dist/internal/events/cache.test.js +0 -43
- package/dist/internal/events/cache.test.js.map +0 -1
- package/dist/internal/nodes/index.test.js +0 -112
- package/dist/internal/nodes/index.test.js.map +0 -1
- package/src/internal/events/cache.test.ts +0 -47
- package/src/internal/events/cache.ts +0 -80
- package/src/internal/nodes/index.test.ts +0 -135
- /package/dist/{internal/events/cache.test.d.ts → diagnostic/zipGenerators.test.d.ts} +0 -0
- /package/dist/internal/{nodes/index.test.d.ts → asyncIteratorMap.test.d.ts} +0 -0
|
@@ -44,6 +44,18 @@ function generateAPIFolderNode(linkOverrides = {}, overrides = {}) {
|
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
function generateAPIAlbumNode(linkOverrides = {}, overrides = {}) {
|
|
48
|
+
const node = generateAPINode();
|
|
49
|
+
return {
|
|
50
|
+
Link: {
|
|
51
|
+
...node.Link,
|
|
52
|
+
Type: 3,
|
|
53
|
+
...linkOverrides,
|
|
54
|
+
},
|
|
55
|
+
...overrides,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
47
59
|
function generateAPINode() {
|
|
48
60
|
return {
|
|
49
61
|
Link: {
|
|
@@ -107,6 +119,15 @@ function generateFolderNode(overrides = {}) {
|
|
|
107
119
|
}
|
|
108
120
|
}
|
|
109
121
|
|
|
122
|
+
function generateAlbumNode(overrides = {}) {
|
|
123
|
+
const node = generateNode();
|
|
124
|
+
return {
|
|
125
|
+
...node,
|
|
126
|
+
type: NodeType.Album,
|
|
127
|
+
...overrides
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
110
131
|
function generateNode() {
|
|
111
132
|
return {
|
|
112
133
|
hash: "nameHash",
|
|
@@ -119,7 +140,7 @@ function generateNode() {
|
|
|
119
140
|
|
|
120
141
|
shareId: undefined,
|
|
121
142
|
isShared: false,
|
|
122
|
-
directMemberRole: MemberRole.
|
|
143
|
+
directMemberRole: MemberRole.Admin,
|
|
123
144
|
|
|
124
145
|
encryptedCrypto: {
|
|
125
146
|
armoredKey: "nodeKey",
|
|
@@ -149,13 +170,13 @@ describe("nodeAPIService", () => {
|
|
|
149
170
|
});
|
|
150
171
|
|
|
151
172
|
describe('iterateNodes', () => {
|
|
152
|
-
async function testIterateNodes(mockedLink: any, expectedNode: any) {
|
|
173
|
+
async function testIterateNodes(mockedLink: any, expectedNode: any, ownVolumeId = 'volumeId') {
|
|
153
174
|
// @ts-expect-error Mocking for testing purposes
|
|
154
175
|
apiMock.post = jest.fn(async () => Promise.resolve({
|
|
155
176
|
Links: [mockedLink],
|
|
156
177
|
}));
|
|
157
178
|
|
|
158
|
-
const nodes = await Array.fromAsync(api.iterateNodes(['volumeId~nodeId']));
|
|
179
|
+
const nodes = await Array.fromAsync(api.iterateNodes(['volumeId~nodeId'], ownVolumeId));
|
|
159
180
|
expect(nodes).toStrictEqual([expectedNode]);
|
|
160
181
|
}
|
|
161
182
|
|
|
@@ -180,6 +201,13 @@ describe("nodeAPIService", () => {
|
|
|
180
201
|
);
|
|
181
202
|
});
|
|
182
203
|
|
|
204
|
+
it('should get album node', async () => {
|
|
205
|
+
await testIterateNodes(
|
|
206
|
+
generateAPIAlbumNode(),
|
|
207
|
+
generateAlbumNode(),
|
|
208
|
+
);
|
|
209
|
+
});
|
|
210
|
+
|
|
183
211
|
it('should get shared node', async () => {
|
|
184
212
|
await testIterateNodes(
|
|
185
213
|
generateAPIFolderNode({}, {
|
|
@@ -213,6 +241,7 @@ describe("nodeAPIService", () => {
|
|
|
213
241
|
shareId: 'shareId',
|
|
214
242
|
directMemberRole: MemberRole.Viewer,
|
|
215
243
|
}),
|
|
244
|
+
'myVolumeId',
|
|
216
245
|
);
|
|
217
246
|
});
|
|
218
247
|
|
|
@@ -240,7 +269,7 @@ describe("nodeAPIService", () => {
|
|
|
240
269
|
],
|
|
241
270
|
}));
|
|
242
271
|
|
|
243
|
-
const generator = api.iterateNodes(['volumeId~nodeId']);
|
|
272
|
+
const generator = api.iterateNodes(['volumeId~nodeId'], 'volumeId');
|
|
244
273
|
|
|
245
274
|
const node1 = await generator.next();
|
|
246
275
|
expect(node1.value).toStrictEqual(generateFolderNode());
|
|
@@ -272,10 +301,10 @@ describe("nodeAPIService", () => {
|
|
|
272
301
|
],
|
|
273
302
|
}));
|
|
274
303
|
|
|
275
|
-
const nodes = await Array.fromAsync(api.iterateNodes(['volumeId1~nodeId1', 'volumeId2~nodeId2']));
|
|
304
|
+
const nodes = await Array.fromAsync(api.iterateNodes(['volumeId1~nodeId1', 'volumeId2~nodeId2'], 'volumeId1'));
|
|
276
305
|
expect(nodes).toStrictEqual([
|
|
277
|
-
generateFolderNode({ uid: 'volumeId1~nodeId1', parentUid: 'volumeId1~parentNodeId1' }),
|
|
278
|
-
generateFolderNode({ uid: 'volumeId2~nodeId2', parentUid: 'volumeId2~parentNodeId2' }),
|
|
306
|
+
generateFolderNode({ uid: 'volumeId1~nodeId1', parentUid: 'volumeId1~parentNodeId1', directMemberRole: MemberRole.Admin }),
|
|
307
|
+
generateFolderNode({ uid: 'volumeId2~nodeId2', parentUid: 'volumeId2~parentNodeId2', directMemberRole: MemberRole.Inherited }),
|
|
279
308
|
]);
|
|
280
309
|
});
|
|
281
310
|
});
|
|
@@ -2,7 +2,7 @@ import { c } from "ttag";
|
|
|
2
2
|
|
|
3
3
|
import { ProtonDriveError, ValidationError } from "../../errors";
|
|
4
4
|
import { Logger, NodeResult } from "../../interface";
|
|
5
|
-
import { RevisionState } from "../../interface/nodes";
|
|
5
|
+
import { MemberRole, RevisionState } from "../../interface/nodes";
|
|
6
6
|
import { DriveAPIService, drivePaths, isCodeOk, nodeTypeNumberToNodeType, permissionsToDirectMemberRole } from "../apiService";
|
|
7
7
|
import { splitNodeUid, makeNodeUid, makeNodeRevisionUid, splitNodeRevisionUid, makeNodeThumbnailUid } from "../uids";
|
|
8
8
|
import { EncryptedNode, EncryptedRevision, Thumbnail } from "./interface";
|
|
@@ -56,15 +56,15 @@ export class NodeAPIService {
|
|
|
56
56
|
this.apiService = apiService;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
async getNode(nodeUid: string, signal?: AbortSignal): Promise<EncryptedNode> {
|
|
60
|
-
const nodesGenerator = this.iterateNodes([nodeUid], signal);
|
|
59
|
+
async getNode(nodeUid: string, ownVolumeId: string, signal?: AbortSignal): Promise<EncryptedNode> {
|
|
60
|
+
const nodesGenerator = this.iterateNodes([nodeUid], ownVolumeId, signal);
|
|
61
61
|
const result = await nodesGenerator.next();
|
|
62
62
|
await nodesGenerator.return("finish");
|
|
63
63
|
return result.value;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
// Improvement requested: split into multiple calls for many nodes.
|
|
67
|
-
async* iterateNodes(nodeUids: string[], signal?: AbortSignal): AsyncGenerator<EncryptedNode> {
|
|
67
|
+
async* iterateNodes(nodeUids: string[], ownVolumeId: string, signal?: AbortSignal): AsyncGenerator<EncryptedNode> {
|
|
68
68
|
const allNodeIds = nodeUids.map(splitNodeUid);
|
|
69
69
|
|
|
70
70
|
const nodeIdsByVolumeId = new Map<string, string[]>();
|
|
@@ -81,13 +81,15 @@ export class NodeAPIService {
|
|
|
81
81
|
const errors = [];
|
|
82
82
|
|
|
83
83
|
for (const [volumeId, nodeIds] of nodeIdsByVolumeId.entries()) {
|
|
84
|
+
const isAdmin = volumeId === ownVolumeId;
|
|
85
|
+
|
|
84
86
|
const response = await this.apiService.post<PostLoadLinksMetadataRequest, PostLoadLinksMetadataResponse>(`drive/v2/volumes/${volumeId}/links`, {
|
|
85
87
|
LinkIDs: nodeIds,
|
|
86
88
|
}, signal);
|
|
87
89
|
|
|
88
90
|
for (const link of response.Links) {
|
|
89
91
|
try {
|
|
90
|
-
yield linkToEncryptedNode(this.logger, volumeId, link);
|
|
92
|
+
yield linkToEncryptedNode(this.logger, volumeId, link, isAdmin);
|
|
91
93
|
} catch (error: unknown) {
|
|
92
94
|
this.logger.error(`Failed to transform node ${link.Link.LinkID}`, error);
|
|
93
95
|
errors.push(error);
|
|
@@ -363,7 +365,7 @@ function* handleResponseErrors(nodeUids: string[], volumeId: string, responses:
|
|
|
363
365
|
}
|
|
364
366
|
}
|
|
365
367
|
|
|
366
|
-
function linkToEncryptedNode(logger: Logger, volumeId: string, link: PostLoadLinksMetadataResponse['Links'][0]): EncryptedNode {
|
|
368
|
+
function linkToEncryptedNode(logger: Logger, volumeId: string, link: PostLoadLinksMetadataResponse['Links'][0], isAdmin: boolean): EncryptedNode {
|
|
367
369
|
const baseNodeMetadata = {
|
|
368
370
|
// Internal metadata
|
|
369
371
|
hash: link.Link.NameHash || undefined,
|
|
@@ -379,7 +381,7 @@ function linkToEncryptedNode(logger: Logger, volumeId: string, link: PostLoadLin
|
|
|
379
381
|
// Sharing node metadata
|
|
380
382
|
shareId: link.Sharing?.ShareID || undefined,
|
|
381
383
|
isShared: !!link.Sharing,
|
|
382
|
-
directMemberRole: permissionsToDirectMemberRole(logger, link.Membership?.Permissions),
|
|
384
|
+
directMemberRole: isAdmin ? MemberRole.Admin : permissionsToDirectMemberRole(logger, link.Membership?.Permissions),
|
|
383
385
|
}
|
|
384
386
|
const baseCryptoNodeMetadata = {
|
|
385
387
|
signatureEmail: link.Link.SignatureEmail || undefined,
|
|
@@ -426,6 +428,15 @@ function linkToEncryptedNode(logger: Logger, volumeId: string, link: PostLoadLin
|
|
|
426
428
|
}
|
|
427
429
|
}
|
|
428
430
|
|
|
431
|
+
if (link.Link.Type === 3) {
|
|
432
|
+
return {
|
|
433
|
+
...baseNodeMetadata,
|
|
434
|
+
encryptedCrypto: {
|
|
435
|
+
...baseCryptoNodeMetadata,
|
|
436
|
+
},
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
429
440
|
throw new Error(`Unknown node type: ${link.Link.Type}`);
|
|
430
441
|
}
|
|
431
442
|
|
|
@@ -437,6 +448,7 @@ function transformRevisionResponse(
|
|
|
437
448
|
return {
|
|
438
449
|
uid: makeNodeRevisionUid(volumeId, nodeId, revision.ID),
|
|
439
450
|
state: revision.State === APIRevisionState.Active ? RevisionState.Active : RevisionState.Superseded,
|
|
451
|
+
// @ts-expect-error: API doc is wrong, CreateTime is not optional.
|
|
440
452
|
creationTime: new Date(revision.CreateTime*1000),
|
|
441
453
|
storageSize: revision.Size,
|
|
442
454
|
signatureEmail: revision.SignatureEmail || undefined,
|
|
@@ -108,6 +108,7 @@ describe('nodesCache', () => {
|
|
|
108
108
|
creationTime: new Date('2021-01-01'),
|
|
109
109
|
storageSize: 100,
|
|
110
110
|
contentAuthor: resultOk('test@test.com'),
|
|
111
|
+
claimedModificationTime: new Date('2021-02-01')
|
|
111
112
|
});
|
|
112
113
|
const node = generateNode('node1', '', { activeRevision });
|
|
113
114
|
|
|
@@ -6,6 +6,7 @@ import { DecryptedNode, DecryptedRevision } from "./interface";
|
|
|
6
6
|
export enum CACHE_TAG_KEYS {
|
|
7
7
|
ParentUid = 'nodeParentUid',
|
|
8
8
|
Trashed = 'nodeTrashed',
|
|
9
|
+
Roots = 'nodeRoot',
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
type DecryptedNodeResult = (
|
|
@@ -15,10 +16,10 @@ type DecryptedNodeResult = (
|
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Provides caching for nodes metadata.
|
|
18
|
-
*
|
|
19
|
+
*
|
|
19
20
|
* The cache is responsible for serialising and deserialising node metadata,
|
|
20
21
|
* recording parent-child relationships, and recursively removing nodes.
|
|
21
|
-
*
|
|
22
|
+
*
|
|
22
23
|
* The cache of node metadata should not contain any crypto material.
|
|
23
24
|
*/
|
|
24
25
|
export class NodesCache {
|
|
@@ -35,6 +36,8 @@ export class NodesCache {
|
|
|
35
36
|
const tags = [`volume:${volumeId}`];
|
|
36
37
|
if (node.parentUid) {
|
|
37
38
|
tags.push(`${CACHE_TAG_KEYS.ParentUid}:${node.parentUid}`)
|
|
39
|
+
} else {
|
|
40
|
+
tags.push(`${CACHE_TAG_KEYS.Roots}:${volumeId}`)
|
|
38
41
|
}
|
|
39
42
|
if (node.trashTime) {
|
|
40
43
|
tags.push(`${CACHE_TAG_KEYS.Trashed}`)
|
|
@@ -74,6 +77,17 @@ export class NodesCache {
|
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Remove all entries associated with a volume.
|
|
82
|
+
*
|
|
83
|
+
* This is needed when a user looses access to a volume.
|
|
84
|
+
*/
|
|
85
|
+
async removeVolume(volumeId: string): Promise<void> {
|
|
86
|
+
for await (const result of this.iterateRootNodeUids(volumeId)) {
|
|
87
|
+
await this.removeNodes([result.key]);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
77
91
|
/**
|
|
78
92
|
* Remove corrupted node never throws, but it logs so we can know
|
|
79
93
|
* about issues and fix them. It is crucial to remove corrupted
|
|
@@ -142,6 +156,10 @@ export class NodesCache {
|
|
|
142
156
|
}
|
|
143
157
|
}
|
|
144
158
|
|
|
159
|
+
async *iterateRootNodeUids(volumeId: string): AsyncGenerator<EntityResult<string>> {
|
|
160
|
+
yield* this.driveCache.iterateEntitiesByTag(`${CACHE_TAG_KEYS.Roots}:${volumeId}`);
|
|
161
|
+
}
|
|
162
|
+
|
|
145
163
|
async *iterateTrashedNodes(): AsyncGenerator<DecryptedNodeResult> {
|
|
146
164
|
for await (const result of this.driveCache.iterateEntitiesByTag(CACHE_TAG_KEYS.Trashed)) {
|
|
147
165
|
const node = await this.convertCacheResult(result);
|
|
@@ -261,6 +279,7 @@ function deserialiseRevision(revision: any): Result<DecryptedRevision, Error> {
|
|
|
261
279
|
return resultOk({
|
|
262
280
|
...revision.value,
|
|
263
281
|
creationTime: new Date(revision.value.creationTime),
|
|
282
|
+
claimedModificationTime: new Date(revision.value.claimedModificationTime)
|
|
264
283
|
});
|
|
265
284
|
}
|
|
266
285
|
|
|
@@ -578,6 +578,44 @@ describe("nodesCryptoService", () => {
|
|
|
578
578
|
});
|
|
579
579
|
});
|
|
580
580
|
|
|
581
|
+
describe("album node", () => {
|
|
582
|
+
const encryptedNode = {
|
|
583
|
+
uid: "volumeId~nodeId",
|
|
584
|
+
parentUid: "volumeId~parentId",
|
|
585
|
+
encryptedCrypto: {
|
|
586
|
+
signatureEmail: "signatureEmail",
|
|
587
|
+
nameSignatureEmail: "nameSignatureEmail",
|
|
588
|
+
armoredKey: "armoredKey",
|
|
589
|
+
armoredNodePassphrase: "armoredNodePassphrase",
|
|
590
|
+
armoredNodePassphraseSignature: "armoredNodePassphraseSignature",
|
|
591
|
+
},
|
|
592
|
+
} as EncryptedNode;
|
|
593
|
+
|
|
594
|
+
it("should decrypt successfuly", async () => {
|
|
595
|
+
const result = await cryptoService.decryptNode(encryptedNode, parentKey);
|
|
596
|
+
|
|
597
|
+
expect(result).toMatchObject({
|
|
598
|
+
node: {
|
|
599
|
+
name: { ok: true, value: "name" },
|
|
600
|
+
keyAuthor: { ok: true, value: "signatureEmail" },
|
|
601
|
+
nameAuthor: { ok: true, value: "nameSignatureEmail" },
|
|
602
|
+
folder: undefined,
|
|
603
|
+
activeRevision: undefined,
|
|
604
|
+
errors: undefined,
|
|
605
|
+
},
|
|
606
|
+
keys: {
|
|
607
|
+
passphrase: "pass",
|
|
608
|
+
key: "decryptedKey",
|
|
609
|
+
passphraseSessionKey: "passphraseSessionKey",
|
|
610
|
+
hashKey: new Uint8Array(),
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
expect(account.getPublicKeys).toHaveBeenCalledTimes(2);
|
|
615
|
+
expect(telemetry.logEvent).not.toHaveBeenCalled();
|
|
616
|
+
});
|
|
617
|
+
});
|
|
618
|
+
|
|
581
619
|
describe("anonymous node", () => {
|
|
582
620
|
const encryptedNode = {
|
|
583
621
|
uid: "volumeId~nodeId",
|
|
@@ -422,7 +422,7 @@ export class NodesCryptoService {
|
|
|
422
422
|
};
|
|
423
423
|
|
|
424
424
|
async moveNode(
|
|
425
|
-
node: DecryptedNode,
|
|
425
|
+
node: Pick<DecryptedNode, 'name'>,
|
|
426
426
|
keys: { passphrase: string, passphraseSessionKey: SessionKey, nameSessionKey: SessionKey },
|
|
427
427
|
parentKeys: { key: PrivateKey, hashKey: Uint8Array },
|
|
428
428
|
address: { email: string, addressKey: PrivateKey },
|