@wireapp/core 28.1.0 → 28.2.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/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [28.2.0](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/compare/@wireapp/core@28.1.0...@wireapp/core@28.2.0) (2022-07-04)
7
+
8
+
9
+ ### Features
10
+
11
+ * **core, api-client:** Add MLS group creation ([#4295](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/issues/4295)) ([9755e03](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/commit/9755e03bee6a01860b932c4da5f713809551241f))
12
+
13
+
14
+
15
+
16
+
6
17
  # [28.1.0](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/compare/@wireapp/core@28.0.0...@wireapp/core@28.1.0) (2022-07-04)
7
18
 
8
19
 
package/package.json CHANGED
@@ -4,10 +4,10 @@
4
4
  },
5
5
  "dependencies": {
6
6
  "@open-wc/webpack-import-meta-loader": "0.4.7",
7
- "@otak/core-crypto": "0.2.0-beta-3",
7
+ "@otak/core-crypto": "0.3.0-beta-1",
8
8
  "@types/long": "4.0.1",
9
9
  "@types/node": "~14",
10
- "@wireapp/api-client": "19.8.0",
10
+ "@wireapp/api-client": "19.9.0",
11
11
  "@wireapp/cryptobox": "12.8.0",
12
12
  "bazinga64": "5.10.0",
13
13
  "hash.js": "1.1.7",
@@ -73,6 +73,6 @@
73
73
  "test:project": "yarn dist && yarn test",
74
74
  "test:node": "nyc jasmine --config=jasmine.json"
75
75
  },
76
- "version": "28.1.0",
77
- "gitHead": "4b3f49cdb3d62b745a325faa6deab76ad93b07f2"
76
+ "version": "28.2.0",
77
+ "gitHead": "5fb6aacf6f616c92d73593ec24cefb50a5a0f7f0"
78
78
  }
@@ -90,7 +90,7 @@ class Account extends events_1.EventEmitter {
90
90
  super();
91
91
  this.apiClient = apiClient;
92
92
  this.backendFeatures = this.apiClient.backendFeatures;
93
- this.mlsConfig = this.mlsConfig;
93
+ this.mlsConfig = mlsConfig;
94
94
  this.nbPrekeys = nbPrekeys;
95
95
  this.createStore = createStore;
96
96
  apiClient.on(api_client_1.APIClient.TOPIC.COOKIE_REFRESH, async (cookie) => {
@@ -232,7 +232,7 @@ class Account extends events_1.EventEmitter {
232
232
  const conversationService = new conversation_1.ConversationService(this.apiClient, cryptographyService, {
233
233
  // We can use qualified ids to send messages as long as the backend supports federated endpoints
234
234
  useQualifiedIds: this.backendFeatures.federationEndpoints,
235
- });
235
+ }, () => this.coreCryptoClient);
236
236
  const notificationService = new notification_1.NotificationService(this.apiClient, cryptographyService, this.storeEngine);
237
237
  const selfService = new self_1.SelfService(this.apiClient);
238
238
  const teamService = new team_1.TeamService(this.apiClient);
@@ -278,9 +278,10 @@ class Account extends events_1.EventEmitter {
278
278
  }
279
279
  const { userId, domain } = this.apiClient.context;
280
280
  return CoreCrypto.init({
281
- path: `corecrypto-${this.generateDbName(context)}`,
281
+ databaseName: `corecrypto-${this.generateDbName(context)}`,
282
282
  key: bazinga64_1.Encoder.toBase64(key).asString,
283
283
  clientId: `${userId}:${client.id}@${domain}`,
284
+ wasmFilePath: mlsConfig.coreCrypoWasmFilePath,
284
285
  });
285
286
  }
286
287
  async registerClient(loginData, clientInfo = coreDefaultClient, entropyData) {
@@ -292,7 +293,7 @@ class Account extends events_1.EventEmitter {
292
293
  if (this.mlsConfig) {
293
294
  this.coreCryptoClient = await this.createMLSClient(registeredClient, this.apiClient.context, this.mlsConfig);
294
295
  await this.service.client.uploadMLSPublicKeys(this.coreCryptoClient.clientPublicKey(), registeredClient.id);
295
- await this.service.client.uploadMLSKeyPackages(this.coreCryptoClient.clientKeypackages(this.nbPrekeys), registeredClient.id);
296
+ await this.service.client.uploadMLSKeyPackages(await this.coreCryptoClient.clientKeypackages(this.nbPrekeys), registeredClient.id);
296
297
  }
297
298
  this.apiClient.context.clientId = registeredClient.id;
298
299
  this.logger.info('Client is created');
@@ -1,3 +1,4 @@
1
+ import type { CoreCrypto } from '@otak/core-crypto';
1
2
  import type { APIClient } from '@wireapp/api-client';
2
3
  import { MessageSendingStatus, Conversation, DefaultConversationRoleName, MutedStatus, NewConversation, QualifiedUserClients, UserClients, ClientMismatch } from '@wireapp/api-client/src/conversation';
3
4
  import type { ConversationMemberLeaveEvent } from '@wireapp/api-client/src/event';
@@ -61,12 +62,13 @@ export interface MessageSendingCallbacks {
61
62
  export declare class ConversationService {
62
63
  private readonly apiClient;
63
64
  private readonly config;
65
+ private readonly coreCryptoClientProvider;
64
66
  readonly messageTimer: MessageTimer;
65
67
  private readonly messageService;
66
68
  private selfConversationId?;
67
69
  constructor(apiClient: APIClient, cryptographyService: CryptographyService, config: {
68
70
  useQualifiedIds?: boolean;
69
- });
71
+ }, coreCryptoClientProvider: () => CoreCrypto);
70
72
  private createEphemeral;
71
73
  private getConversationQualifiedMembers;
72
74
  /**
@@ -167,6 +169,7 @@ export declare class ConversationService {
167
169
  * @returns Resolves when the conversation was created
168
170
  */
169
171
  createConversation(conversationData: NewConversation): Promise<Conversation>;
172
+ private createMLSConversation;
170
173
  getConversations(conversationId: string): Promise<Conversation>;
171
174
  getConversations(conversationIds?: string[]): Promise<Conversation[]>;
172
175
  getAsset({ assetId, assetToken, otrKey, sha256 }: RemoteData): Promise<Uint8Array>;
@@ -19,6 +19,7 @@
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.ConversationService = exports.MessageTargetMode = void 0;
22
+ const bazinga64_1 = require("bazinga64");
22
23
  const conversation_1 = require("@wireapp/api-client/src/conversation");
23
24
  const data_1 = require("@wireapp/api-client/src/conversation/data");
24
25
  const protocol_messaging_1 = require("@wireapp/protocol-messaging");
@@ -35,9 +36,10 @@ var MessageTargetMode;
35
36
  MessageTargetMode[MessageTargetMode["USERS_CLIENTS"] = 2] = "USERS_CLIENTS";
36
37
  })(MessageTargetMode = exports.MessageTargetMode || (exports.MessageTargetMode = {}));
37
38
  class ConversationService {
38
- constructor(apiClient, cryptographyService, config) {
39
+ constructor(apiClient, cryptographyService, config, coreCryptoClientProvider) {
39
40
  this.apiClient = apiClient;
40
41
  this.config = config;
42
+ this.coreCryptoClientProvider = coreCryptoClientProvider;
41
43
  this.messageTimer = new conversation_2.MessageTimer();
42
44
  this.messageService = new MessageService_1.MessageService(this.apiClient, cryptographyService);
43
45
  }
@@ -620,8 +622,64 @@ class ConversationService {
620
622
  else {
621
623
  payload = conversationData;
622
624
  }
625
+ if (typeof conversationData !== 'string' && conversationData.protocol === conversation_1.ConversationProtocol.MLS) {
626
+ return this.createMLSConversation(conversationData);
627
+ }
623
628
  return this.apiClient.api.conversation.postConversation(payload);
624
629
  }
630
+ async createMLSConversation(conversationData) {
631
+ /**
632
+ * @note For creating MLS conversations the users & qualified_users
633
+ * field must be empty as backend is not aware which users
634
+ * are in a MLS conversation because of the MLS architecture.
635
+ */
636
+ const newConversation = await this.apiClient.api.conversation.postConversation(Object.assign(Object.assign({}, conversationData), { users: undefined, qualified_users: undefined }));
637
+ const { group_id: groupId } = newConversation;
638
+ const groupIdDecodedFromBase64 = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
639
+ const { qualified_users: qualifiedUsers = [], selfUserId } = conversationData;
640
+ if (!selfUserId) {
641
+ throw new Error('You need to pass self user qualified id in order to create an MLS conversation');
642
+ }
643
+ /**
644
+ * @note We need to fetch key packages for all the users
645
+ * we want to add to the new MLS conversations,
646
+ * includes self user too.
647
+ */
648
+ const keyPackages = await Promise.all([
649
+ this.apiClient.api.client.claimMLSKeyPackages(selfUserId.id, selfUserId.domain,
650
+ /**
651
+ * we should skip fetching key packages for current self client,
652
+ * it's already added by the backend on the group creation time
653
+ */
654
+ conversationData.creator_client),
655
+ ...qualifiedUsers.map(qualifiedId => this.apiClient.api.client.claimMLSKeyPackages(qualifiedId.id, qualifiedId.domain)),
656
+ ]);
657
+ const coreCryptoClient = this.coreCryptoClientProvider();
658
+ const coreCryptoKeyPackagesPayload = keyPackages.reduce((previousValue, currentValue) => {
659
+ // skip users that have not uploaded their MLS key packages
660
+ if (currentValue.key_packages.length > 0) {
661
+ return [
662
+ ...previousValue,
663
+ ...currentValue.key_packages.map(keyPackage => ({
664
+ id: new TextEncoder().encode(keyPackage.client),
665
+ kp: bazinga64_1.Decoder.fromBase64(keyPackage.key_package).asBytes,
666
+ })),
667
+ ];
668
+ }
669
+ return previousValue;
670
+ }, []);
671
+ await coreCryptoClient.createConversation(groupIdDecodedFromBase64);
672
+ const memberAddedMessages = await coreCryptoClient.addClientsToConversation(groupIdDecodedFromBase64, coreCryptoKeyPackagesPayload);
673
+ const sendingPromises = [];
674
+ if (memberAddedMessages === null || memberAddedMessages === void 0 ? void 0 : memberAddedMessages.welcome) {
675
+ sendingPromises.push(this.apiClient.api.conversation.postMlsWelcomeMessage(Uint8Array.from(memberAddedMessages.welcome)));
676
+ }
677
+ if (memberAddedMessages === null || memberAddedMessages === void 0 ? void 0 : memberAddedMessages.message) {
678
+ sendingPromises.push(this.apiClient.api.conversation.postMlsMessage(Uint8Array.from(memberAddedMessages.message)));
679
+ }
680
+ await Promise.all(sendingPromises);
681
+ return newConversation;
682
+ }
625
683
  async getConversations(conversationIds) {
626
684
  if (!conversationIds || !conversationIds.length) {
627
685
  return this.apiClient.api.conversation.getAllConversations();