@wireapp/core 29.0.6 → 29.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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
+ # [29.1.0](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/compare/@wireapp/core@29.0.6...@wireapp/core@29.1.0) (2022-07-28)
7
+
8
+
9
+ ### Features
10
+
11
+ * add users to mls conversation (FS-851) ([#4340](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/issues/4340)) ([2889385](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/commit/28893855ec9c42d59e1394142e8cf31252f2503a))
12
+
13
+
14
+
15
+
16
+
6
17
  ## [29.0.6](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/compare/@wireapp/core@29.0.5...@wireapp/core@29.0.6) (2022-07-27)
7
18
 
8
19
  **Note:** Version bump only for package @wireapp/core
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "@otak/core-crypto": "0.3.0-beta-2",
8
8
  "@types/long": "4.0.1",
9
9
  "@types/node": "~14",
10
- "@wireapp/api-client": "19.18.1",
10
+ "@wireapp/api-client": "19.19.0",
11
11
  "@wireapp/commons": "4.3.0",
12
12
  "@wireapp/cryptobox": "12.8.0",
13
13
  "@wireapp/store-engine-dexie": "1.6.10",
@@ -77,6 +77,6 @@
77
77
  "test:node": "nyc jasmine --config=jasmine.json",
78
78
  "watch": "tsc ---watch"
79
79
  },
80
- "version": "29.0.6",
81
- "gitHead": "3a5d82cac221738a5652a24756441b28e0b49072"
80
+ "version": "29.1.0",
81
+ "gitHead": "801c08df89e3374bc3019a13a91ba173c3f29ef0"
82
82
  }
@@ -9,7 +9,7 @@ import type { CryptographyService } from '../../cryptography/';
9
9
  import type { ClearConversationMessage, DeleteMessage, HideMessage, OtrMessage } from '../message/OtrMessage';
10
10
  import { XOR } from '@wireapp/commons/src/main/util/TypeUtil';
11
11
  import type { NotificationService } from '../../notification';
12
- import { AddUsersParams, MessageSendingCallbacks, MessageSendingOptions, SendMlsMessageParams, SendProteusMessageParams } from './ConversationService.types';
12
+ import { AddUsersParams, MessageSendingCallbacks, MessageSendingOptions, MLSReturnType, SendMlsMessageParams, SendProteusMessageParams } from './ConversationService.types';
13
13
  export declare class ConversationService {
14
14
  private readonly apiClient;
15
15
  private readonly config;
@@ -111,7 +111,7 @@ export declare class ConversationService {
111
111
  * @deprecated
112
112
  * @returns Promise
113
113
  */
114
- createConversation(name: string, otherUserIds: string | string[]): Promise<Conversation>;
114
+ createProteusConversation(name: string, otherUserIds: string | string[]): Promise<Conversation>;
115
115
  /**
116
116
  * Create a group conversation.
117
117
  *
@@ -121,17 +121,13 @@ export declare class ConversationService {
121
121
  * @param conversationData Payload object for group creation
122
122
  * @returns Resolves when the conversation was created
123
123
  */
124
- createConversation(conversationData: NewConversation): Promise<Conversation>;
125
- private createMLSConversation;
124
+ createProteusConversation(conversationData: NewConversation): Promise<Conversation>;
126
125
  getConversations(conversationId: string): Promise<Conversation>;
127
126
  getConversations(conversationIds?: string[]): Promise<Conversation[]>;
128
127
  getAsset({ assetId, assetToken, otrKey, sha256 }: RemoteData): Promise<Uint8Array>;
129
128
  getUnencryptedAsset(assetId: string, assetToken?: string): Promise<ArrayBuffer>;
130
- private addUsersToProteusGroup;
131
- private addUsersToMLSGroup;
132
- addUsers({ conversationId, protocol, userIds }: AddUsersParams): Promise<void | import("@wireapp/api-client/src/event").ConversationMemberJoinEvent>;
129
+ addUsersToProteusConversation({ conversationId, qualifiedUserIds }: Omit<AddUsersParams, 'groupId'>): Promise<import("@wireapp/api-client/src/event").ConversationMemberJoinEvent>;
133
130
  removeUser(conversationId: string, userId: string): Promise<string>;
134
- private sendMlsMessage;
135
131
  private sendProteusMessage;
136
132
  /**
137
133
  * Sends a message to a conversation
@@ -145,4 +141,14 @@ export declare class ConversationService {
145
141
  setMemberConversationRole(conversationId: string, userId: string, conversationRole: DefaultConversationRoleName | string): Promise<void>;
146
142
  private isClearFromMismatch;
147
143
  private generateGenericMessage;
144
+ /**
145
+ * ###############################################
146
+ * ################ MLS Functions ################
147
+ * ###############################################
148
+ */
149
+ private getCoreCryptoKeyPackagesPayload;
150
+ private addUsersToExistingMLSConversation;
151
+ createMLSConversation(conversationData: NewConversation): Promise<MLSReturnType>;
152
+ private sendMLSMessage;
153
+ addUsersToMLSConversation({ qualifiedUserIds, groupId, conversationId, }: Required<AddUsersParams>): Promise<MLSReturnType>;
148
154
  }
@@ -19,7 +19,6 @@
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.ConversationService = void 0;
22
- const bazinga64_1 = require("bazinga64");
23
22
  const conversation_1 = require("@wireapp/api-client/src/conversation");
24
23
  const data_1 = require("@wireapp/api-client/src/conversation/data");
25
24
  const protocol_messaging_1 = require("@wireapp/protocol-messaging");
@@ -30,6 +29,7 @@ const MessageBuilder_1 = require("../message/MessageBuilder");
30
29
  const MessageService_1 = require("../message/MessageService");
31
30
  const MessageToProtoMapper_1 = require("../message/MessageToProtoMapper");
32
31
  const ConversationService_types_1 = require("./ConversationService.types");
32
+ const bazinga64_1 = require("bazinga64");
33
33
  class ConversationService {
34
34
  constructor(apiClient, cryptographyService, config, coreCryptoClientProvider, notificationService) {
35
35
  this.apiClient = apiClient;
@@ -609,7 +609,7 @@ class ConversationService {
609
609
  }
610
610
  return Promise.all(conversationIds.map(conversationId => this.leaveConversation(conversationId)));
611
611
  }
612
- createConversation(conversationData, otherUserIds) {
612
+ createProteusConversation(conversationData, otherUserIds) {
613
613
  let payload;
614
614
  if (typeof conversationData === 'string') {
615
615
  const ids = typeof otherUserIds === 'string' ? [otherUserIds] : otherUserIds;
@@ -622,66 +622,8 @@ class ConversationService {
622
622
  else {
623
623
  payload = conversationData;
624
624
  }
625
- if (typeof conversationData !== 'string' && conversationData.protocol === conversation_1.ConversationProtocol.MLS) {
626
- return this.createMLSConversation(conversationData);
627
- }
628
625
  return this.apiClient.api.conversation.postConversation(payload);
629
626
  }
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: bazinga64_1.Encoder.toBase64(keyPackage.client).asBytes,
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
- await this.notificationService.saveConversationGroupId(newConversation);
682
- // We fetch the fresh version of the conversation created on backend with the newly added users
683
- return this.getConversations(newConversation.id);
684
- }
685
627
  async getConversations(conversationIds) {
686
628
  if (!conversationIds || !conversationIds.length) {
687
629
  return this.apiClient.api.conversation.getAllConversations();
@@ -704,37 +646,14 @@ class ConversationService {
704
646
  const request = await this.apiClient.api.asset.getAssetV3(assetId, assetToken);
705
647
  return (await request.response).buffer;
706
648
  }
707
- async addUsersToProteusGroup({ conversationId, userIds }) {
708
- const response = await this.apiClient.api.conversation.postMembers(conversationId, userIds);
649
+ async addUsersToProteusConversation({ conversationId, qualifiedUserIds }) {
650
+ const response = await this.apiClient.api.conversation.postMembers(conversationId, qualifiedUserIds);
709
651
  return response;
710
652
  }
711
- async addUsersToMLSGroup({ conversationId, userIds }) {
712
- return console.info('addUsersToMLSGroup', conversationId, userIds);
713
- }
714
- async addUsers({ conversationId, protocol, userIds }) {
715
- return protocol === conversation_1.ConversationProtocol.MLS
716
- ? this.addUsersToMLSGroup({ conversationId, userIds })
717
- : this.addUsersToProteusGroup({ conversationId, userIds });
718
- }
719
653
  async removeUser(conversationId, userId) {
720
654
  await this.apiClient.api.conversation.deleteMember(conversationId, userId);
721
655
  return userId;
722
656
  }
723
- async sendMlsMessage(params, genericMessage, content) {
724
- var _a, _b;
725
- const { groupId, onSuccess, payload } = params;
726
- const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
727
- const coreCryptoClient = this.coreCryptoClientProvider();
728
- const encrypted = await coreCryptoClient.encryptMessage(groupIdBytes, protocol_messaging_1.GenericMessage.encode(genericMessage).finish());
729
- try {
730
- const { time = '' } = await this.apiClient.api.conversation.postMlsMessage(encrypted);
731
- onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(genericMessage, (time === null || time === void 0 ? void 0 : time.length) > 0 ? time : new Date().toISOString());
732
- return Object.assign(Object.assign({}, payload), { content, messageTimer: ((_a = genericMessage.ephemeral) === null || _a === void 0 ? void 0 : _a.expireAfterMillis) || 0, state: conversation_2.PayloadBundleState.OUTGOING_SENT });
733
- }
734
- catch (_c) {
735
- return Object.assign(Object.assign({}, payload), { content, messageTimer: ((_b = genericMessage.ephemeral) === null || _b === void 0 ? void 0 : _b.expireAfterMillis) || 0, state: conversation_2.PayloadBundleState.CANCELLED });
736
- }
737
- }
738
657
  async sendProteusMessage(params, genericMessage, content) {
739
658
  var _a;
740
659
  const { userIds, sendAsProtobuf, conversationDomain, nativePush, targetMode, payload, onClientMismatch, onSuccess } = params;
@@ -770,7 +689,7 @@ class ConversationService {
770
689
  return Object.assign(Object.assign({}, payload), { state: conversation_2.PayloadBundleState.CANCELLED });
771
690
  }
772
691
  return isMLS(params)
773
- ? this.sendMlsMessage(params, genericMessage, content)
692
+ ? this.sendMLSMessage(params, genericMessage, content)
774
693
  : this.sendProteusMessage(params, genericMessage, content);
775
694
  }
776
695
  sendTypingStart(conversationId) {
@@ -870,6 +789,108 @@ class ConversationService {
870
789
  throw new Error(`No send method implemented for "${payload['type']}".`);
871
790
  }
872
791
  }
792
+ /**
793
+ * ###############################################
794
+ * ################ MLS Functions ################
795
+ * ###############################################
796
+ */
797
+ async getCoreCryptoKeyPackagesPayload(qualifiedUsers) {
798
+ /**
799
+ * @note We need to fetch key packages for all the users
800
+ * we want to add to the new MLS conversations,
801
+ * includes self user too.
802
+ */
803
+ const keyPackages = await Promise.all([
804
+ ...qualifiedUsers.map(({ id, domain, skipOwn }) => this.apiClient.api.client.claimMLSKeyPackages(id, domain, skipOwn)),
805
+ ]);
806
+ const coreCryptoKeyPackagesPayload = keyPackages.reduce((previousValue, currentValue) => {
807
+ // skip users that have not uploaded their MLS key packages
808
+ if (currentValue.key_packages.length > 0) {
809
+ return [
810
+ ...previousValue,
811
+ ...currentValue.key_packages.map(keyPackage => ({
812
+ id: bazinga64_1.Encoder.toBase64(keyPackage.client).asBytes,
813
+ kp: bazinga64_1.Decoder.fromBase64(keyPackage.key_package).asBytes,
814
+ })),
815
+ ];
816
+ }
817
+ return previousValue;
818
+ }, []);
819
+ return coreCryptoKeyPackagesPayload;
820
+ }
821
+ async addUsersToExistingMLSConversation(groupIdDecodedFromBase64, invitee) {
822
+ const coreCryptoClient = this.coreCryptoClientProvider();
823
+ const memberAddedMessages = await coreCryptoClient.addClientsToConversation(groupIdDecodedFromBase64, invitee);
824
+ if (memberAddedMessages === null || memberAddedMessages === void 0 ? void 0 : memberAddedMessages.welcome) {
825
+ await this.apiClient.api.conversation.postMlsWelcomeMessage(Uint8Array.from(memberAddedMessages.welcome));
826
+ }
827
+ if (memberAddedMessages === null || memberAddedMessages === void 0 ? void 0 : memberAddedMessages.message) {
828
+ return this.apiClient.api.conversation.postMlsMessage(Uint8Array.from(memberAddedMessages.message));
829
+ }
830
+ return null;
831
+ }
832
+ async createMLSConversation(conversationData) {
833
+ /**
834
+ * @note For creating MLS conversations the users & qualified_users
835
+ * field must be empty as backend is not aware which users
836
+ * are in a MLS conversation because of the MLS architecture.
837
+ */
838
+ const newConversation = await this.apiClient.api.conversation.postConversation(Object.assign(Object.assign({}, conversationData), { users: undefined, qualified_users: undefined }));
839
+ const { group_id: groupId, qualified_id: qualifiedId } = newConversation;
840
+ const groupIdDecodedFromBase64 = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
841
+ const { qualified_users: qualifiedUsers = [], selfUserId } = conversationData;
842
+ if (!selfUserId) {
843
+ throw new Error('You need to pass self user qualified id in order to create an MLS conversation');
844
+ }
845
+ const coreCryptoClient = this.coreCryptoClientProvider();
846
+ await coreCryptoClient.createConversation(groupIdDecodedFromBase64);
847
+ const coreCryptoKeyPackagesPayload = await this.getCoreCryptoKeyPackagesPayload([
848
+ {
849
+ id: selfUserId.id,
850
+ domain: selfUserId.domain,
851
+ /**
852
+ * we should skip fetching key packages for current self client,
853
+ * it's already added by the backend on the group creation time
854
+ */
855
+ skipOwn: conversationData.creator_client,
856
+ },
857
+ ...qualifiedUsers,
858
+ ]);
859
+ const response = await this.addUsersToExistingMLSConversation(groupIdDecodedFromBase64, coreCryptoKeyPackagesPayload);
860
+ await this.notificationService.saveConversationGroupId(newConversation);
861
+ // We fetch the fresh version of the conversation created on backend with the newly added users
862
+ const conversation = await this.getConversations(qualifiedId.id);
863
+ return {
864
+ events: (response === null || response === void 0 ? void 0 : response.events) || [],
865
+ conversation,
866
+ };
867
+ }
868
+ async sendMLSMessage(params, genericMessage, content) {
869
+ var _a, _b;
870
+ const { groupId, onSuccess, payload } = params;
871
+ const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
872
+ const coreCryptoClient = this.coreCryptoClientProvider();
873
+ const encrypted = await coreCryptoClient.encryptMessage(groupIdBytes, protocol_messaging_1.GenericMessage.encode(genericMessage).finish());
874
+ try {
875
+ const { time = '' } = await this.apiClient.api.conversation.postMlsMessage(encrypted);
876
+ onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(genericMessage, (time === null || time === void 0 ? void 0 : time.length) > 0 ? time : new Date().toISOString());
877
+ return Object.assign(Object.assign({}, payload), { content, messageTimer: ((_a = genericMessage.ephemeral) === null || _a === void 0 ? void 0 : _a.expireAfterMillis) || 0, state: conversation_2.PayloadBundleState.OUTGOING_SENT });
878
+ }
879
+ catch (_c) {
880
+ return Object.assign(Object.assign({}, payload), { content, messageTimer: ((_b = genericMessage.ephemeral) === null || _b === void 0 ? void 0 : _b.expireAfterMillis) || 0, state: conversation_2.PayloadBundleState.CANCELLED });
881
+ }
882
+ }
883
+ async addUsersToMLSConversation({ qualifiedUserIds, groupId, conversationId, }) {
884
+ const groupIdDecodedFromBase64 = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
885
+ const coreCryptoKeyPackagesPayload = await this.getCoreCryptoKeyPackagesPayload([...qualifiedUserIds]);
886
+ const response = await this.addUsersToExistingMLSConversation(groupIdDecodedFromBase64, coreCryptoKeyPackagesPayload);
887
+ console.info('addUsersToMLSGroup', conversationId, qualifiedUserIds, groupIdDecodedFromBase64, response);
888
+ const conversation = await this.getConversations(conversationId.id);
889
+ return {
890
+ events: (response === null || response === void 0 ? void 0 : response.events) || [],
891
+ conversation,
892
+ };
893
+ }
873
894
  }
874
895
  exports.ConversationService = ConversationService;
875
896
  //# sourceMappingURL=ConversationService.js.map
@@ -1,6 +1,7 @@
1
1
  import { GenericMessage } from '@wireapp/protocol-messaging';
2
- import { QualifiedUserClients, ClientMismatch, ConversationProtocol, MessageSendingStatus, UserClients } from '@wireapp/api-client/src/conversation';
2
+ import { QualifiedUserClients, ClientMismatch, ConversationProtocol, MessageSendingStatus, UserClients, Conversation } from '@wireapp/api-client/src/conversation';
3
3
  import { QualifiedId } from '@wireapp/api-client/src/user';
4
+ import { MlsEvent } from '@wireapp/api-client/src/conversation/data/MlsEventData';
4
5
  export declare enum MessageTargetMode {
5
6
  NONE = 0,
6
7
  USERS = 1,
@@ -88,7 +89,15 @@ export declare type SendMlsMessageParams<T> = SendCommonParams<T> & {
88
89
  */
89
90
  groupId: string;
90
91
  };
91
- export declare type AddUsersParams = ProtocolParam & {
92
+ export declare type QualifiedUsers = QualifiedId & {
93
+ skipOwn?: string;
94
+ };
95
+ export declare type AddUsersParams = {
92
96
  conversationId: QualifiedId;
93
- userIds: QualifiedId[];
97
+ qualifiedUserIds: QualifiedId[];
98
+ groupId?: string;
99
+ };
100
+ export declare type MLSReturnType = {
101
+ events: MlsEvent[];
102
+ conversation: Conversation;
94
103
  };