@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.
@@ -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
- isMLSConversationEstablished(groupId: string): Promise<boolean>;
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<void>;
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":"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"}
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
- const mlsConversation = await this.apiClient.api.conversation.getMLS1to1Conversation(otherUserId);
64
- if (mlsConversation.epoch > 0) {
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
- // If conversation is not established, we can wipe it and try to establish it again
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
- async isMLSConversationEstablished(groupId) {
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.isMLSConversationEstablished(groupId);
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, 'isMLSConversationEstablished').mockResolvedValue(false);
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, 'isMLSConversationEstablished').mockResolvedValue(true);
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, 'isMLSConversationEstablished').mockResolvedValueOnce(true);
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('successfully register an MLS group if it did not exist before', async () => {
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).toHaveBeenCalledTimes(1);
215
- expect(mlsService.registerConversation).toHaveBeenCalledWith(mockGroupId, [otherUserId, selfUser.user], selfUser);
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 epoch number is higher than 0', async () => {
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
- jest.spyOn(mlsService, 'registerConversation').mockRejectedValueOnce(undefined);
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: 1,
245
+ epoch: updatedEpoch,
230
246
  group_id: mockGroupId,
231
247
  });
232
- await conversationService.establishMLS1to1Conversation(mockGroupId, selfUser, otherUserId);
233
- expect(mlsService.registerConversation).toHaveBeenCalledTimes(1);
234
- expect(mlsService.registerConversation).toHaveBeenCalledWith(mockGroupId, [otherUserId, selfUser.user], selfUser);
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('retries to register mls group if epoch number is equal 0', async () => {
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
- jest.spyOn(mlsService, 'registerConversation').mockRejectedValueOnce(undefined);
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: 0,
266
+ epoch: remoteEpoch,
248
267
  group_id: mockGroupId,
249
268
  });
250
- await conversationService.establishMLS1to1Conversation(mockGroupId, selfUser, otherUserId);
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":"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;IAKhB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKrD,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"}
1
+ {"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"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"}
@@ -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 isMLSConversationEstablished = await this.conversationExists(groupId);
485
- if (!isMLSConversationEstablished) {
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.0",
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.2",
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.0",
64
- "gitHead": "6cec3bde870a1f566dc7213e7c254f56fdff19d0"
63
+ "version": "41.7.2",
64
+ "gitHead": "f9a30a2960bbd94bcdfc6e590aba55c8594dae45"
65
65
  }