@wireapp/core 42.19.1 → 42.20.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/lib/Account.d.ts +5 -3
- package/lib/Account.d.ts.map +1 -1
- package/lib/Account.js +12 -6
- package/lib/conversation/ConversationService/ConversationService.d.ts +3 -2
- package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
- package/lib/conversation/ConversationService/ConversationService.js +3 -2
- package/lib/conversation/ConversationService/ConversationService.test.js +2 -1
- package/lib/conversation/SubconversationService/SubconversationService.d.ts +14 -3
- package/lib/conversation/SubconversationService/SubconversationService.d.ts.map +1 -1
- package/lib/conversation/SubconversationService/SubconversationService.js +33 -19
- package/lib/conversation/SubconversationService/SubconversationService.test.js +37 -53
- package/lib/conversation/SubconversationService/subconversationUtil.d.ts +4 -0
- package/lib/conversation/SubconversationService/subconversationUtil.d.ts.map +1 -0
- package/lib/conversation/SubconversationService/subconversationUtil.js +25 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts +4 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.js +2 -2
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.js +8 -8
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +2 -11
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.js +8 -24
- package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +5 -4
- package/lib/messagingProtocols/mls/types.d.ts +2 -3
- package/lib/messagingProtocols/mls/types.d.ts.map +1 -1
- package/lib/self/SelfService.d.ts +7 -0
- package/lib/self/SelfService.d.ts.map +1 -1
- package/lib/self/SelfService.js +19 -0
- package/lib/self/SelfService.test.d.ts +2 -0
- package/lib/self/SelfService.test.d.ts.map +1 -0
- package/lib/self/SelfService.test.js +54 -0
- package/lib/storage/CoreDB.d.ts +10 -0
- package/lib/storage/CoreDB.d.ts.map +1 -1
- package/lib/storage/CoreDB.js +3 -1
- package/lib/user/UserService.d.ts +5 -0
- package/lib/user/UserService.d.ts.map +1 -1
- package/lib/user/UserService.js +12 -0
- package/package.json +9 -9
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.d.ts +0 -13
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.js +0 -67
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.test.d.ts +0 -2
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.test.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.test.js +0 -72
|
@@ -22,7 +22,7 @@ const conversation_1 = require("@wireapp/api-client/lib/conversation");
|
|
|
22
22
|
const http_1 = require("@wireapp/api-client/lib/http");
|
|
23
23
|
const api_client_1 = require("@wireapp/api-client");
|
|
24
24
|
const SubconversationService_1 = require("./SubconversationService");
|
|
25
|
-
const
|
|
25
|
+
const CoreDB_1 = require("../../storage/CoreDB");
|
|
26
26
|
const fullyQualifiedClientIdUtils_1 = require("../../util/fullyQualifiedClientIdUtils");
|
|
27
27
|
const getSubconversationResponse = ({ epoch, epochTimestamp, parentConversationId, groupId, members = [], subconversationId = conversation_1.SUBCONVERSATION_ID.CONFERENCE, }) => {
|
|
28
28
|
return {
|
|
@@ -35,7 +35,7 @@ const getSubconversationResponse = ({ epoch, epochTimestamp, parentConversationI
|
|
|
35
35
|
epoch_timestamp: epochTimestamp,
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
|
-
const buildSubconversationService = () => {
|
|
38
|
+
const buildSubconversationService = async () => {
|
|
39
39
|
const apiClient = new api_client_1.APIClient({ urls: api_client_1.APIClient.BACKEND.STAGING });
|
|
40
40
|
const mlsService = {
|
|
41
41
|
conversationExists: jest.fn(),
|
|
@@ -51,8 +51,9 @@ const buildSubconversationService = () => {
|
|
|
51
51
|
off: jest.fn(),
|
|
52
52
|
removeClientsFromConversation: jest.fn(),
|
|
53
53
|
};
|
|
54
|
-
const
|
|
55
|
-
|
|
54
|
+
const coreDatabase = await (0, CoreDB_1.openDB)('core-test-db');
|
|
55
|
+
const subconversationService = new SubconversationService_1.SubconversationService(apiClient, coreDatabase, mlsService);
|
|
56
|
+
return [subconversationService, { apiClient, mlsService, coreDatabase }];
|
|
56
57
|
};
|
|
57
58
|
describe('SubconversationService', () => {
|
|
58
59
|
describe('joinConferenceSubconversation', () => {
|
|
@@ -61,7 +62,7 @@ describe('SubconversationService', () => {
|
|
|
61
62
|
jest.clearAllMocks();
|
|
62
63
|
});
|
|
63
64
|
it('wipes group locally (if it exists) before registering a group if remote epoch is equal 0', async () => {
|
|
64
|
-
const [subconversationService, { apiClient, mlsService }] = buildSubconversationService();
|
|
65
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
65
66
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
66
67
|
const subconversationGroupId = 'subconversationGroupId';
|
|
67
68
|
const subconversationResponse = getSubconversationResponse({
|
|
@@ -78,7 +79,7 @@ describe('SubconversationService', () => {
|
|
|
78
79
|
expect(mlsService.registerConversation).toHaveBeenCalledWith(subconversationGroupId, []);
|
|
79
80
|
});
|
|
80
81
|
it('registers a group if remote epoch is 0 and group does not exist locally', async () => {
|
|
81
|
-
const [subconversationService, { apiClient, mlsService }] = buildSubconversationService();
|
|
82
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
82
83
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
83
84
|
const subconversationGroupId = 'subconversationGroupId';
|
|
84
85
|
const subconversationResponse = getSubconversationResponse({
|
|
@@ -96,7 +97,7 @@ describe('SubconversationService', () => {
|
|
|
96
97
|
});
|
|
97
98
|
it('deletes conference subconversation from backend if group is already established and epoch is older than one day, then rejoins', async () => {
|
|
98
99
|
jest.useFakeTimers();
|
|
99
|
-
const [subconversationService, { apiClient, mlsService }] = buildSubconversationService();
|
|
100
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
100
101
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
101
102
|
const subconversationGroupId = 'subconversationGroupId';
|
|
102
103
|
const initialSubconversationEpoch = 1;
|
|
@@ -133,7 +134,7 @@ describe('SubconversationService', () => {
|
|
|
133
134
|
});
|
|
134
135
|
it('joins conference subconversation with external commit if group is already established and epoch is younger than one day', async () => {
|
|
135
136
|
jest.useFakeTimers();
|
|
136
|
-
const [subconversationService, { apiClient, mlsService }] = buildSubconversationService();
|
|
137
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
137
138
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
138
139
|
const subconversationGroupId = 'subconversationGroupId';
|
|
139
140
|
const subconversationEpoch = 1;
|
|
@@ -157,7 +158,7 @@ describe('SubconversationService', () => {
|
|
|
157
158
|
expect(mlsService.joinByExternalCommit).toHaveBeenCalled();
|
|
158
159
|
});
|
|
159
160
|
it('retries to join if registering a conversations throws an error', async () => {
|
|
160
|
-
const [subconversationService, { apiClient, mlsService }] = buildSubconversationService();
|
|
161
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
161
162
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
162
163
|
const subconversationGroupId = 'subconversationGroupId';
|
|
163
164
|
const subconversationResponse = getSubconversationResponse({
|
|
@@ -178,7 +179,7 @@ describe('SubconversationService', () => {
|
|
|
178
179
|
expect(mlsService.registerConversation).toHaveBeenCalledTimes(2);
|
|
179
180
|
});
|
|
180
181
|
it('returns fresh epoch number after joining the group', async () => {
|
|
181
|
-
const [subconversationService, { apiClient, mlsService }] = buildSubconversationService();
|
|
182
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
182
183
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
183
184
|
const subconversationGroupId = 'subconversationGroupId';
|
|
184
185
|
const subconversationResponse = getSubconversationResponse({
|
|
@@ -200,31 +201,31 @@ describe('SubconversationService', () => {
|
|
|
200
201
|
});
|
|
201
202
|
describe('leaveConferenceSubconversation', () => {
|
|
202
203
|
it('does nothing if subconversation id is not found in the store', async () => {
|
|
203
|
-
const [subconversationService, { mlsService }] = buildSubconversationService();
|
|
204
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
204
205
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
205
206
|
await subconversationService.leaveConferenceSubconversation(parentConversationId);
|
|
206
207
|
expect(mlsService.wipeConversation).not.toHaveBeenCalled();
|
|
207
208
|
});
|
|
208
209
|
it('removes subconversation id from the store if conversations was known but not established locally', async () => {
|
|
209
|
-
const [subconversationService, { mlsService }] = buildSubconversationService();
|
|
210
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
210
211
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
211
212
|
const subconversationGroupId = 'subconversationGroupId';
|
|
212
|
-
|
|
213
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
213
214
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
|
|
214
215
|
await subconversationService.leaveConferenceSubconversation(parentConversationId);
|
|
215
|
-
const groupId =
|
|
216
|
+
const groupId = await subconversationService.getSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
216
217
|
expect(groupId).toEqual(undefined);
|
|
217
218
|
expect(mlsService.wipeConversation).not.toHaveBeenCalled();
|
|
218
219
|
});
|
|
219
220
|
it('deletes self client from conference subconversation', async () => {
|
|
220
|
-
const [subconversationService, { apiClient, mlsService }] = buildSubconversationService();
|
|
221
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
221
222
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
222
223
|
const subconversationGroupId = 'subconversationGroupId';
|
|
223
|
-
|
|
224
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
224
225
|
jest.spyOn(apiClient.api.conversation, 'deleteSubconversationSelf');
|
|
225
226
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
|
|
226
227
|
await subconversationService.leaveConferenceSubconversation(parentConversationId);
|
|
227
|
-
const groupId =
|
|
228
|
+
const groupId = await subconversationService.getSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
228
229
|
expect(groupId).toEqual(undefined);
|
|
229
230
|
expect(apiClient.api.conversation.deleteSubconversationSelf).toHaveBeenCalledWith(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
230
231
|
expect(mlsService.wipeConversation).toHaveBeenCalledWith(subconversationGroupId);
|
|
@@ -232,47 +233,31 @@ describe('SubconversationService', () => {
|
|
|
232
233
|
});
|
|
233
234
|
describe('getSubconversationEpochInfo', () => {
|
|
234
235
|
it('returns null if subconversation id is not known by a client', async () => {
|
|
235
|
-
const [subconversationService
|
|
236
|
+
const [subconversationService] = await buildSubconversationService();
|
|
236
237
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
237
|
-
|
|
238
|
-
const response = await subconversationService.getSubconversationEpochInfo(parentConversationId);
|
|
238
|
+
const parentConversationGroupId = 'parentConversationGroupId';
|
|
239
|
+
const response = await subconversationService.getSubconversationEpochInfo(parentConversationId, parentConversationGroupId);
|
|
239
240
|
expect(response).toEqual(null);
|
|
240
241
|
});
|
|
241
242
|
it('returns null if MLS group for subconversation does not exist locally', async () => {
|
|
242
|
-
const [subconversationService, { mlsService }] = buildSubconversationService();
|
|
243
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
243
244
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
244
245
|
const parentConversationGroupId = 'parentConversationGroupId';
|
|
245
|
-
const subconversationGroupId = 'subconversationGroupId';
|
|
246
|
-
jest
|
|
247
|
-
.spyOn(mlsService, 'getGroupIdFromConversationId')
|
|
248
|
-
.mockImplementation(async (_conversationId, subconverstionId) => {
|
|
249
|
-
if (subconverstionId) {
|
|
250
|
-
return subconversationGroupId;
|
|
251
|
-
}
|
|
252
|
-
return parentConversationGroupId;
|
|
253
|
-
});
|
|
254
246
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
|
|
255
|
-
const response = await subconversationService.getSubconversationEpochInfo(parentConversationId);
|
|
247
|
+
const response = await subconversationService.getSubconversationEpochInfo(parentConversationId, parentConversationGroupId);
|
|
256
248
|
expect(response).toEqual(null);
|
|
257
249
|
});
|
|
258
250
|
it('returns epoch info and advances epoch number', async () => {
|
|
259
|
-
const [subconversationService, { mlsService }] = buildSubconversationService();
|
|
251
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
260
252
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
261
253
|
const parentConversationGroupId = 'parentConversationGroupId';
|
|
262
254
|
const subconversationGroupId = 'subconversationGroupId';
|
|
263
|
-
jest
|
|
264
|
-
.spyOn(mlsService, 'getGroupIdFromConversationId')
|
|
265
|
-
.mockImplementation(async (_conversationId, subconverstionId) => {
|
|
266
|
-
if (subconverstionId) {
|
|
267
|
-
return subconversationGroupId;
|
|
268
|
-
}
|
|
269
|
-
return parentConversationGroupId;
|
|
270
|
-
});
|
|
271
255
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
|
|
272
256
|
const mockedEpoch = 2;
|
|
273
257
|
jest.spyOn(mlsService, 'getEpoch').mockResolvedValueOnce(mockedEpoch);
|
|
274
258
|
const mockedSecretKey = 'mockedSecretKey';
|
|
275
259
|
jest.spyOn(mlsService, 'exportSecretKey').mockResolvedValueOnce(mockedSecretKey);
|
|
260
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
276
261
|
const subconversationMemberIds = [{ userId: 'userId1', clientId: 'clientId1', domain: 'domain' }];
|
|
277
262
|
const parentConversationMemberIds = [
|
|
278
263
|
{ userId: 'userId1', clientId: 'clientId1', domain: 'domain' },
|
|
@@ -284,7 +269,7 @@ describe('SubconversationService', () => {
|
|
|
284
269
|
}
|
|
285
270
|
return subconversationMemberIds;
|
|
286
271
|
});
|
|
287
|
-
const response = await subconversationService.getSubconversationEpochInfo(parentConversationId, true);
|
|
272
|
+
const response = await subconversationService.getSubconversationEpochInfo(parentConversationId, parentConversationGroupId, true);
|
|
288
273
|
const expected = {
|
|
289
274
|
epoch: mockedEpoch,
|
|
290
275
|
keyLength: 32,
|
|
@@ -300,12 +285,12 @@ describe('SubconversationService', () => {
|
|
|
300
285
|
});
|
|
301
286
|
describe('subscribeToEpochUpdates', () => {
|
|
302
287
|
it('should subscribe to newEpoch event', async () => {
|
|
303
|
-
const [subconversationService, { mlsService }] = buildSubconversationService();
|
|
288
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
304
289
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
305
290
|
const parentConversationGroupId = 'parentConversationGroupId';
|
|
306
291
|
const subconversationGroupId = 'subconversationGroupId';
|
|
307
292
|
const mockedInitialEpoch = 1;
|
|
308
|
-
|
|
293
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
309
294
|
const mockedEpochInfo = { epoch: mockedInitialEpoch, keyLength: 32, members: [], secretKey: '' };
|
|
310
295
|
jest.spyOn(subconversationService, 'getSubconversationEpochInfo').mockResolvedValueOnce(mockedEpochInfo);
|
|
311
296
|
jest
|
|
@@ -318,9 +303,9 @@ describe('SubconversationService', () => {
|
|
|
318
303
|
return undefined;
|
|
319
304
|
};
|
|
320
305
|
const onEpochUpdateCallback = jest.fn();
|
|
321
|
-
const unsubscribe = await subconversationService.subscribeToEpochUpdates(parentConversationId, findConversationByGroupId, onEpochUpdateCallback);
|
|
306
|
+
const unsubscribe = await subconversationService.subscribeToEpochUpdates(parentConversationId, parentConversationGroupId, findConversationByGroupId, onEpochUpdateCallback);
|
|
322
307
|
expect(mlsService.on).toHaveBeenCalledWith('newEpoch', expect.any(Function));
|
|
323
|
-
expect(subconversationService.getSubconversationEpochInfo).toHaveBeenCalledWith(parentConversationId);
|
|
308
|
+
expect(subconversationService.getSubconversationEpochInfo).toHaveBeenCalledWith(parentConversationId, parentConversationGroupId);
|
|
324
309
|
expect(onEpochUpdateCallback).toHaveBeenCalledWith(mockedEpochInfo);
|
|
325
310
|
unsubscribe();
|
|
326
311
|
expect(mlsService.off).toHaveBeenCalledWith('newEpoch', expect.any(Function));
|
|
@@ -328,9 +313,8 @@ describe('SubconversationService', () => {
|
|
|
328
313
|
});
|
|
329
314
|
describe('removeClientFromConferenceSubconversation', () => {
|
|
330
315
|
it('does nothing if subconversation group is not known', async () => {
|
|
331
|
-
const [subconversationService, { mlsService }] = buildSubconversationService();
|
|
316
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
332
317
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
333
|
-
jest.spyOn(mlsService, 'getGroupIdFromConversationId').mockResolvedValue(undefined);
|
|
334
318
|
const user = { id: 'userId', domain: 'domain' };
|
|
335
319
|
const clientId = 'clientId';
|
|
336
320
|
const clientToRemove = { user, clientId };
|
|
@@ -338,10 +322,10 @@ describe('SubconversationService', () => {
|
|
|
338
322
|
expect(mlsService.removeClientsFromConversation).not.toHaveBeenCalled();
|
|
339
323
|
});
|
|
340
324
|
it('does nothing if subconversation group is not established', async () => {
|
|
341
|
-
const [subconversationService, { mlsService }] = buildSubconversationService();
|
|
325
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
342
326
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
343
327
|
const subconversationGroupId = 'subconversationGroupId';
|
|
344
|
-
|
|
328
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
345
329
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValue(false);
|
|
346
330
|
const user = { id: 'userId', domain: 'domain' };
|
|
347
331
|
const clientId = 'clientId';
|
|
@@ -350,10 +334,10 @@ describe('SubconversationService', () => {
|
|
|
350
334
|
expect(mlsService.removeClientsFromConversation).not.toHaveBeenCalled();
|
|
351
335
|
});
|
|
352
336
|
it('does nothing if client is not a subconversation group member', async () => {
|
|
353
|
-
const [subconversationService, { mlsService }] = buildSubconversationService();
|
|
337
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
354
338
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
355
339
|
const subconversationGroupId = 'subconversationGroupId';
|
|
356
|
-
|
|
340
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
357
341
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValue(true);
|
|
358
342
|
const subconversationMemberIds = [
|
|
359
343
|
{ userId: 'userId1', clientId: 'clientId1', domain: 'domain' },
|
|
@@ -367,10 +351,10 @@ describe('SubconversationService', () => {
|
|
|
367
351
|
expect(mlsService.removeClientsFromConversation).not.toHaveBeenCalled();
|
|
368
352
|
});
|
|
369
353
|
it('removes client from subconversation group', async () => {
|
|
370
|
-
const [subconversationService, { mlsService }] = buildSubconversationService();
|
|
354
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
371
355
|
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
372
356
|
const subconversationGroupId = 'subconversationGroupId';
|
|
373
|
-
|
|
357
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
374
358
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValue(true);
|
|
375
359
|
const user = { id: 'userId3', domain: 'domain3' };
|
|
376
360
|
const clientId = 'clientId3';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SUBCONVERSATION_ID } from '@wireapp/api-client/lib/conversation';
|
|
2
|
+
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
3
|
+
export declare const generateSubconversationStoreKey: (parentConversationId: QualifiedId, subconversationId: SUBCONVERSATION_ID) => `${string}@${string}:${SUBCONVERSATION_ID}`;
|
|
4
|
+
//# sourceMappingURL=subconversationUtil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subconversationUtil.d.ts","sourceRoot":"","sources":["../../../src/conversation/SubconversationService/subconversationUtil.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAEzD,eAAO,MAAM,+BAA+B,yBACpB,WAAW,qBACd,kBAAkB,KACpC,GAAG,MAAM,IAAI,MAAM,IAAI,kBAAkB,EAE3C,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Wire
|
|
4
|
+
* Copyright (C) 2023 Wire Swiss GmbH
|
|
5
|
+
*
|
|
6
|
+
* This program is free software: you can redistribute it and/or modify
|
|
7
|
+
* it under the terms of the GNU General Public License as published by
|
|
8
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
* (at your option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
* GNU General Public License for more details.
|
|
15
|
+
*
|
|
16
|
+
* You should have received a copy of the GNU General Public License
|
|
17
|
+
* along with this program. If not, see http://www.gnu.org/licenses/.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.generateSubconversationStoreKey = void 0;
|
|
22
|
+
const generateSubconversationStoreKey = (parentConversationId, subconversationId) => {
|
|
23
|
+
return `${parentConversationId.id}@${parentConversationId.domain}:${subconversationId}`;
|
|
24
|
+
};
|
|
25
|
+
exports.generateSubconversationStoreKey = generateSubconversationStoreKey;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { SUBCONVERSATION_ID } from '@wireapp/api-client/lib/conversation';
|
|
1
2
|
import { ConversationMLSMessageAddEvent } from '@wireapp/api-client/lib/event';
|
|
3
|
+
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
2
4
|
import { HandledEventPayload } from '../../../../../notification';
|
|
3
5
|
import { MLSService } from '../../../MLSService/MLSService';
|
|
4
6
|
interface HandleMLSMessageAddParams {
|
|
5
7
|
event: ConversationMLSMessageAddEvent;
|
|
6
8
|
mlsService: MLSService;
|
|
9
|
+
groupIdFromConversationId: (conversationId: QualifiedId, subconversationId?: SUBCONVERSATION_ID) => Promise<string | undefined>;
|
|
7
10
|
}
|
|
8
|
-
export declare const handleMLSMessageAdd: ({ event, mlsService, }: HandleMLSMessageAddParams) => Promise<HandledEventPayload | null>;
|
|
11
|
+
export declare const handleMLSMessageAdd: ({ event, mlsService, groupIdFromConversationId, }: HandleMLSMessageAddParams) => Promise<HandledEventPayload | null>;
|
|
9
12
|
export {};
|
|
10
13
|
//# sourceMappingURL=messageAdd.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messageAdd.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,8BAA8B,EAAC,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"messageAdd.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAC,8BAA8B,EAAC,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAKzD,OAAO,EAAC,mBAAmB,EAAC,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAC,UAAU,EAAuB,MAAM,gCAAgC,CAAC;AAEhF,UAAU,yBAAyB;IACjC,KAAK,EAAE,8BAA8B,CAAC;IACtC,UAAU,EAAE,UAAU,CAAC;IACvB,yBAAyB,EAAE,CACzB,cAAc,EAAE,WAAW,EAC3B,iBAAiB,CAAC,EAAE,kBAAkB,KACnC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAClC;AAED,eAAO,MAAM,mBAAmB,sDAI7B,yBAAyB,KAAG,QAAQ,mBAAmB,GAAG,IAAI,CA+ChE,CAAC"}
|
|
@@ -22,11 +22,11 @@ exports.handleMLSMessageAdd = void 0;
|
|
|
22
22
|
const bazinga64_1 = require("bazinga64");
|
|
23
23
|
const protocol_messaging_1 = require("@wireapp/protocol-messaging");
|
|
24
24
|
const MLSService_1 = require("../../../MLSService/MLSService");
|
|
25
|
-
const handleMLSMessageAdd = async ({ event, mlsService, }) => {
|
|
25
|
+
const handleMLSMessageAdd = async ({ event, mlsService, groupIdFromConversationId, }) => {
|
|
26
26
|
var _a;
|
|
27
27
|
const encryptedData = bazinga64_1.Decoder.fromBase64(event.data).asBytes;
|
|
28
28
|
const qualifiedConversationId = (_a = event.qualified_conversation) !== null && _a !== void 0 ? _a : { id: event.conversation, domain: '' };
|
|
29
|
-
const groupId = await
|
|
29
|
+
const groupId = await groupIdFromConversationId(qualifiedConversationId, event.subconv);
|
|
30
30
|
// We should not receive a message for a group the client is not aware of
|
|
31
31
|
if (!groupId) {
|
|
32
32
|
throw new Error(`Could not find a group_id for conversation ${qualifiedConversationId.id}@${qualifiedConversationId.domain}`);
|
|
@@ -46,13 +46,13 @@ const createMockedMessage = () => {
|
|
|
46
46
|
describe('handleMLSMessageAdd', () => {
|
|
47
47
|
it('throws when received a message for a group that is not known by a client', async () => {
|
|
48
48
|
const event = createMLSMessageAddEventMock({ id: 'conversationId', domain: 'staging.zinfra.io' });
|
|
49
|
-
|
|
50
|
-
await expect((0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService })).rejects.toThrow();
|
|
49
|
+
const groupIdFromConversationId = () => Promise.resolve(undefined);
|
|
50
|
+
await expect((0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService, groupIdFromConversationId })).rejects.toThrow();
|
|
51
51
|
});
|
|
52
52
|
it('does not handle pending proposals if message does not contain proposals', async () => {
|
|
53
53
|
const event = createMLSMessageAddEventMock({ id: 'conversationId', domain: 'staging.zinfra.io' });
|
|
54
54
|
const mockGroupId = 'AAEAAH87aajaQ011i+rNLmwpy0sAZGl5YS53aXJlLmxpbms=';
|
|
55
|
-
|
|
55
|
+
const groupIdFromConversationId = () => Promise.resolve(mockGroupId);
|
|
56
56
|
const message = createMockedMessage();
|
|
57
57
|
jest.spyOn(mockedMLSService, 'decryptMessage').mockResolvedValueOnce({
|
|
58
58
|
proposals: [],
|
|
@@ -61,13 +61,13 @@ describe('handleMLSMessageAdd', () => {
|
|
|
61
61
|
hasEpochChanged: false,
|
|
62
62
|
isActive: true,
|
|
63
63
|
});
|
|
64
|
-
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService });
|
|
64
|
+
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService, groupIdFromConversationId });
|
|
65
65
|
expect(mockedMLSService.handlePendingProposals).not.toHaveBeenCalled();
|
|
66
66
|
});
|
|
67
67
|
it('handles pending proposals if message includes proposals', async () => {
|
|
68
68
|
const event = createMLSMessageAddEventMock({ id: 'conversationId', domain: 'staging.zinfra.io' });
|
|
69
69
|
const mockGroupId = 'AAEAAH87aajaQ011i+rNLmwpy0sAZGl5YS53aXJlLmxpbms=';
|
|
70
|
-
|
|
70
|
+
const groupIdFromConversationId = () => Promise.resolve(mockGroupId);
|
|
71
71
|
const message = createMockedMessage();
|
|
72
72
|
jest.spyOn(mockedMLSService, 'decryptMessage').mockResolvedValueOnce({
|
|
73
73
|
proposals: [{ proposal: new Uint8Array(), proposalRef: new Uint8Array() }],
|
|
@@ -76,7 +76,7 @@ describe('handleMLSMessageAdd', () => {
|
|
|
76
76
|
hasEpochChanged: false,
|
|
77
77
|
isActive: true,
|
|
78
78
|
});
|
|
79
|
-
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService });
|
|
79
|
+
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService, groupIdFromConversationId });
|
|
80
80
|
expect(mockedMLSService.handlePendingProposals).toHaveBeenCalledWith({
|
|
81
81
|
groupId: mockGroupId,
|
|
82
82
|
delayInMs: 2000,
|
|
@@ -86,7 +86,7 @@ describe('handleMLSMessageAdd', () => {
|
|
|
86
86
|
it('emits "newEpoch" event if incoming message has advanced epoch number', async () => {
|
|
87
87
|
const event = createMLSMessageAddEventMock({ id: 'conversationId', domain: 'staging.zinfra.io' });
|
|
88
88
|
const mockGroupId = 'AAEAAH87aajaQ011i+rNLmwpy0sAZGl5YS53aXJlLmxpbms=';
|
|
89
|
-
|
|
89
|
+
const groupIdFromConversationId = () => Promise.resolve(mockGroupId);
|
|
90
90
|
const message = createMockedMessage();
|
|
91
91
|
jest.spyOn(mockedMLSService, 'decryptMessage').mockResolvedValueOnce({
|
|
92
92
|
proposals: [],
|
|
@@ -96,7 +96,7 @@ describe('handleMLSMessageAdd', () => {
|
|
|
96
96
|
});
|
|
97
97
|
const mockedNewEpoch = 5;
|
|
98
98
|
jest.spyOn(mockedMLSService, 'getEpoch').mockResolvedValueOnce(mockedNewEpoch);
|
|
99
|
-
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService });
|
|
99
|
+
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService, groupIdFromConversationId });
|
|
100
100
|
expect(mockedMLSService.emit).toHaveBeenCalledWith('newEpoch', {
|
|
101
101
|
groupId: mockGroupId,
|
|
102
102
|
epoch: mockedNewEpoch,
|
|
@@ -11,7 +11,7 @@ import { KeyPackageClaimUser } from '../../../conversation';
|
|
|
11
11
|
import { CoreDatabase } from '../../../storage/CoreDB';
|
|
12
12
|
import { RecurringTaskScheduler } from '../../../util/RecurringTaskScheduler';
|
|
13
13
|
import { AcmeChallenge, E2EIServiceExternal, User } from '../E2EIdentityService';
|
|
14
|
-
import { ClientId, CommitPendingProposalsParams, HandlePendingProposalsParams
|
|
14
|
+
import { ClientId, CommitPendingProposalsParams, HandlePendingProposalsParams } from '../types';
|
|
15
15
|
export declare const optionalToUint8Array: (array: Uint8Array | []) => Uint8Array;
|
|
16
16
|
interface LocalMLSServiceConfig extends MLSServiceConfig {
|
|
17
17
|
/**
|
|
@@ -32,7 +32,6 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
32
32
|
private readonly recurringTaskScheduler;
|
|
33
33
|
logger: logdown.Logger;
|
|
34
34
|
config: LocalMLSServiceConfig;
|
|
35
|
-
groupIdFromConversationId?: MLSCallbacks['groupIdFromConversationId'];
|
|
36
35
|
private readonly textEncoder;
|
|
37
36
|
private readonly textDecoder;
|
|
38
37
|
constructor(apiClient: APIClient, coreCryptoClient: CoreCrypto, coreDatabase: CoreDatabase, recurringTaskScheduler: RecurringTaskScheduler, { keyingMaterialUpdateThreshold, nbKeyPackages, defaultCiphersuite, defaultCredentialType, }: Partial<MLSServiceConfig>);
|
|
@@ -46,7 +45,6 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
46
45
|
* @param invitee - the list of keys of clients to add to the MLS group
|
|
47
46
|
*/
|
|
48
47
|
addUsersToExistingConversation(groupId: string, invitee: Invitee[]): Promise<PostMlsMessageResponse>;
|
|
49
|
-
configureMLSCallbacks({ groupIdFromConversationId, ...coreCryptoCallbacks }: MLSCallbacks): void;
|
|
50
48
|
getKeyPackagesPayload(qualifiedUsers: KeyPackageClaimUser[]): Promise<{
|
|
51
49
|
coreCryptoKeyPackagesPayload: Invitee[];
|
|
52
50
|
failedToFetchKeyPackages: QualifiedId[];
|
|
@@ -163,13 +161,6 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
163
161
|
private uploadMLSPublicKeys;
|
|
164
162
|
private uploadMLSKeyPackages;
|
|
165
163
|
wipeConversation(groupId: string): Promise<void>;
|
|
166
|
-
/**
|
|
167
|
-
* If there is a matching conversationId => groupId pair in the database,
|
|
168
|
-
* we can find the groupId and return it as a string
|
|
169
|
-
*
|
|
170
|
-
* @param conversationQualifiedId
|
|
171
|
-
*/
|
|
172
|
-
getGroupIdFromConversationId(conversationQualifiedId: QualifiedId, subconversationId?: SUBCONVERSATION_ID): Promise<string | undefined>;
|
|
173
164
|
/**
|
|
174
165
|
* If there are pending proposals, we need to either process them,
|
|
175
166
|
* or save them in the database for later processing
|
|
@@ -205,7 +196,7 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
205
196
|
clientId: ClientId;
|
|
206
197
|
domain: string;
|
|
207
198
|
}[]>;
|
|
208
|
-
handleMLSMessageAddEvent(event: ConversationMLSMessageAddEvent): Promise<import("../../../notification").HandledEventPayload | null>;
|
|
199
|
+
handleMLSMessageAddEvent(event: ConversationMLSMessageAddEvent, groupIdFromConversationId: (conversationId: QualifiedId, subconversationId?: SUBCONVERSATION_ID) => Promise<string | undefined>): Promise<import("../../../notification").HandledEventPayload | null>;
|
|
209
200
|
handleMLSWelcomeMessageEvent(event: ConversationMLSWelcomeEvent, clientId: string): Promise<import("../../../notification").HandledEventPayload>;
|
|
210
201
|
deleteMLSKeyPackages(clientId: ClientId, keyPackagRefs: Uint8Array[]): Promise<void>;
|
|
211
202
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAqB,gBAAgB,EAAC,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAC,sBAAsB,EAAE,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AAChG,OAAO,EAAC,8BAA8B,EAAE,2BAA2B,EAAC,MAAM,+BAA+B,CAAC;AAE1G,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAEzD,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAW,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EACL,eAAe,EAIf,cAAc,EACd,UAAU,EAEV,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAC,gBAAgB,EAAsB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,7 +39,6 @@ const logdown_1 = __importDefault(require("logdown"));
|
|
|
39
39
|
const commons_1 = require("@wireapp/commons");
|
|
40
40
|
const core_crypto_1 = require("@wireapp/core-crypto");
|
|
41
41
|
const CoreCryptoMLSError_1 = require("./CoreCryptoMLSError");
|
|
42
|
-
const subconversationGroupIdStore_1 = require("./stores/subconversationGroupIdStore/subconversationGroupIdStore");
|
|
43
42
|
const messageSender_1 = require("../../../conversation/message/messageSender");
|
|
44
43
|
const fullyQualifiedClientIdUtils_1 = require("../../../util/fullyQualifiedClientIdUtils");
|
|
45
44
|
const numberToHex_1 = require("../../../util/numberToHex");
|
|
@@ -148,6 +147,12 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
148
147
|
async initClient(userId, client) {
|
|
149
148
|
const qualifiedClientId = (0, fullyQualifiedClientIdUtils_1.constructFullyQualifiedClientId)(userId.id, client.id, userId.domain);
|
|
150
149
|
await this.coreCryptoClient.mlsInit(this.textEncoder.encode(qualifiedClientId), [this.config.defaultCiphersuite], this.config.nbKeyPackages);
|
|
150
|
+
await this.coreCryptoClient.registerCallbacks({
|
|
151
|
+
// All authorization/membership rules are enforced on backend
|
|
152
|
+
clientIsExistingGroupUser: async () => true,
|
|
153
|
+
authorize: async () => true,
|
|
154
|
+
userAuthorize: async () => true,
|
|
155
|
+
});
|
|
151
156
|
// We need to make sure keypackages and public key are uploaded to the backend
|
|
152
157
|
await this.uploadMLSPublicKeys(client);
|
|
153
158
|
await this.verifyRemoteMLSKeyPackagesAmount(client.id);
|
|
@@ -166,14 +171,6 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
166
171
|
}
|
|
167
172
|
return this.processCommitAction(groupIdBytes, () => this.coreCryptoClient.addClientsToConversation(groupIdBytes, invitee));
|
|
168
173
|
}
|
|
169
|
-
configureMLSCallbacks(_a) {
|
|
170
|
-
var { groupIdFromConversationId } = _a, coreCryptoCallbacks = __rest(_a, ["groupIdFromConversationId"]);
|
|
171
|
-
void this.coreCryptoClient.registerCallbacks(Object.assign(Object.assign({}, coreCryptoCallbacks), { clientIsExistingGroupUser: (_groupId, _client, _otherClients) => {
|
|
172
|
-
// All authorization/membership rules are enforced on backend
|
|
173
|
-
return Promise.resolve(true);
|
|
174
|
-
} }));
|
|
175
|
-
this.groupIdFromConversationId = groupIdFromConversationId;
|
|
176
|
-
}
|
|
177
174
|
async getKeyPackagesPayload(qualifiedUsers) {
|
|
178
175
|
/**
|
|
179
176
|
* @note We need to fetch key packages for all the users
|
|
@@ -495,19 +492,6 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
495
492
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
496
493
|
return this.coreCryptoClient.wipeConversation(groupIdBytes);
|
|
497
494
|
}
|
|
498
|
-
/**
|
|
499
|
-
* If there is a matching conversationId => groupId pair in the database,
|
|
500
|
-
* we can find the groupId and return it as a string
|
|
501
|
-
*
|
|
502
|
-
* @param conversationQualifiedId
|
|
503
|
-
*/
|
|
504
|
-
async getGroupIdFromConversationId(conversationQualifiedId, subconversationId) {
|
|
505
|
-
var _a;
|
|
506
|
-
const groupId = subconversationId
|
|
507
|
-
? subconversationGroupIdStore_1.subconversationGroupIdStore.getGroupId(conversationQualifiedId, subconversationId)
|
|
508
|
-
: await ((_a = this.groupIdFromConversationId) === null || _a === void 0 ? void 0 : _a.call(this, conversationQualifiedId));
|
|
509
|
-
return groupId;
|
|
510
|
-
}
|
|
511
495
|
/**
|
|
512
496
|
* If there are pending proposals, we need to either process them,
|
|
513
497
|
* or save them in the database for later processing
|
|
@@ -592,8 +576,8 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
592
576
|
});
|
|
593
577
|
return clientIds;
|
|
594
578
|
}
|
|
595
|
-
async handleMLSMessageAddEvent(event) {
|
|
596
|
-
return (0, events_1.handleMLSMessageAdd)({ event, mlsService: this });
|
|
579
|
+
async handleMLSMessageAddEvent(event, groupIdFromConversationId) {
|
|
580
|
+
return (0, events_1.handleMLSMessageAdd)({ event, mlsService: this, groupIdFromConversationId });
|
|
597
581
|
}
|
|
598
582
|
async handleMLSWelcomeMessageEvent(event, clientId) {
|
|
599
583
|
// Every time we've received a welcome message, it means that our key package was consumed,
|
|
@@ -46,6 +46,7 @@ const createMLSService = async () => {
|
|
|
46
46
|
decryptMessage: jest.fn(),
|
|
47
47
|
conversationEpoch: jest.fn(),
|
|
48
48
|
commitPendingProposals: jest.fn(),
|
|
49
|
+
registerCallbacks: jest.fn(),
|
|
49
50
|
};
|
|
50
51
|
const mockedDb = await (0, CoreDB_1.openDB)('core-test-db');
|
|
51
52
|
const recurringTaskScheduler = new RecurringTaskScheduler_1.RecurringTaskScheduler({
|
|
@@ -196,7 +197,7 @@ describe('MLSService', () => {
|
|
|
196
197
|
const [mlsService, { coreCrypto: mockCoreCrypto }] = await createMLSService();
|
|
197
198
|
const mockGroupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
198
199
|
const mockedNewEpoch = 3;
|
|
199
|
-
|
|
200
|
+
const getGroupIdFromConversationId = () => Promise.resolve(mockGroupId);
|
|
200
201
|
const mockedDecryptoedMessage = {
|
|
201
202
|
hasEpochChanged: true,
|
|
202
203
|
isActive: false,
|
|
@@ -213,7 +214,7 @@ describe('MLSService', () => {
|
|
|
213
214
|
from: '',
|
|
214
215
|
time: '',
|
|
215
216
|
};
|
|
216
|
-
await mlsService.handleMLSMessageAddEvent(mockedMLSWelcomeEvent);
|
|
217
|
+
await mlsService.handleMLSMessageAddEvent(mockedMLSWelcomeEvent, getGroupIdFromConversationId);
|
|
217
218
|
expect(mockCoreCrypto.decryptMessage).toHaveBeenCalled();
|
|
218
219
|
expect(mlsService.emit).toHaveBeenCalledWith('newEpoch', { epoch: mockedNewEpoch, groupId: mockGroupId });
|
|
219
220
|
});
|
|
@@ -223,7 +224,7 @@ describe('MLSService', () => {
|
|
|
223
224
|
const mockGroupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
224
225
|
const mockedNewEpoch = 3;
|
|
225
226
|
const commitDelay = 1000;
|
|
226
|
-
|
|
227
|
+
const getGroupIdFromConversationId = () => Promise.resolve(mockGroupId);
|
|
227
228
|
const mockedDecryptoedMessage = {
|
|
228
229
|
hasEpochChanged: true,
|
|
229
230
|
isActive: false,
|
|
@@ -241,7 +242,7 @@ describe('MLSService', () => {
|
|
|
241
242
|
from: '',
|
|
242
243
|
time: new Date().toISOString(),
|
|
243
244
|
};
|
|
244
|
-
await mlsService.handleMLSMessageAddEvent(mockedMLSWelcomeEvent);
|
|
245
|
+
await mlsService.handleMLSMessageAddEvent(mockedMLSWelcomeEvent, getGroupIdFromConversationId);
|
|
245
246
|
expect(mockCoreCrypto.commitPendingProposals).not.toHaveBeenCalled();
|
|
246
247
|
jest.advanceTimersByTime(commitDelay);
|
|
247
248
|
expect(mockCoreCrypto.decryptMessage).toHaveBeenCalled();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
2
|
-
import { CoreCryptoCallbacks } from '@wireapp/core-crypto';
|
|
3
2
|
import { MLSServiceConfig } from './MLSService/MLSService.types';
|
|
4
3
|
export type ClientId = string;
|
|
5
4
|
export type SecretCrypto = {
|
|
@@ -11,12 +10,12 @@ export type SecretCrypto = {
|
|
|
11
10
|
decrypt: (payload: Uint8Array) => Promise<string>;
|
|
12
11
|
version: 1;
|
|
13
12
|
};
|
|
14
|
-
export interface
|
|
13
|
+
export interface CoreCallbacks {
|
|
15
14
|
/**
|
|
16
15
|
* Should return a groupId corresponding to the conversation ID given
|
|
17
16
|
* Used for the core to know what core-crypto conversation we are dealing with when receiving events
|
|
18
17
|
* @param conversationId
|
|
19
|
-
* @returns the
|
|
18
|
+
* @returns the groupId corresponding to the conversation ID
|
|
20
19
|
*/
|
|
21
20
|
groupIdFromConversationId: (conversationId: QualifiedId) => Promise<string | undefined>;
|
|
22
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/messagingProtocols/mls/types.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAEzD,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/messagingProtocols/mls/types.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAEzD,OAAO,EAAC,gBAAgB,EAAC,MAAM,+BAA+B,CAAC;AAE/D,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,MAAM,MAAM,YAAY,GACpB;IACE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACpD,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACtD,OAAO,EAAE,SAAS,CAAC;CACpB,GACD;IACE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAChD,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,OAAO,EAAE,CAAC,CAAC;CACZ,CAAC;AAEN,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,yBAAyB,EAAE,CAAC,cAAc,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACzF;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,SAAS,CAAC;AAEd,MAAM,MAAM,4BAA4B,GAAG;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,SAAS,CAAC;AAEd,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAE5B,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAE9B,uEAAuE;IACvE,GAAG,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAEhC,oKAAoK;IACpK,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
|