@wireapp/core 41.7.0 → 41.7.2
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/conversation/ConversationService/ConversationService.d.ts +13 -3
- package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
- package/lib/conversation/ConversationService/ConversationService.js +43 -13
- package/lib/conversation/ConversationService/ConversationService.test.js +85 -19
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +10 -0
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.js +15 -2
- package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +25 -0
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Conversation, DefaultConversationRoleName, MutedStatus, NewConversation, QualifiedUserClients, RemoteConversations, PostMlsMessageResponse } from '@wireapp/api-client/lib/conversation';
|
|
1
|
+
import { Conversation, DefaultConversationRoleName, MutedStatus, NewConversation, QualifiedUserClients, RemoteConversations, PostMlsMessageResponse, MLSConversation } from '@wireapp/api-client/lib/conversation';
|
|
2
2
|
import { BackendEvent, ConversationMemberLeaveEvent } from '@wireapp/api-client/lib/event';
|
|
3
3
|
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
4
4
|
import { XOR } from '@wireapp/commons/lib/util/TypeUtil';
|
|
@@ -91,7 +91,17 @@ export declare class ConversationService extends TypedEventEmitter<Events> {
|
|
|
91
91
|
* @param epoch The current epoch of the local conversation
|
|
92
92
|
*/
|
|
93
93
|
sendExternalJoinProposal(groupId: string, epoch: number): Promise<void>;
|
|
94
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Will check if mls group exists locally.
|
|
96
|
+
* @param groupId groupId of the conversation
|
|
97
|
+
*/
|
|
98
|
+
mlsGroupExistsLocally(groupId: string): Promise<boolean>;
|
|
99
|
+
/**
|
|
100
|
+
* Will check if mls group is established locally.
|
|
101
|
+
* Group is established after the first commit was sent in the group and epoch number is at least 1.
|
|
102
|
+
* @param groupId groupId of the conversation
|
|
103
|
+
*/
|
|
104
|
+
isMLSGroupEstablishedLocally(groupId: string): Promise<boolean>;
|
|
95
105
|
wipeMLSConversation(groupId: string): Promise<void>;
|
|
96
106
|
private matchesEpoch;
|
|
97
107
|
handleConversationsEpochMismatch(): Promise<void>;
|
|
@@ -113,7 +123,7 @@ export declare class ConversationService extends TypedEventEmitter<Events> {
|
|
|
113
123
|
readonly establishMLS1to1Conversation: (groupId: string, selfUser: {
|
|
114
124
|
user: QualifiedId;
|
|
115
125
|
client: string;
|
|
116
|
-
}, otherUserId: QualifiedId) => Promise<
|
|
126
|
+
}, otherUserId: QualifiedId, shouldRetry?: boolean) => Promise<MLSConversation>;
|
|
117
127
|
private handleMLSMessageAddEvent;
|
|
118
128
|
private handleMLSWelcomeMessageEvent;
|
|
119
129
|
private handleOtrMessageAddEvent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationService.d.ts","sourceRoot":"","sources":["../../../src/conversation/ConversationService/ConversationService.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,YAAY,EACZ,2BAA2B,EAC3B,WAAW,EACX,eAAe,EACf,oBAAoB,EAEpB,mBAAmB,EACnB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"ConversationService.d.ts","sourceRoot":"","sources":["../../../src/conversation/ConversationService/ConversationService.ts"],"names":[],"mappings":"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"}
|
|
@@ -54,23 +54,41 @@ class ConversationService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
54
54
|
* @param selfUser - user and client ids of the self user
|
|
55
55
|
* @param otherUserId - id of the other user
|
|
56
56
|
*/
|
|
57
|
-
this.establishMLS1to1Conversation = async (groupId, selfUser, otherUserId) => {
|
|
57
|
+
this.establishMLS1to1Conversation = async (groupId, selfUser, otherUserId, shouldRetry = true) => {
|
|
58
|
+
this.logger.info(`Trying to establish a MLS 1:1 conversation with user ${otherUserId.id}...`);
|
|
59
|
+
// Before trying to register a group, check if the group is already established o backend.
|
|
60
|
+
// If remote epoch is higher than 0, it means that the group was already established.
|
|
61
|
+
// It's possible that we've already received a welcome message.
|
|
62
|
+
const mlsConversation = await this.apiClient.api.conversation.getMLS1to1Conversation(otherUserId);
|
|
63
|
+
if (mlsConversation.epoch > 0) {
|
|
64
|
+
this.logger.info(`Conversation (id ${mlsConversation.qualified_id.id}) is already established on backend, checking the local epoch...`);
|
|
65
|
+
const isMLSGroupEstablishedLocally = await this.isMLSGroupEstablishedLocally(groupId);
|
|
66
|
+
// If group is already established locally, there's nothing more to do
|
|
67
|
+
if (isMLSGroupEstablishedLocally) {
|
|
68
|
+
this.logger.info(`Conversation (id ${mlsConversation.qualified_id.id}) is already established locally.`);
|
|
69
|
+
return mlsConversation;
|
|
70
|
+
}
|
|
71
|
+
// If local epoch is 0 it means that we've not received a welcome message
|
|
72
|
+
// We try joining via external commit.
|
|
73
|
+
this.logger.info(`Conversation (id ${mlsConversation.qualified_id.id}) is not yet established locally, joining via external commit...`);
|
|
74
|
+
await this.joinByExternalCommit(mlsConversation.qualified_id);
|
|
75
|
+
return this.apiClient.api.conversation.getMLS1to1Conversation(otherUserId);
|
|
76
|
+
}
|
|
77
|
+
// If group is not established on backend,
|
|
78
|
+
// we wipe the it locally (in case it exsits in the local store) and try to register it.
|
|
79
|
+
await this.mlsService.wipeConversation(groupId);
|
|
58
80
|
try {
|
|
59
81
|
await this.mlsService.registerConversation(groupId, [otherUserId, selfUser.user], selfUser);
|
|
82
|
+
this.logger.info(`Conversation (id ${mlsConversation.qualified_id.id}) established successfully.`);
|
|
83
|
+
return this.apiClient.api.conversation.getMLS1to1Conversation(otherUserId);
|
|
60
84
|
}
|
|
61
85
|
catch (error) {
|
|
62
|
-
this.logger.info(`Could not register MLS group with id ${groupId}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
this.logger.info(`Conversation (id ${mlsConversation.qualified_id.id}) is already established, joining via external commit`);
|
|
66
|
-
// If its already established, we join with external commit
|
|
67
|
-
await this.joinByExternalCommit(mlsConversation.qualified_id);
|
|
68
|
-
return;
|
|
86
|
+
this.logger.info(`Could not register MLS group with id ${groupId}: `, error);
|
|
87
|
+
if (!shouldRetry) {
|
|
88
|
+
throw error;
|
|
69
89
|
}
|
|
70
90
|
this.logger.info(`Conversation (id ${mlsConversation.qualified_id.id}) is not established, retrying to establish it`);
|
|
71
|
-
|
|
72
|
-
await this.wipeMLSConversation(groupId);
|
|
73
|
-
return this.establishMLS1to1Conversation(groupId, selfUser, otherUserId);
|
|
91
|
+
return this.establishMLS1to1Conversation(groupId, selfUser, otherUserId, false);
|
|
74
92
|
}
|
|
75
93
|
};
|
|
76
94
|
this.messageTimer = new conversation_2.MessageTimer();
|
|
@@ -310,9 +328,21 @@ class ConversationService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
310
328
|
this.mlsService.resetKeyMaterialRenewal(groupId);
|
|
311
329
|
});
|
|
312
330
|
}
|
|
313
|
-
|
|
331
|
+
/**
|
|
332
|
+
* Will check if mls group exists locally.
|
|
333
|
+
* @param groupId groupId of the conversation
|
|
334
|
+
*/
|
|
335
|
+
async mlsGroupExistsLocally(groupId) {
|
|
314
336
|
return this.mlsService.conversationExists(groupId);
|
|
315
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* Will check if mls group is established locally.
|
|
340
|
+
* Group is established after the first commit was sent in the group and epoch number is at least 1.
|
|
341
|
+
* @param groupId groupId of the conversation
|
|
342
|
+
*/
|
|
343
|
+
async isMLSGroupEstablishedLocally(groupId) {
|
|
344
|
+
return this.mlsService.isConversationEstablished(groupId);
|
|
345
|
+
}
|
|
316
346
|
async wipeMLSConversation(groupId) {
|
|
317
347
|
return this.mlsService.wipeConversation(groupId);
|
|
318
348
|
}
|
|
@@ -340,7 +370,7 @@ class ConversationService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
340
370
|
async handleConversationEpochMismatch(remoteMlsConversation, onSuccessfulRejoin) {
|
|
341
371
|
const { qualified_id: qualifiedId, group_id: groupId, epoch } = remoteMlsConversation;
|
|
342
372
|
try {
|
|
343
|
-
const isEstablished = await this.
|
|
373
|
+
const isEstablished = await this.mlsGroupExistsLocally(groupId);
|
|
344
374
|
const doesEpochMatch = isEstablished && (await this.matchesEpoch(groupId, epoch));
|
|
345
375
|
//if conversation is not established or epoch does not match -> try to rejoin
|
|
346
376
|
if (!isEstablished || !doesEpochMatch) {
|
|
@@ -102,6 +102,7 @@ describe('ConversationService', () => {
|
|
|
102
102
|
wipeConversation: jest.fn(),
|
|
103
103
|
handleMLSMessageAddEvent: jest.fn(),
|
|
104
104
|
conversationExists: jest.fn(),
|
|
105
|
+
isConversationEstablished: jest.fn(),
|
|
105
106
|
};
|
|
106
107
|
const conversationService = new __1.ConversationService(client, mockedProteusService, mockedMLSService);
|
|
107
108
|
jest.spyOn(conversationService, 'joinByExternalCommit');
|
|
@@ -175,7 +176,7 @@ describe('ConversationService', () => {
|
|
|
175
176
|
const mlsConversation2 = createConversation(remoteEpoch, 'conversation2');
|
|
176
177
|
const mockedDBResponse = [mlsConversation1, mlsConversation2];
|
|
177
178
|
jest.spyOn(apiClient.api.conversation, 'getConversationList').mockResolvedValueOnce({ found: mockedDBResponse });
|
|
178
|
-
jest.spyOn(conversationService, '
|
|
179
|
+
jest.spyOn(conversationService, 'mlsGroupExistsLocally').mockResolvedValue(false);
|
|
179
180
|
await conversationService.handleConversationsEpochMismatch();
|
|
180
181
|
expect(conversationService.joinByExternalCommit).toHaveBeenCalledWith(mlsConversation1.qualified_id);
|
|
181
182
|
expect(conversationService.joinByExternalCommit).toHaveBeenCalledWith(mlsConversation2.qualified_id);
|
|
@@ -186,7 +187,7 @@ describe('ConversationService', () => {
|
|
|
186
187
|
const mlsConversation2 = createConversation(1, 'conversation2');
|
|
187
188
|
const mockedDBResponse = [mlsConversation1, mlsConversation2];
|
|
188
189
|
jest.spyOn(apiClient.api.conversation, 'getConversationList').mockResolvedValueOnce({ found: mockedDBResponse });
|
|
189
|
-
jest.spyOn(conversationService, '
|
|
190
|
+
jest.spyOn(conversationService, 'mlsGroupExistsLocally').mockResolvedValue(true);
|
|
190
191
|
jest.spyOn(mlsService, 'getEpoch').mockResolvedValue(2);
|
|
191
192
|
await conversationService.handleConversationsEpochMismatch();
|
|
192
193
|
expect(conversationService.joinByExternalCommit).toHaveBeenCalledWith(mlsConversation1.qualified_id);
|
|
@@ -197,7 +198,7 @@ describe('ConversationService', () => {
|
|
|
197
198
|
const mlsConversation = createConversation(1);
|
|
198
199
|
const mockedDBResponse = [mlsConversation];
|
|
199
200
|
jest.spyOn(apiClient.api.conversation, 'getConversationList').mockResolvedValueOnce({ found: mockedDBResponse });
|
|
200
|
-
jest.spyOn(conversationService, '
|
|
201
|
+
jest.spyOn(conversationService, 'mlsGroupExistsLocally').mockResolvedValueOnce(true);
|
|
201
202
|
jest.spyOn(mlsService, 'getEpoch').mockResolvedValueOnce(1);
|
|
202
203
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
|
|
203
204
|
await conversationService.handleConversationsEpochMismatch();
|
|
@@ -205,52 +206,117 @@ describe('ConversationService', () => {
|
|
|
205
206
|
});
|
|
206
207
|
});
|
|
207
208
|
describe('establishMLS1to1Conversation', () => {
|
|
208
|
-
it('
|
|
209
|
-
const [conversationService, { mlsService }] = buildConversationService();
|
|
209
|
+
it('only returns a conversation if a group is already established on backend and locally', async () => {
|
|
210
|
+
const [conversationService, { apiClient, mlsService }] = buildConversationService();
|
|
211
|
+
const mockConversationId = { id: 'mock-conversation-id', domain: 'staging.zinfra.io' };
|
|
210
212
|
const mockGroupId = 'mock-group-id';
|
|
211
213
|
const selfUser = { user: { id: 'self-user-id', domain: 'staging.zinfra.io' }, client: 'self-user-client-id' };
|
|
212
214
|
const otherUserId = { id: 'other-user-id', domain: 'staging.zinfra.io' };
|
|
215
|
+
const remoteEpoch = 1;
|
|
216
|
+
jest.spyOn(apiClient.api.conversation, 'getMLS1to1Conversation').mockResolvedValueOnce({
|
|
217
|
+
qualified_id: mockConversationId,
|
|
218
|
+
protocol: conversation_1.ConversationProtocol.MLS,
|
|
219
|
+
epoch: remoteEpoch,
|
|
220
|
+
group_id: mockGroupId,
|
|
221
|
+
});
|
|
222
|
+
jest.spyOn(mlsService, 'isConversationEstablished').mockResolvedValueOnce(true);
|
|
213
223
|
await conversationService.establishMLS1to1Conversation(mockGroupId, selfUser, otherUserId);
|
|
214
|
-
expect(mlsService.registerConversation).
|
|
215
|
-
expect(
|
|
216
|
-
expect(mlsService.joinByExternalCommit).not.toHaveBeenCalled();
|
|
217
|
-
expect(mlsService.wipeConversation).not.toHaveBeenCalled();
|
|
224
|
+
expect(mlsService.registerConversation).not.toHaveBeenCalled();
|
|
225
|
+
expect(conversationService.joinByExternalCommit).not.toHaveBeenCalled();
|
|
218
226
|
});
|
|
219
|
-
it('joins with external commit if
|
|
227
|
+
it('joins with an external commit if a group is already established on backend but not established locally', async () => {
|
|
220
228
|
const [conversationService, { apiClient, mlsService }] = buildConversationService();
|
|
221
229
|
const mockConversationId = { id: 'mock-conversation-id', domain: 'staging.zinfra.io' };
|
|
222
230
|
const mockGroupId = 'mock-group-id';
|
|
223
231
|
const selfUser = { user: { id: 'self-user-id', domain: 'staging.zinfra.io' }, client: 'self-user-client-id' };
|
|
224
232
|
const otherUserId = { id: 'other-user-id', domain: 'staging.zinfra.io' };
|
|
225
|
-
|
|
233
|
+
const remoteEpoch = 1;
|
|
234
|
+
const updatedEpoch = 2;
|
|
235
|
+
jest.spyOn(apiClient.api.conversation, 'getMLS1to1Conversation').mockResolvedValueOnce({
|
|
236
|
+
qualified_id: mockConversationId,
|
|
237
|
+
protocol: conversation_1.ConversationProtocol.MLS,
|
|
238
|
+
epoch: remoteEpoch,
|
|
239
|
+
group_id: mockGroupId,
|
|
240
|
+
});
|
|
241
|
+
// The 2nd request we make after joining the conversation with external commit
|
|
226
242
|
jest.spyOn(apiClient.api.conversation, 'getMLS1to1Conversation').mockResolvedValueOnce({
|
|
227
243
|
qualified_id: mockConversationId,
|
|
228
244
|
protocol: conversation_1.ConversationProtocol.MLS,
|
|
229
|
-
epoch:
|
|
245
|
+
epoch: updatedEpoch,
|
|
230
246
|
group_id: mockGroupId,
|
|
231
247
|
});
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
248
|
+
jest.spyOn(mlsService, 'isConversationEstablished').mockResolvedValueOnce(false);
|
|
249
|
+
jest.spyOn(mlsService, 'joinByExternalCommit').mockResolvedValueOnce({ events: [], time: '' });
|
|
250
|
+
const establishedConversation = await conversationService.establishMLS1to1Conversation(mockGroupId, selfUser, otherUserId);
|
|
251
|
+
expect(mlsService.registerConversation).not.toHaveBeenCalled();
|
|
235
252
|
expect(conversationService.joinByExternalCommit).toHaveBeenCalledWith(mockConversationId);
|
|
253
|
+
expect(establishedConversation.epoch).toEqual(updatedEpoch);
|
|
236
254
|
});
|
|
237
|
-
it('
|
|
255
|
+
it('wipes the conversation and registers it if a group is not yet established on backend', async () => {
|
|
238
256
|
const [conversationService, { apiClient, mlsService }] = buildConversationService();
|
|
239
257
|
const mockConversationId = { id: 'mock-conversation-id', domain: 'staging.zinfra.io' };
|
|
240
258
|
const mockGroupId = 'mock-group-id';
|
|
241
259
|
const selfUser = { user: { id: 'self-user-id', domain: 'staging.zinfra.io' }, client: 'self-user-client-id' };
|
|
242
260
|
const otherUserId = { id: 'other-user-id', domain: 'staging.zinfra.io' };
|
|
243
|
-
|
|
261
|
+
const remoteEpoch = 0;
|
|
262
|
+
const updatedEpoch = 1;
|
|
244
263
|
jest.spyOn(apiClient.api.conversation, 'getMLS1to1Conversation').mockResolvedValueOnce({
|
|
245
264
|
qualified_id: mockConversationId,
|
|
246
265
|
protocol: conversation_1.ConversationProtocol.MLS,
|
|
247
|
-
epoch:
|
|
266
|
+
epoch: remoteEpoch,
|
|
248
267
|
group_id: mockGroupId,
|
|
249
268
|
});
|
|
250
|
-
|
|
269
|
+
// The 2nd request we make after successfully registering a group
|
|
270
|
+
jest.spyOn(apiClient.api.conversation, 'getMLS1to1Conversation').mockResolvedValueOnce({
|
|
271
|
+
qualified_id: mockConversationId,
|
|
272
|
+
protocol: conversation_1.ConversationProtocol.MLS,
|
|
273
|
+
epoch: updatedEpoch,
|
|
274
|
+
group_id: mockGroupId,
|
|
275
|
+
});
|
|
276
|
+
jest.spyOn(mlsService, 'wipeConversation');
|
|
277
|
+
const establishedConversation = await conversationService.establishMLS1to1Conversation(mockGroupId, selfUser, otherUserId);
|
|
278
|
+
expect(mlsService.wipeConversation).toHaveBeenCalledWith(mockGroupId);
|
|
279
|
+
expect(mlsService.registerConversation).toHaveBeenCalledTimes(1);
|
|
251
280
|
expect(mlsService.registerConversation).toHaveBeenCalledWith(mockGroupId, [otherUserId, selfUser.user], selfUser);
|
|
281
|
+
expect(conversationService.joinByExternalCommit).not.toHaveBeenCalled();
|
|
282
|
+
expect(establishedConversation.epoch).toEqual(updatedEpoch);
|
|
283
|
+
});
|
|
284
|
+
it('retries to register the conversation after it has failed for the first time', async () => {
|
|
285
|
+
const [conversationService, { apiClient, mlsService }] = buildConversationService();
|
|
286
|
+
const mockConversationId = { id: 'mock-conversation-id', domain: 'staging.zinfra.io' };
|
|
287
|
+
const mockGroupId = 'mock-group-id';
|
|
288
|
+
const selfUser = { user: { id: 'self-user-id', domain: 'staging.zinfra.io' }, client: 'self-user-client-id' };
|
|
289
|
+
const otherUserId = { id: 'other-user-id', domain: 'staging.zinfra.io' };
|
|
290
|
+
const remoteEpoch = 0;
|
|
291
|
+
const updatedEpoch = 1;
|
|
292
|
+
jest.spyOn(apiClient.api.conversation, 'getMLS1to1Conversation').mockResolvedValueOnce({
|
|
293
|
+
qualified_id: mockConversationId,
|
|
294
|
+
protocol: conversation_1.ConversationProtocol.MLS,
|
|
295
|
+
epoch: remoteEpoch,
|
|
296
|
+
group_id: mockGroupId,
|
|
297
|
+
});
|
|
298
|
+
// The 2nd request we make when retrying to register the conversation
|
|
299
|
+
jest.spyOn(apiClient.api.conversation, 'getMLS1to1Conversation').mockResolvedValueOnce({
|
|
300
|
+
qualified_id: mockConversationId,
|
|
301
|
+
protocol: conversation_1.ConversationProtocol.MLS,
|
|
302
|
+
epoch: remoteEpoch,
|
|
303
|
+
group_id: mockGroupId,
|
|
304
|
+
});
|
|
305
|
+
// The 3rd request we make after successfully registering a group
|
|
306
|
+
jest.spyOn(apiClient.api.conversation, 'getMLS1to1Conversation').mockResolvedValueOnce({
|
|
307
|
+
qualified_id: mockConversationId,
|
|
308
|
+
protocol: conversation_1.ConversationProtocol.MLS,
|
|
309
|
+
epoch: updatedEpoch,
|
|
310
|
+
group_id: mockGroupId,
|
|
311
|
+
});
|
|
312
|
+
jest.spyOn(mlsService, 'registerConversation').mockRejectedValueOnce(undefined);
|
|
313
|
+
jest.spyOn(mlsService, 'wipeConversation');
|
|
314
|
+
const establishedConversation = await conversationService.establishMLS1to1Conversation(mockGroupId, selfUser, otherUserId);
|
|
252
315
|
expect(mlsService.wipeConversation).toHaveBeenCalledWith(mockGroupId);
|
|
253
316
|
expect(mlsService.registerConversation).toHaveBeenCalledTimes(2);
|
|
317
|
+
expect(mlsService.registerConversation).toHaveBeenCalledWith(mockGroupId, [otherUserId, selfUser.user], selfUser);
|
|
318
|
+
expect(conversationService.joinByExternalCommit).not.toHaveBeenCalled();
|
|
319
|
+
expect(establishedConversation.epoch).toEqual(updatedEpoch);
|
|
254
320
|
});
|
|
255
321
|
});
|
|
256
322
|
describe('handleEvent', () => {
|
|
@@ -107,7 +107,17 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
107
107
|
*/
|
|
108
108
|
removeClientsFromConversation(groupId: string, clientIds: string[]): Promise<PostMlsMessageResponse>;
|
|
109
109
|
private commitProposals;
|
|
110
|
+
/**
|
|
111
|
+
* Will check if mls group exists in corecrypto.
|
|
112
|
+
* @param groupId groupId of the conversation
|
|
113
|
+
*/
|
|
110
114
|
conversationExists(groupId: string): Promise<boolean>;
|
|
115
|
+
/**
|
|
116
|
+
* Will check if mls group is established in coreCrypto.
|
|
117
|
+
* Group is established after the first commit was sent in the group and epoch number is at least 1.
|
|
118
|
+
* @param groupId groupId of the conversation
|
|
119
|
+
*/
|
|
120
|
+
isConversationEstablished(groupId: string): Promise<boolean>;
|
|
111
121
|
clientValidKeypackagesCount(): Promise<number>;
|
|
112
122
|
clientKeypackages(amountRequested: number): Promise<Uint8Array[]>;
|
|
113
123
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAC,sBAAsB,EAAE,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AAChG,OAAO,EAAC,eAAe,EAAC,MAAM,sDAAsD,CAAC;AACrF,OAAO,EAAC,8BAA8B,EAAE,2BAA2B,EAAC,MAAM,+BAA+B,CAAC;AAE1G,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAGzD,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAE9C,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;AAE9B,OAAO,EAAC,gBAAgB,EAAsB,MAAM,oBAAoB,CAAC;AAIzE,OAAO,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAM1D,OAAO,EAAC,iBAAiB,EAAC,MAAM,iCAAiC,CAAC;AAElE,OAAO,EAAC,4BAA4B,EAAE,4BAA4B,EAAE,YAAY,EAAC,MAAM,UAAU,CAAC;AAIlG,eAAO,MAAM,oBAAoB,UAAW,UAAU,GAAG,EAAE,KAAG,UAE7D,CAAC;AASF,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,KAAK,MAAM,GAAG;IACZ,QAAQ,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;CAC5C,CAAC;AACF,qBAAa,UAAW,SAAQ,iBAAiB,CAAC,MAAM,CAAC;IAQrD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IARnC,MAAM,iBAAuC;IAC7C,MAAM,EAAE,gBAAgB,CAAC;IACzB,yBAAyB,CAAC,EAAE,YAAY,CAAC,2BAA2B,CAAC,CAAC;IACtE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;gBAG9B,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,UAAU,EAC7C,EACE,6BAA2E,EAC3E,aAA2C,EAC3C,kBAAqD,EACrD,qBAA2D,GAC5D,EAAE,OAAO,CAAC,gBAAgB,CAAC;IAWjB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM;IAKhD,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM;YAajD,kBAAkB;IAuChC;;;;;;OAMG;IACI,8BAA8B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE;IAWlE,qBAAqB,CAAC,EAAC,yBAAyB,EAAE,GAAG,mBAAmB,EAAC,EAAE,YAAY,GAAG,IAAI;IAWxF,qBAAqB,CAAC,cAAc,EAAE,mBAAmB,EAAE;;;;IA8CjE,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU;IAK/B,WAAW,CAAC,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe,GAAG,kBAAkB;IAIjG,oBAAoB,CAAC,YAAY,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC;IAwB5D,4BAA4B,CAAC,cAAc,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC;YAIlF,+BAA+B;IAO7C;;;;OAIG;IACU,8BAA8B,CAAC,cAAc,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA4B1E,oCAAoC,IAAI,OAAO,CAAC,IAAI,CAAC;IAUlE;;;;;OAKG;IACU,6BAA6B,CAAC,cAAc,EAAE,WAAW,GAAG,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC;IAkCrG,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMpE,mBAAmB,CAAC,oBAAoB,EAAE,oBAAoB,EAAE,IAAI,EAAE,uBAAuB;IAI7F,qBAAqB,CAAC,cAAc,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC;IAI1E,cAAc,CAAC,cAAc,EAAE,cAAc,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAI9F,cAAc,CAAC,cAAc,EAAE,cAAc,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAIrG;;;;;;;;;OASG;YACW,mBAAmB;IAQjC,OAAO,CAAC,oBAAoB;IAK5B;;;OAGG;IACU,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAatE;;;;;OAKG;IACU,oBAAoB,CAC/B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,WAAW,EAAE,EACpB,OAAO,CAAC,EAAE;QAAC,IAAI,EAAE,WAAW,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,GAC7C,OAAO,CAAC,sBAAsB,CAAC;IAiClC;;;;OAIG;IACI,6BAA6B,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE;YAW3D,eAAe;IAK7B;;;OAGG;IACU,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlE;;;;OAIG;IACU,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK5D,2BAA2B,IAAI,OAAO,CAAC,MAAM,CAAC;IAO9C,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAQ9E;;;;OAIG;IACU,gBAAgB,CAAC,OAAO,EAAE,MAAM;IAc7C,OAAO,CAAC,sCAAsC;IAI9C;;;OAGG;IACI,uBAAuB,CAAC,OAAO,EAAE,MAAM;IAK9C;;;OAGG;IACI,wBAAwB,CAAC,OAAO,EAAE,MAAM;IAI/C;;;OAGG;IACI,0BAA0B,CAAC,OAAO,EAAE,MAAM;IAUjD;;;OAGG;IACI,mCAAmC,CAAC,QAAQ,EAAE,MAAM,EAAE;IAQ7D;;;OAGG;IACI,8BAA8B;YAQvB,eAAe;IAsB7B;;;;;OAKG;YACW,mBAAmB;YAMnB,oBAAoB;IAOrB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7D;;;;;OAKG;IACU,4BAA4B,CACvC,uBAAuB,EAAE,WAAW,EACpC,iBAAiB,CAAC,EAAE,kBAAkB,GACrC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAQ9B;;;;;;;OAOG;IACU,sBAAsB,CAAC,EAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAC,EAAE,4BAA4B;IAoBjG;;;;;OAKG;IACU,sBAAsB,CAAC,EAAC,OAAO,EAAE,UAAkB,EAAC,EAAE,4BAA4B;IAa/F;;;;OAIG;IACU,6BAA6B;IAiB1C;;;;OAIG;IACU,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAY5F,wBAAwB,CAAC,KAAK,EAAE,8BAA8B;IAI9D,4BAA4B,CAAC,KAAK,EAAE,2BAA2B;CAG7E"}
|
|
@@ -372,10 +372,23 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
372
372
|
const commitBundle = await this.coreCryptoClient.commitPendingProposals(groupId);
|
|
373
373
|
return commitBundle ? void (await this.uploadCommitBundle(groupId, commitBundle)) : undefined;
|
|
374
374
|
}
|
|
375
|
+
/**
|
|
376
|
+
* Will check if mls group exists in corecrypto.
|
|
377
|
+
* @param groupId groupId of the conversation
|
|
378
|
+
*/
|
|
375
379
|
async conversationExists(groupId) {
|
|
376
380
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
377
381
|
return this.coreCryptoClient.conversationExists(groupIdBytes);
|
|
378
382
|
}
|
|
383
|
+
/**
|
|
384
|
+
* Will check if mls group is established in coreCrypto.
|
|
385
|
+
* Group is established after the first commit was sent in the group and epoch number is at least 1.
|
|
386
|
+
* @param groupId groupId of the conversation
|
|
387
|
+
*/
|
|
388
|
+
async isConversationEstablished(groupId) {
|
|
389
|
+
const doesConversationExist = await this.conversationExists(groupId);
|
|
390
|
+
return doesConversationExist && (await this.getEpoch(groupId)) > 0;
|
|
391
|
+
}
|
|
379
392
|
async clientValidKeypackagesCount() {
|
|
380
393
|
return this.coreCryptoClient.clientValidKeypackagesCount(this.config.defaultCiphersuite, this.config.defaultCredentialType);
|
|
381
394
|
}
|
|
@@ -481,8 +494,8 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
481
494
|
return this.apiClient.api.client.uploadMLSKeyPackages(clientId, keypackages.map(keypackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keypackage))));
|
|
482
495
|
}
|
|
483
496
|
async wipeConversation(groupId) {
|
|
484
|
-
const
|
|
485
|
-
if (!
|
|
497
|
+
const doesConversationExist = await this.conversationExists(groupId);
|
|
498
|
+
if (!doesConversationExist) {
|
|
486
499
|
//if the mls group does not exist, we don't need to wipe it
|
|
487
500
|
return;
|
|
488
501
|
}
|
|
@@ -71,4 +71,29 @@ describe('MLSService', () => {
|
|
|
71
71
|
expect(mlsService.cancelKeyMaterialRenewal).toHaveBeenCalledWith(groupId);
|
|
72
72
|
});
|
|
73
73
|
});
|
|
74
|
+
describe('isConversationEstablished', () => {
|
|
75
|
+
it('returns false if conversation does not exist locally', async () => {
|
|
76
|
+
const mlsService = new MLSService_1.MLSService(apiClient, mockCoreCrypto, {});
|
|
77
|
+
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
78
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
|
|
79
|
+
const isEstablshed = await mlsService.isConversationEstablished(groupId);
|
|
80
|
+
expect(isEstablshed).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
it('returns false if epoch number is 0', async () => {
|
|
83
|
+
const mlsService = new MLSService_1.MLSService(apiClient, mockCoreCrypto, {});
|
|
84
|
+
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
85
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
|
|
86
|
+
jest.spyOn(mlsService, 'getEpoch').mockResolvedValueOnce(0);
|
|
87
|
+
const isEstablshed = await mlsService.isConversationEstablished(groupId);
|
|
88
|
+
expect(isEstablshed).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
it.each([1, 2, 100])('returns false if epoch number is 1 or more', async (epoch) => {
|
|
91
|
+
const mlsService = new MLSService_1.MLSService(apiClient, mockCoreCrypto, {});
|
|
92
|
+
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
93
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
|
|
94
|
+
jest.spyOn(mlsService, 'getEpoch').mockResolvedValueOnce(epoch);
|
|
95
|
+
const isEstablshed = await mlsService.isConversationEstablished(groupId);
|
|
96
|
+
expect(isEstablshed).toBe(true);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
74
99
|
});
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"./lib/cryptography/AssetCryptography/crypto.node": "./lib/cryptography/AssetCryptography/crypto.browser.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@wireapp/api-client": "^25.4.
|
|
14
|
+
"@wireapp/api-client": "^25.4.1",
|
|
15
15
|
"@wireapp/commons": "^5.1.0",
|
|
16
16
|
"@wireapp/core-crypto": "1.0.0-rc.6",
|
|
17
17
|
"@wireapp/cryptobox": "12.8.0",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@wireapp/store-engine": "5.1.1",
|
|
21
21
|
"@wireapp/store-engine-dexie": "^2.1.3",
|
|
22
22
|
"axios": "1.5.0",
|
|
23
|
-
"bazinga64": "6.1.
|
|
23
|
+
"bazinga64": "6.1.3",
|
|
24
24
|
"deepmerge-ts": "5.1.0",
|
|
25
25
|
"hash.js": "1.1.7",
|
|
26
26
|
"http-status-codes": "2.2.0",
|
|
@@ -60,6 +60,6 @@
|
|
|
60
60
|
"test:coverage": "jest --coverage",
|
|
61
61
|
"watch": "tsc --watch"
|
|
62
62
|
},
|
|
63
|
-
"version": "41.7.
|
|
64
|
-
"gitHead": "
|
|
63
|
+
"version": "41.7.2",
|
|
64
|
+
"gitHead": "f9a30a2960bbd94bcdfc6e590aba55c8594dae45"
|
|
65
65
|
}
|