@wireapp/core 46.46.6-beta.10.d7a6c4c53 → 46.46.6-beta.14.f6fd03fe6

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.
Files changed (195) hide show
  1. package/lib/Account.d.ts +51 -168
  2. package/lib/Account.d.ts.map +1 -1
  3. package/lib/Account.js +127 -517
  4. package/lib/Account.test.js +147 -158
  5. package/lib/broadcast/AvailabilityType.d.ts +1 -1
  6. package/lib/broadcast/AvailabilityType.d.ts.map +1 -1
  7. package/lib/broadcast/BroadcastService.d.ts +1 -1
  8. package/lib/broadcast/BroadcastService.d.ts.map +1 -1
  9. package/lib/broadcast/BroadcastService.js +1 -1
  10. package/lib/client/ClientService.d.ts +3 -4
  11. package/lib/client/ClientService.d.ts.map +1 -1
  12. package/lib/client/ClientService.js +5 -19
  13. package/lib/conversation/AbortReason.d.ts +1 -1
  14. package/lib/conversation/AbortReason.d.ts.map +1 -1
  15. package/lib/conversation/AssetService/AssetService.d.ts +30 -12
  16. package/lib/conversation/AssetService/AssetService.d.ts.map +1 -1
  17. package/lib/conversation/AssetService/AssetService.js +10 -1
  18. package/lib/conversation/AssetService/AssetService.test.js +3 -8
  19. package/lib/conversation/ClientActionType.d.ts +1 -1
  20. package/lib/conversation/ClientActionType.d.ts.map +1 -1
  21. package/lib/conversation/ClientActionType.js +1 -1
  22. package/lib/conversation/ConversationService/ConversationService.d.ts +14 -98
  23. package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
  24. package/lib/conversation/ConversationService/ConversationService.js +101 -314
  25. package/lib/conversation/ConversationService/ConversationService.test.js +47 -441
  26. package/lib/conversation/ConversationService/ConversationService.types.d.ts +4 -5
  27. package/lib/conversation/ConversationService/ConversationService.types.d.ts.map +1 -1
  28. package/lib/conversation/ConversationService/Utility/getConversationQualifiedMembers.d.ts.map +1 -1
  29. package/lib/conversation/ConversationService/Utility/getConversationQualifiedMembers.js +3 -6
  30. package/lib/conversation/SubconversationService/SubconversationService.d.ts.map +1 -1
  31. package/lib/conversation/SubconversationService/SubconversationService.js +11 -158
  32. package/lib/conversation/SubconversationService/SubconversationService.test.js +2 -8
  33. package/lib/conversation/content/AssetContent.d.ts +1 -1
  34. package/lib/conversation/content/AssetContent.d.ts.map +1 -1
  35. package/lib/conversation/content/ButtonActionConfirmationContent.d.ts +1 -1
  36. package/lib/conversation/content/ButtonActionConfirmationContent.d.ts.map +1 -1
  37. package/lib/conversation/content/ButtonActionContent.d.ts +1 -1
  38. package/lib/conversation/content/ButtonActionContent.d.ts.map +1 -1
  39. package/lib/conversation/content/ClearedContent.d.ts +1 -1
  40. package/lib/conversation/content/ClearedContent.d.ts.map +1 -1
  41. package/lib/conversation/content/ClientActionContent.d.ts +1 -1
  42. package/lib/conversation/content/ClientActionContent.d.ts.map +1 -1
  43. package/lib/conversation/content/CompositeContent.d.ts +1 -1
  44. package/lib/conversation/content/CompositeContent.d.ts.map +1 -1
  45. package/lib/conversation/content/ConfirmationContent.d.ts +1 -1
  46. package/lib/conversation/content/ConfirmationContent.d.ts.map +1 -1
  47. package/lib/conversation/content/DeletedContent.d.ts +1 -1
  48. package/lib/conversation/content/DeletedContent.d.ts.map +1 -1
  49. package/lib/conversation/content/HiddenContent.d.ts +1 -1
  50. package/lib/conversation/content/HiddenContent.d.ts.map +1 -1
  51. package/lib/conversation/content/KnockContent.d.ts +1 -1
  52. package/lib/conversation/content/KnockContent.d.ts.map +1 -1
  53. package/lib/conversation/content/LinkPreviewContent.d.ts +1 -1
  54. package/lib/conversation/content/LinkPreviewContent.d.ts.map +1 -1
  55. package/lib/conversation/content/MentionContent.d.ts +1 -1
  56. package/lib/conversation/content/MentionContent.d.ts.map +1 -1
  57. package/lib/conversation/content/MultipartContent.d.ts +1 -1
  58. package/lib/conversation/content/MultipartContent.d.ts.map +1 -1
  59. package/lib/conversation/content/QuoteContent.d.ts +1 -1
  60. package/lib/conversation/content/QuoteContent.d.ts.map +1 -1
  61. package/lib/conversation/content/TweetContent.d.ts +1 -1
  62. package/lib/conversation/content/TweetContent.d.ts.map +1 -1
  63. package/lib/conversation/content/index.d.ts +1 -1
  64. package/lib/conversation/content/index.d.ts.map +1 -1
  65. package/lib/conversation/content/index.js +1 -1
  66. package/lib/conversation/message/MessageBuilder.d.ts +1 -1
  67. package/lib/conversation/message/MessageBuilder.d.ts.map +1 -1
  68. package/lib/conversation/message/MessageBuilder.js +1 -1
  69. package/lib/conversation/message/MessageService.d.ts.map +1 -1
  70. package/lib/conversation/message/MessageService.js +1 -1
  71. package/lib/conversation/message/MessageService.test.js +1 -7
  72. package/lib/conversation/message/MessageToProtoMapper.d.ts +1 -1
  73. package/lib/conversation/message/MessageToProtoMapper.d.ts.map +1 -1
  74. package/lib/conversation/message/MessageToProtoMapper.js +1 -1
  75. package/lib/conversation/message/messageSender.js +2 -2
  76. package/lib/cryptography/AssetCryptography/EncryptedAsset.d.ts +2 -2
  77. package/lib/cryptography/AssetCryptography/EncryptedAsset.d.ts.map +1 -1
  78. package/lib/messagingProtocols/common.types.d.ts +0 -9
  79. package/lib/messagingProtocols/common.types.d.ts.map +1 -1
  80. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.d.ts +2 -2
  81. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.d.ts.map +1 -1
  82. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.js +1 -2
  83. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.d.ts +1 -1
  84. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.d.ts.map +1 -1
  85. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.js +11 -13
  86. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.test.js +16 -21
  87. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts +3 -9
  88. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts.map +1 -1
  89. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.js +12 -31
  90. package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts +0 -6
  91. package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts.map +1 -1
  92. package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.js +1 -19
  93. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts +4 -0
  94. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts.map +1 -0
  95. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.js +69 -0
  96. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/index.d.ts +2 -0
  97. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingProposalsQueue → IncomingMessagesQueue}/index.d.ts.map +1 -1
  98. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingProposalsQueue → IncomingMessagesQueue}/index.js +1 -1
  99. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts +1 -0
  100. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts.map +1 -1
  101. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.js +1 -0
  102. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts.map +1 -1
  103. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.js +14 -23
  104. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts +2 -0
  105. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts.map +1 -0
  106. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.js +98 -0
  107. package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.d.ts.map +1 -1
  108. package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.js +2 -5
  109. package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.test.js +3 -13
  110. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts +2 -38
  111. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts.map +1 -1
  112. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.js +6 -41
  113. package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +34 -38
  114. package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
  115. package/lib/messagingProtocols/mls/MLSService/MLSService.js +208 -267
  116. package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +160 -157
  117. package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.js +3 -3
  118. package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.test.js +5 -5
  119. package/lib/messagingProtocols/mls/conversationRejoinQueue.js +2 -2
  120. package/lib/messagingProtocols/mls/types.d.ts +8 -0
  121. package/lib/messagingProtocols/mls/types.d.ts.map +1 -1
  122. package/lib/messagingProtocols/proteus/EventHandler/events/otrMessageAdd/otrMessageAdd.d.ts.map +1 -1
  123. package/lib/messagingProtocols/proteus/EventHandler/events/otrMessageAdd/otrMessageAdd.js +1 -7
  124. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts +15 -8
  125. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts.map +1 -1
  126. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.js +62 -97
  127. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts +6 -0
  128. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts.map +1 -1
  129. package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts +6 -1
  130. package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts.map +1 -1
  131. package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.js +22 -19
  132. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts +3 -5
  133. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts.map +1 -1
  134. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.js +24 -11
  135. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts +0 -1
  136. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts.map +1 -1
  137. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.js +2 -11
  138. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.test.js +9 -13
  139. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts +2 -3
  140. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts.map +1 -1
  141. package/lib/messagingProtocols/proteus/ProteusService/WithMockedGenerics.test.js +4 -11
  142. package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts +4 -0
  143. package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts.map +1 -1
  144. package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.js +5 -0
  145. package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts +1 -2
  146. package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts.map +1 -1
  147. package/lib/messagingProtocols/proteus/ProteusService/identityClearer.js +2 -8
  148. package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.test.js +0 -4
  149. package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts +1 -1
  150. package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts.map +1 -1
  151. package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.js +1 -1
  152. package/lib/notification/NotificationService.d.ts +6 -20
  153. package/lib/notification/NotificationService.d.ts.map +1 -1
  154. package/lib/notification/NotificationService.js +14 -23
  155. package/lib/notification/NotificationService.test.js +0 -8
  156. package/lib/secretStore/secretKeyGenerator.d.ts +0 -1
  157. package/lib/secretStore/secretKeyGenerator.d.ts.map +1 -1
  158. package/lib/secretStore/secretKeyGenerator.js +1 -3
  159. package/lib/self/SelfService.d.ts +2 -2
  160. package/lib/self/SelfService.d.ts.map +1 -1
  161. package/lib/self/SelfService.test.js +2 -5
  162. package/lib/team/TeamService.d.ts +2 -5
  163. package/lib/team/TeamService.d.ts.map +1 -1
  164. package/lib/team/TeamService.js +2 -12
  165. package/lib/user/UserService.d.ts +2 -2
  166. package/lib/user/UserService.d.ts.map +1 -1
  167. package/lib/user/UserService.js +3 -3
  168. package/lib/util/TypePredicateUtil.d.ts.map +1 -1
  169. package/lib/util/TypePredicateUtil.js +2 -2
  170. package/package.json +3 -3
  171. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts +0 -7
  172. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts.map +0 -1
  173. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.js +0 -48
  174. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/index.d.ts +0 -2
  175. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts +0 -2
  176. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts.map +0 -1
  177. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.js +0 -124
  178. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.d.ts +0 -78
  179. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.d.ts.map +0 -1
  180. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.js +0 -173
  181. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts +0 -2
  182. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts.map +0 -1
  183. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.js +0 -117
  184. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts +0 -167
  185. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts.map +0 -1
  186. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.js +0 -317
  187. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts +0 -2
  188. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts.map +0 -1
  189. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.js +0 -248
  190. package/lib/messagingProtocols/mls/recovery/index.d.ts +0 -5
  191. package/lib/messagingProtocols/mls/recovery/index.d.ts.map +0 -1
  192. package/lib/messagingProtocols/mls/recovery/index.js +0 -28
  193. package/lib/test/StoreHelper.d.ts +0 -2
  194. package/lib/test/StoreHelper.d.ts.map +0 -1
  195. package/lib/test/StoreHelper.js +0 -27
@@ -18,20 +18,24 @@
18
18
  *
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.MLSService = exports.MLSServiceEvents = exports.optionalToUint8Array = void 0;
22
- const conversation_1 = require("@wireapp/api-client/lib/conversation");
21
+ exports.MLSService = exports.optionalToUint8Array = void 0;
22
+ const http_1 = require("@wireapp/api-client/lib/http");
23
+ const TimeUtil_1 = require("@wireapp/commons/lib/util/TimeUtil");
23
24
  const bazinga64_1 = require("bazinga64");
24
25
  const commons_1 = require("@wireapp/commons");
25
26
  const core_crypto_1 = require("@wireapp/core-crypto");
27
+ const priority_queue_1 = require("@wireapp/priority-queue");
26
28
  const ClientMLSError_1 = require("./ClientMLSError");
27
29
  const CoreCryptoMLSError_1 = require("./CoreCryptoMLSError");
28
- const conversation_2 = require("../../../conversation");
30
+ const conversation_1 = require("../../../conversation");
31
+ const messageSender_1 = require("../../../conversation/message/messageSender");
29
32
  const fullyQualifiedClientIdUtils_1 = require("../../../util/fullyQualifiedClientIdUtils");
30
33
  const numberToHex_1 = require("../../../util/numberToHex");
31
34
  const TaskScheduler_1 = require("../../../util/TaskScheduler");
32
35
  const E2EIServiceInternal_1 = require("../E2EIdentityService/E2EIServiceInternal");
33
36
  const Helper_1 = require("../E2EIdentityService/Helper");
34
37
  const events_1 = require("../EventHandler/events");
38
+ const messageAdd_1 = require("../EventHandler/events/messageAdd");
35
39
  const MLSId_1 = require("../utils/MLSId");
36
40
  //@todo: this function is temporary, we wait for the update from core-crypto side
37
41
  //they are returning regular array instead of Uint8Array for commit and welcome messages
@@ -40,17 +44,9 @@ const optionalToUint8Array = (array) => {
40
44
  };
41
45
  exports.optionalToUint8Array = optionalToUint8Array;
42
46
  const defaultConfig = {
43
- keyingMaterialUpdateThreshold: commons_1.TimeUtil.TimeInMillis.DAY * 30,
47
+ keyingMaterialUpdateThreshold: 1000 * 60 * 60 * 24 * 30, //30 days
44
48
  nbKeyPackages: 100,
45
49
  };
46
- var MLSServiceEvents;
47
- (function (MLSServiceEvents) {
48
- MLSServiceEvents["NEW_EPOCH"] = "newEpoch";
49
- MLSServiceEvents["MLS_CLIENT_MISMATCH"] = "mlsClientMismatch";
50
- MLSServiceEvents["NEW_CRL_DISTRIBUTION_POINTS"] = "newCrlDistributionPoints";
51
- MLSServiceEvents["MLS_EVENT_DISTRIBUTED"] = "mlsEventDistributed";
52
- MLSServiceEvents["KEY_MATERIAL_UPDATE_FAILURE"] = "keyMaterialUpdateFailure";
53
- })(MLSServiceEvents || (exports.MLSServiceEvents = MLSServiceEvents = {}));
54
50
  class MLSService extends commons_1.TypedEventEmitter {
55
51
  apiClient;
56
52
  coreCryptoClient;
@@ -60,31 +56,18 @@ class MLSService extends commons_1.TypedEventEmitter {
60
56
  _config;
61
57
  textEncoder = new TextEncoder();
62
58
  textDecoder = new TextDecoder();
59
+ conflictBackoffQueue = new priority_queue_1.PriorityQueue({
60
+ maxRetries: 10,
61
+ retryDelay: 500,
62
+ maxRetryDelay: TimeUtil_1.TimeInMillis.SECOND * 32,
63
+ shouldRetry: error => error instanceof http_1.BackendError && error.code === http_1.StatusCode.CONFLICT,
64
+ });
63
65
  constructor(apiClient, coreCryptoClient, coreDatabase, recurringTaskScheduler) {
64
66
  super();
65
67
  this.apiClient = apiClient;
66
68
  this.coreCryptoClient = coreCryptoClient;
67
69
  this.coreDatabase = coreDatabase;
68
70
  this.recurringTaskScheduler = recurringTaskScheduler;
69
- const mlsTransport = {
70
- sendCommitBundle: this._uploadCommitBundle,
71
- // Info: This is not used for now, but we need to implement it to be able to use the mls transport
72
- sendMessage: async () => {
73
- return 'success';
74
- },
75
- prepareForTransport: async () => {
76
- throw new Error('Method not implemented.');
77
- },
78
- };
79
- const epochObserver = {
80
- epochChanged: async (groupId, epoch) => {
81
- const groupIdStr = bazinga64_1.Encoder.toBase64(groupId.copyBytes()).asString;
82
- this.logger.info(`Epoch changed for group ${groupIdStr}, new epoch: ${epoch}`);
83
- this.emit(MLSServiceEvents.NEW_EPOCH, { epoch, groupId: groupIdStr });
84
- },
85
- };
86
- void this.coreCryptoClient.registerEpochObserver(epochObserver);
87
- void this.coreCryptoClient.provideTransport(mlsTransport);
88
71
  }
89
72
  /**
90
73
  * return true if the MLS service if configured and ready to be used
@@ -114,39 +97,24 @@ class MLSService extends commons_1.TypedEventEmitter {
114
97
  ...defaultConfig,
115
98
  ...filteredMLSConfig,
116
99
  };
117
- await this.coreCryptoClient.transaction(cx => {
118
- const clientId = new core_crypto_1.ClientId((0, MLSId_1.generateMLSDeviceId)(userId, client.id));
119
- return cx.mlsInit(clientId, this.config.ciphersuites, this.config.nbKeyPackages);
100
+ await this.coreCryptoClient.mlsInit((0, MLSId_1.generateMLSDeviceId)(userId, client.id), this.config.ciphersuites, this.config.nbKeyPackages);
101
+ await this.coreCryptoClient.registerCallbacks({
102
+ // All authorization/membership rules are enforced on backend
103
+ clientIsExistingGroupUser: async () => true,
104
+ authorize: async () => true,
105
+ userAuthorize: async () => true,
120
106
  });
121
- try {
122
- const ccClientSignature = await this.getCCClientSignatureString();
123
- const mlsDeviceStatus = (0, Helper_1.getMLSDeviceStatus)(client, this.config.defaultCiphersuite, ccClientSignature);
124
- switch (mlsDeviceStatus) {
125
- case Helper_1.MLSDeviceStatus.REGISTERED:
126
- if (!skipInitIdentity) {
127
- await this.verifyRemoteMLSKeyPackagesAmount(client.id);
128
- }
129
- else {
130
- this.logger.info(`Blocked initial key package upload for client ${client.id} as E2EI is enabled`);
131
- }
132
- break;
133
- case Helper_1.MLSDeviceStatus.MISMATCH:
134
- this.logger.error(`Client ${client.id} is registered but with a different signature`);
135
- this.emit(MLSServiceEvents.MLS_CLIENT_MISMATCH);
136
- break;
137
- case Helper_1.MLSDeviceStatus.FRESH:
138
- if (!skipInitIdentity) {
139
- await this.uploadMLSPublicKeys(client);
140
- }
141
- else {
142
- this.logger.info(`Blocked initial key package upload for client ${client.id} as E2EI is enabled`);
143
- }
144
- break;
107
+ const isFreshMLSSelfClient = !this.isInitializedMLSClient(client);
108
+ const shouldinitIdentity = !(isFreshMLSSelfClient && skipInitIdentity);
109
+ if (shouldinitIdentity) {
110
+ // We need to make sure keypackages and public key are uploaded to the backend
111
+ if (isFreshMLSSelfClient) {
112
+ await this.uploadMLSPublicKeys(client);
145
113
  }
114
+ await this.verifyRemoteMLSKeyPackagesAmount(client.id);
146
115
  }
147
- catch (error) {
148
- this.logger.error(`Error while initializing client ${client.id}`, error);
149
- throw error;
116
+ else {
117
+ this.logger.info(`Blocked initial key package upload for client ${client.id} as E2EI is enabled`);
150
118
  }
151
119
  }
152
120
  /**
@@ -159,62 +127,46 @@ class MLSService extends commons_1.TypedEventEmitter {
159
127
  ? core_crypto_1.CredentialType.X509
160
128
  : core_crypto_1.CredentialType.Basic;
161
129
  }
162
- _uploadCommitBundle = async ({ commit, groupInfo, welcome, }) => {
163
- const bundlePayload = new Uint8Array([
164
- ...commit,
165
- ...groupInfo.payload.copyBytes(),
166
- ...(welcome?.copyBytes() || []),
167
- ]);
130
+ uploadCommitBundle = async (groupId, commitBundle, { isExternalCommit = false, regenerateCommitBundle } = {}) => {
168
131
  try {
169
- const response = await this.apiClient.api.conversation.postMlsCommitBundle(bundlePayload);
170
- if (response.failed_to_send) {
171
- this.logger.warn(`Failed to send commit bundle to backend`);
172
- return 'retry';
173
- }
174
- const { events, time } = response;
175
- this.emit(MLSServiceEvents.MLS_EVENT_DISTRIBUTED, { events, time });
176
- return 'success';
132
+ return await this._uploadCommitBundle(groupId, async () => commitBundle, isExternalCommit);
177
133
  }
178
134
  catch (error) {
179
- this.logger.warn(`Failed to upload commit bundle`, error);
180
- if (error instanceof conversation_1.MLSInvalidLeafNodeSignatureError || error instanceof conversation_1.MLSInvalidLeafNodeIndexError) {
181
- this.logger.info('Aborting commit bundle upload due to broken MLS conversation');
182
- return {
183
- abort: {
184
- reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({
185
- message: CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.BROKEN_MLS_CONVERSATION,
186
- }),
187
- },
188
- };
135
+ if (error instanceof http_1.BackendError && error.code === http_1.StatusCode.CONFLICT && regenerateCommitBundle) {
136
+ return this.conflictBackoffQueue.add(async () => this._uploadCommitBundle(groupId, regenerateCommitBundle, isExternalCommit));
189
137
  }
190
- if (error instanceof conversation_1.MLSStaleMessageError) {
191
- this.logger.info('Aborting commit bundle upload due to stale MLS message');
192
- return {
193
- abort: {
194
- reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({ message: CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.MLS_STALE_MESSAGE }),
195
- },
196
- };
138
+ throw error;
139
+ }
140
+ };
141
+ _uploadCommitBundle = async (groupId, generateCommitBundle, isExternalCommit) => {
142
+ const groupIdStr = bazinga64_1.Encoder.toBase64(groupId).asString;
143
+ // We need to lock the incoming mls messages queue while we are uploading the commit bundle
144
+ // it's possible that we will be sent some mls messages before we receive the response from backend and accept a commit locally.
145
+ return (0, messageAdd_1.withLockedMLSMessagesQueue)(groupIdStr, async () => {
146
+ const { commit, groupInfo, welcome } = await generateCommitBundle();
147
+ const bundlePayload = new Uint8Array([...commit, ...groupInfo.payload, ...(welcome || [])]);
148
+ try {
149
+ const response = await this.apiClient.api.conversation.postMlsCommitBundle(bundlePayload);
150
+ if (isExternalCommit) {
151
+ await this.coreCryptoClient.mergePendingGroupFromExternalCommit(groupId);
152
+ }
153
+ else {
154
+ await this.coreCryptoClient.commitAccepted(groupId);
155
+ }
156
+ const newEpoch = await this.getEpoch(groupId);
157
+ this.emit('newEpoch', { epoch: newEpoch, groupId: groupIdStr });
158
+ return response;
197
159
  }
198
- if (error instanceof conversation_1.MLSGroupOutOfSyncError) {
199
- this.logger.info('Aborting commit bundle upload due to group out of sync');
200
- return {
201
- abort: {
202
- reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({
203
- message: CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.MLS_GROUP_OUT_OF_SYNC,
204
- missing_users: error.missing_users,
205
- }),
206
- },
207
- };
160
+ catch (error) {
161
+ if (isExternalCommit) {
162
+ await this.coreCryptoClient.clearPendingGroupFromExternalCommit(groupId);
163
+ }
164
+ else {
165
+ await this.coreCryptoClient.clearPendingCommit(groupId);
166
+ }
167
+ throw error;
208
168
  }
209
- this.logger.info('Aborting commit bundle upload due to unknown error');
210
- return {
211
- abort: {
212
- reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({
213
- message: error instanceof Error ? error.message : CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.OTHER,
214
- }),
215
- },
216
- };
217
- }
169
+ });
218
170
  };
219
171
  /**
220
172
  * Will add users to an existing MLS group and send a commit bundle to backend.
@@ -228,26 +180,25 @@ class MLSService extends commons_1.TypedEventEmitter {
228
180
  if (keyPackages.length < 1) {
229
181
  throw new Error('Empty list of keys provided to addUsersToExistingConversation');
230
182
  }
231
- const crlNewDistributionPoints = await this.coreCryptoClient.transaction(cx => cx.addClientsToConversation(new core_crypto_1.ConversationId(groupIdBytes), keyPackages));
232
- this.dispatchNewCrlDistributionPoints(crlNewDistributionPoints);
233
- }
234
- /**
235
- * Will return a list of client ids which are already in the group at core crypto level
236
- *
237
- * @param groupId - the group id of the MLS group
238
- * @returns list of client ids
239
- */
240
- async getClientIdsInGroup(groupId) {
241
- const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
242
- const currentClientIdsInGroup = [];
243
- for (const clientId of await this.coreCryptoClient.getClientIds(new core_crypto_1.ConversationId(groupIdBytes))) {
244
- // [user-id]:[client-id]@[domain] -> [client-id]
245
- // example: fb880fac-b549-4d8b-9398-4246324c7b85:67f41928e2844b6c@staging.zinfra.io -> 67f41928e2844b6c
246
- currentClientIdsInGroup.push(bazinga64_1.Converter.arrayBufferViewToStringUTF8(clientId.copyBytes()).split('@')[0].split(':')[1]);
247
- }
248
- return currentClientIdsInGroup;
183
+ //TODO: handle federation error when sending a commit bundle to backend like we do in ProteusService
184
+ const response = await this.processCommitAction(groupIdBytes, async () => {
185
+ const commitBundle = await this.coreCryptoClient.addClientsToConversation(groupIdBytes, keyPackages);
186
+ this.dispatchNewCrlDistributionPoints(commitBundle);
187
+ return commitBundle;
188
+ });
189
+ const failedUsers = response.failed;
190
+ const failures = failedUsers
191
+ ? [
192
+ {
193
+ users: failedUsers,
194
+ backends: failedUsers.map(({ domain }) => domain),
195
+ reason: conversation_1.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
196
+ },
197
+ ]
198
+ : [];
199
+ return { ...response, failures };
249
200
  }
250
- async getKeyPackagesPayload(qualifiedUsers, skipClientIds = []) {
201
+ async getKeyPackagesPayload(qualifiedUsers) {
251
202
  /**
252
203
  * @note We need to fetch key packages for all the users
253
204
  * we want to add to the new MLS conversations,
@@ -287,20 +238,18 @@ class MLSService extends commons_1.TypedEventEmitter {
287
238
  if (key_packages.length > 0) {
288
239
  return [
289
240
  ...previousValue,
290
- ...key_packages
291
- .filter(keyPackage => !skipClientIds.includes(keyPackage.client))
292
- .map(keyPackage => bazinga64_1.Decoder.fromBase64(keyPackage.key_package).asBytes),
241
+ ...key_packages.map(keyPackage => bazinga64_1.Decoder.fromBase64(keyPackage.key_package).asBytes),
293
242
  ];
294
243
  }
295
244
  return previousValue;
296
245
  }, []);
297
246
  const failures = [];
298
247
  if (emptyKeyPackagesUsers.length > 0) {
299
- failures.push({ reason: conversation_2.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG, users: emptyKeyPackagesUsers });
248
+ failures.push({ reason: conversation_1.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG, users: emptyKeyPackagesUsers });
300
249
  }
301
250
  if (failedToFetchKeyPackages.length > 0) {
302
251
  failures.push({
303
- reason: conversation_2.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
252
+ reason: conversation_1.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
304
253
  users: failedToFetchKeyPackages,
305
254
  backends: failedToFetchKeyPackages.map(({ domain }) => domain),
306
255
  });
@@ -309,98 +258,92 @@ class MLSService extends commons_1.TypedEventEmitter {
309
258
  }
310
259
  getEpoch(groupId) {
311
260
  const groupIdBytes = typeof groupId === 'string' ? bazinga64_1.Decoder.fromBase64(groupId).asBytes : groupId;
312
- return this.coreCryptoClient.conversationEpoch(new core_crypto_1.ConversationId(groupIdBytes));
261
+ return this.coreCryptoClient.conversationEpoch(groupIdBytes);
262
+ }
263
+ async newProposal(proposalType, args) {
264
+ return this.coreCryptoClient.newProposal(proposalType, args);
313
265
  }
314
266
  async joinByExternalCommit(getGroupInfo) {
315
- try {
316
- this.logger.info('Trying to join MLS group via external commit');
317
- const credentialType = await this.getCredentialType();
267
+ const credentialType = await this.getCredentialType();
268
+ const generateCommit = async () => {
318
269
  const groupInfo = await getGroupInfo();
319
- const welcomeBundle = await this.coreCryptoClient.transaction(cx => cx.joinByExternalCommit(new core_crypto_1.GroupInfo(groupInfo), credentialType));
320
- await this.dispatchNewCrlDistributionPoints(welcomeBundle.crlNewDistributionPoints);
321
- this.logger.info('welcome bundle after joining via external commit');
322
- if (welcomeBundle.id) {
323
- //after we've successfully joined via external commit, we schedule periodic key material renewal
324
- const groupIdStr = bazinga64_1.Encoder.toBase64(welcomeBundle.id.copyBytes()).asString;
325
- const newEpoch = await this.getEpoch(groupIdStr);
326
- // Schedule the next key material renewal
327
- await this.scheduleKeyMaterialRenewal(groupIdStr);
328
- // Notify subscribers about the new epoch
329
- this.emit(MLSServiceEvents.NEW_EPOCH, { groupId: groupIdStr, epoch: newEpoch });
330
- this.logger.info(`Joined MLS group with id ${groupIdStr} via external commit, new epoch: ${newEpoch}`);
331
- }
332
- }
333
- catch (error) {
334
- this.logger.warn('Failed to join MLS group via external commit', error);
335
- throw error;
270
+ const joinRequest = await this.coreCryptoClient.joinByExternalCommit(groupInfo, credentialType);
271
+ this.dispatchNewCrlDistributionPoints(joinRequest);
272
+ const { conversationId, ...commitBundle } = joinRequest;
273
+ return { groupId: conversationId, commitBundle };
274
+ };
275
+ const { commitBundle, groupId } = await generateCommit();
276
+ const mlsResponse = await this.uploadCommitBundle(groupId, commitBundle, {
277
+ isExternalCommit: true,
278
+ regenerateCommitBundle: async () => (await generateCommit()).commitBundle,
279
+ });
280
+ if (mlsResponse) {
281
+ //after we've successfully joined via external commit, we schedule periodic key material renewal
282
+ const groupIdStr = bazinga64_1.Encoder.toBase64(groupId).asString;
283
+ await this.scheduleKeyMaterialRenewal(groupIdStr);
336
284
  }
285
+ return mlsResponse;
337
286
  }
338
287
  async exportSecretKey(groupId, keyLength) {
339
288
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
340
- const key = await this.coreCryptoClient.exportSecretKey(new core_crypto_1.ConversationId(groupIdBytes), keyLength);
289
+ const key = await this.coreCryptoClient.exportSecretKey(groupIdBytes, keyLength);
341
290
  return bazinga64_1.Encoder.toBase64(key).asString;
342
291
  }
343
- dispatchNewCrlDistributionPoints(crlNewDistributionPoints) {
292
+ dispatchNewCrlDistributionPoints(payload) {
293
+ const { crlNewDistributionPoints } = payload;
344
294
  if (crlNewDistributionPoints && crlNewDistributionPoints.length > 0) {
345
- this.emit(MLSServiceEvents.NEW_CRL_DISTRIBUTION_POINTS, crlNewDistributionPoints);
295
+ this.emit('newCrlDistributionPoints', crlNewDistributionPoints);
346
296
  }
347
297
  }
348
298
  async processWelcomeMessage(welcomeMessage) {
349
- const welcomeBundle = await this.coreCryptoClient.transaction(cx => cx.processWelcomeMessage(new core_crypto_1.Welcome(welcomeMessage)));
350
- this.dispatchNewCrlDistributionPoints(welcomeBundle.crlNewDistributionPoints);
299
+ const welcomeBundle = await this.coreCryptoClient.processWelcomeMessage(welcomeMessage);
300
+ this.dispatchNewCrlDistributionPoints(welcomeBundle);
351
301
  return welcomeBundle.id;
352
302
  }
353
303
  async decryptMessage(conversationId, payload) {
354
- try {
355
- const start = Date.now();
356
- this.logger.info('Decrypting message', { conversationId });
357
- const decryptedMessage = await this.coreCryptoClient.transaction(cx => cx.decryptMessage(conversationId, payload));
358
- this.dispatchNewCrlDistributionPoints(decryptedMessage.crlNewDistributionPoints);
359
- this.logger.info('Message decrypted successfully', { conversationId, duration: Date.now() - start });
360
- return decryptedMessage;
361
- }
362
- catch (error) {
363
- this.logger.warn('Failed to decrypt MLS message', { conversationId, error });
364
- // According to CoreCrypto JS doc on .decryptMessage method, we should ignore some errors (corecrypto handle them internally)
365
- if ((0, CoreCryptoMLSError_1.shouldMLSDecryptionErrorBeIgnored)(error)) {
366
- return {
367
- hasEpochChanged: false,
368
- isActive: false,
369
- };
304
+ return await this.coreCryptoClient.transaction(async (cx) => {
305
+ try {
306
+ const decryptedMessage = await cx.decryptMessage(conversationId, payload);
307
+ this.dispatchNewCrlDistributionPoints(decryptedMessage);
308
+ return decryptedMessage;
370
309
  }
371
- throw error;
372
- }
310
+ catch (error) {
311
+ // According to CoreCrypto JS doc on .decryptMessage method, we should ignore some errors (corecrypto handle them internally)
312
+ if ((0, CoreCryptoMLSError_1.shouldMLSDecryptionErrorBeIgnored)(error)) {
313
+ return {
314
+ hasEpochChanged: false,
315
+ isActive: false,
316
+ proposals: [],
317
+ };
318
+ }
319
+ throw error;
320
+ }
321
+ });
373
322
  }
374
323
  async encryptMessage(conversationId, message) {
375
- return this.coreCryptoClient.transaction(cx => cx.encryptMessage(conversationId, message));
324
+ return this.coreCryptoClient.encryptMessage(conversationId, message);
376
325
  }
377
- async updateKeyingMaterial(groupId, retry = true) {
378
- try {
379
- const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
380
- await this.coreCryptoClient.transaction(cx => cx.updateKeyingMaterial(new core_crypto_1.ConversationId(groupIdBytes)));
381
- }
382
- catch (error) {
383
- if (!retry) {
384
- this.logger.error(`Failed to update keying material for group retrying did not fix the issue`, {
385
- error,
386
- groupId,
387
- });
388
- throw error;
389
- }
390
- this.logger.warn(`Failed to update keying material for group`, { error, groupId });
391
- this.emit(MLSServiceEvents.KEY_MATERIAL_UPDATE_FAILURE, { error, groupId });
392
- setTimeout(async () => {
393
- try {
394
- await this.updateKeyingMaterial(groupId, false);
395
- }
396
- catch (error) {
397
- this.logger.error(`Failed to update keying material for group on retry`, {
398
- error,
399
- groupId,
400
- });
401
- }
402
- }, commons_1.TimeUtil.TimeInMillis.SECOND * 10); // retry after 10 seconds
403
- }
326
+ /**
327
+ * Will wrap a coreCrypto call that generates a CommitBundle and do all the necessary work so that commitbundle is handled the right way.
328
+ * It does:
329
+ * - commit the pending proposal
330
+ * - then generates the commitBundle with the given function
331
+ * - uploads the commitBundle to backend
332
+ * - warns coreCrypto that the commit was successfully processed
333
+ * @param groupId
334
+ * @param generateCommit The function that will generate a coreCrypto CommitBundle
335
+ */
336
+ async processCommitAction(groupId, generateCommit) {
337
+ const groupIdStr = bazinga64_1.Encoder.toBase64(groupId).asString;
338
+ return (0, messageSender_1.sendMessage)(async () => {
339
+ await this.commitPendingProposals(groupIdStr);
340
+ const commitBundle = await generateCommit();
341
+ return this.uploadCommitBundle(groupId, commitBundle, { regenerateCommitBundle: generateCommit });
342
+ });
343
+ }
344
+ updateKeyingMaterial(groupId) {
345
+ const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
346
+ return this.processCommitAction(groupIdBytes, () => this.coreCryptoClient.updateKeyingMaterial(groupIdBytes));
404
347
  }
405
348
  /**
406
349
  * Will create an empty conversation inside of coreCrypto.
@@ -412,9 +355,7 @@ class MLSService extends commons_1.TypedEventEmitter {
412
355
  let externalSenders = [];
413
356
  if (parentGroupId) {
414
357
  const parentGroupIdBytes = bazinga64_1.Decoder.fromBase64(parentGroupId).asBytes;
415
- externalSenders = [
416
- new core_crypto_1.ExternalSenderKey(await this.coreCryptoClient.getExternalSender(new core_crypto_1.ConversationId(parentGroupIdBytes))),
417
- ];
358
+ externalSenders = [await this.coreCryptoClient.getExternalSender(parentGroupIdBytes)];
418
359
  }
419
360
  else {
420
361
  const mlsKeys = (await this.apiClient.api.client.getPublicKeys()).removal;
@@ -423,14 +364,14 @@ class MLSService extends commons_1.TypedEventEmitter {
423
364
  if (!removalKeyForSignature) {
424
365
  throw new Error(`Cannot create conversation: No backend removal key found for the signature ${ciphersuiteSignature}`);
425
366
  }
426
- externalSenders = [new core_crypto_1.ExternalSenderKey(bazinga64_1.Decoder.fromBase64(removalKeyForSignature).asBytes)];
367
+ externalSenders = [bazinga64_1.Decoder.fromBase64(removalKeyForSignature).asBytes];
427
368
  }
428
369
  const configuration = {
429
370
  externalSenders,
430
371
  ciphersuite: this.config.defaultCiphersuite,
431
372
  };
432
373
  const credentialType = await this.getCredentialType();
433
- return this.coreCryptoClient.transaction(cx => cx.createConversation(new core_crypto_1.ConversationId(groupIdBytes), credentialType, configuration));
374
+ return this.coreCryptoClient.createConversation(groupIdBytes, credentialType, configuration);
434
375
  }
435
376
  /**
436
377
  * Will create a conversation inside of coreCrypto, add users to it or update the keying material if empty key packages list is provided.
@@ -454,18 +395,19 @@ class MLSService extends commons_1.TypedEventEmitter {
454
395
  }));
455
396
  if (keyPackages.length <= 0) {
456
397
  // If there are no clients to add, just update the keying material
457
- await this.updateKeyingMaterial(groupId);
398
+ const response = await this.updateKeyingMaterial(groupId);
458
399
  await this.scheduleKeyMaterialRenewal(groupId);
459
- return keysClaimingFailures;
400
+ return { ...response, failures: keysClaimingFailures };
460
401
  }
461
- await this.addUsersToExistingConversation(groupId, keyPackages);
402
+ const response = await this.addUsersToExistingConversation(groupId, keyPackages);
462
403
  // We schedule a periodic key material renewal
463
404
  await this.scheduleKeyMaterialRenewal(groupId);
464
405
  /**
465
406
  * @note If we can't fetch a user's key packages then we can not add them to mls conversation
466
407
  * so we're adding them to the list of failed users.
467
408
  */
468
- return keysClaimingFailures;
409
+ response.failures = [...keysClaimingFailures, ...response.failures];
410
+ return response;
469
411
  }
470
412
  /**
471
413
  * Will create a 1:1 conversation inside of coreCrypto, try claiming key packages for user and (if succesfull) add them to the MLS group.
@@ -481,17 +423,21 @@ class MLSService extends commons_1.TypedEventEmitter {
481
423
  // If we're missing key packages for the user we want to add, we can't register the conversation
482
424
  if (otherUserKeyPackages.length <= 0) {
483
425
  if (otherUserKeysClaimingFailures.length > 0 &&
484
- otherUserKeysClaimingFailures.some(({ reason }) => reason === conversation_2.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG)) {
426
+ otherUserKeysClaimingFailures.some(({ reason }) => reason === conversation_1.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG)) {
485
427
  throw new ClientMLSError_1.ClientMLSError(ClientMLSError_1.ClientMLSErrorLabel.NO_KEY_PACKAGES_AVAILABLE);
486
428
  }
487
429
  }
488
430
  const { keyPackages: selfKeyPackages, failures: selfKeysClaimingFailures } = await this.getKeyPackagesPayload([
489
431
  { ...selfUser.user, skipOwnClientId: selfUser.client },
490
432
  ]);
491
- await this.addUsersToExistingConversation(groupId, [...otherUserKeyPackages, ...selfKeyPackages]);
433
+ const response = await this.addUsersToExistingConversation(groupId, [
434
+ ...otherUserKeyPackages,
435
+ ...selfKeyPackages,
436
+ ]);
492
437
  // We schedule a periodic key material renewal
493
438
  await this.scheduleKeyMaterialRenewal(groupId);
494
- return [...otherUserKeysClaimingFailures, ...selfKeysClaimingFailures];
439
+ response.failures = [...otherUserKeysClaimingFailures, ...selfKeysClaimingFailures, ...response.failures];
440
+ return response;
495
441
  }
496
442
  catch (error) {
497
443
  await this.wipeConversation(groupId);
@@ -518,7 +464,6 @@ class MLSService extends commons_1.TypedEventEmitter {
518
464
  return true;
519
465
  }
520
466
  catch (error) {
521
- this.logger.warn("Couldn't establish the MLS group", error);
522
467
  // If conversation already existed, locally, nothing more to do, we've received a welcome message.
523
468
  if ((0, CoreCryptoMLSError_1.isCoreCryptoMLSConversationAlreadyExistsError)(error)) {
524
469
  this.logger.debug(`MLS Group with id ${groupId} already exists, skipping the initialisation.`);
@@ -538,7 +483,7 @@ class MLSService extends commons_1.TypedEventEmitter {
538
483
  */
539
484
  removeClientsFromConversation(groupId, clientIds) {
540
485
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
541
- return this.coreCryptoClient.transaction(cx => cx.removeClientsFromConversation(new core_crypto_1.ConversationId(groupIdBytes), clientIds.map(id => new core_crypto_1.ClientId(this.textEncoder.encode(id)))));
486
+ return this.processCommitAction(groupIdBytes, () => this.coreCryptoClient.removeClientsFromConversation(groupIdBytes, clientIds.map(id => this.textEncoder.encode(id))));
542
487
  }
543
488
  /**
544
489
  * Will check if mls group exists in corecrypto.
@@ -546,7 +491,7 @@ class MLSService extends commons_1.TypedEventEmitter {
546
491
  */
547
492
  async conversationExists(groupId) {
548
493
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
549
- return this.coreCryptoClient.conversationExists(new core_crypto_1.ConversationId(groupIdBytes));
494
+ return this.coreCryptoClient.conversationExists(groupIdBytes);
550
495
  }
551
496
  /**
552
497
  * Will check if mls group is established in coreCrypto.
@@ -559,11 +504,11 @@ class MLSService extends commons_1.TypedEventEmitter {
559
504
  }
560
505
  async clientValidKeypackagesCount() {
561
506
  const credentialType = await this.getCredentialType();
562
- return this.coreCryptoClient.transaction(cx => cx.clientValidKeypackagesCount(this.config.defaultCiphersuite, credentialType));
507
+ return this.coreCryptoClient.clientValidKeypackagesCount(this.config.defaultCiphersuite, credentialType);
563
508
  }
564
509
  async clientKeypackages(amountRequested) {
565
510
  const credentialType = await this.getCredentialType();
566
- return this.coreCryptoClient.transaction(cx => cx.clientKeypackages(this.config.defaultCiphersuite, credentialType, amountRequested));
511
+ return this.coreCryptoClient.clientKeypackages(this.config.defaultCiphersuite, credentialType, amountRequested);
567
512
  }
568
513
  /**
569
514
  * Will send an empty commit into a group (renew key material)
@@ -665,14 +610,6 @@ class MLSService extends commons_1.TypedEventEmitter {
665
610
  async getRemoteMLSKeyPackageCount(clientId) {
666
611
  return this.apiClient.api.client.getMLSKeyPackageCount(clientId, (0, numberToHex_1.numberToHex)(this.config.defaultCiphersuite));
667
612
  }
668
- async getCCClientSignatureString() {
669
- const credentialType = await this.getCredentialType();
670
- const publicKey = await this.coreCryptoClient.clientPublicKey(this.config.defaultCiphersuite, credentialType);
671
- if (!publicKey) {
672
- throw new Error('No public key found for client');
673
- }
674
- return btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(publicKey));
675
- }
676
613
  /**
677
614
  * Will update the given client on backend with its public key.
678
615
  *
@@ -681,18 +618,13 @@ class MLSService extends commons_1.TypedEventEmitter {
681
618
  */
682
619
  async uploadMLSPublicKeys(client) {
683
620
  // If we've already updated a client with its public key, there's no need to do it again.
684
- try {
685
- const clientSignature = await this.getCCClientSignatureString();
686
- return this.apiClient.api.client.putClient(client.id, {
687
- mls_public_keys: {
688
- [(0, Helper_1.getSignatureAlgorithmForCiphersuite)(this.config.defaultCiphersuite)]: clientSignature,
689
- },
690
- });
691
- }
692
- catch (error) {
693
- this.logger.error(`Failed to upload public keys for client ${client.id}`, error);
694
- throw error;
695
- }
621
+ const credentialType = await this.getCredentialType();
622
+ const publicKey = await this.coreCryptoClient.clientPublicKey(this.config.defaultCiphersuite, credentialType);
623
+ return this.apiClient.api.client.putClient(client.id, {
624
+ mls_public_keys: {
625
+ [(0, Helper_1.getSignatureAlgorithmForCiphersuite)(this.config.defaultCiphersuite)]: btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(publicKey)),
626
+ },
627
+ });
696
628
  }
697
629
  async replaceKeyPackages(clientId, keyPackages) {
698
630
  return this.apiClient.api.client.replaceMLSKeyPackages(clientId, keyPackages.map(keyPackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keyPackage))), (0, numberToHex_1.numberToHex)(this.config.defaultCiphersuite));
@@ -701,6 +633,7 @@ class MLSService extends commons_1.TypedEventEmitter {
701
633
  return this.apiClient.api.client.uploadMLSKeyPackages(clientId, keyPackages.map(keyPackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keyPackage))));
702
634
  }
703
635
  async wipeConversation(groupId) {
636
+ (0, messageAdd_1.deleteMLSMessagesQueue)(groupId);
704
637
  await this.cancelKeyMaterialRenewal(groupId);
705
638
  await this.cancelPendingProposalsTask(groupId);
706
639
  const doesConversationExist = await this.conversationExists(groupId);
@@ -709,7 +642,7 @@ class MLSService extends commons_1.TypedEventEmitter {
709
642
  return;
710
643
  }
711
644
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
712
- return this.coreCryptoClient.transaction(cx => cx.wipeConversation(new core_crypto_1.ConversationId(groupIdBytes)));
645
+ return this.coreCryptoClient.wipeConversation(groupIdBytes);
713
646
  }
714
647
  /**
715
648
  * If there are pending proposals, we need to either process them,
@@ -749,29 +682,25 @@ class MLSService extends commons_1.TypedEventEmitter {
749
682
  *
750
683
  * @param groupId groupId of the conversation
751
684
  */
752
- async commitPendingProposals(groupId, shouldRetry = true, params) {
753
- this.logger.info(`Committing pending proposals for groupId ${groupId}`, { shouldRetry, params });
685
+ async commitPendingProposals(groupId, shouldRetry = true) {
754
686
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
755
687
  try {
756
- await this.coreCryptoClient.transaction(cx => cx.commitPendingProposals(new core_crypto_1.ConversationId(groupIdBytes)));
688
+ const commitBundle = await this.coreCryptoClient.commitPendingProposals(groupIdBytes);
689
+ if (commitBundle) {
690
+ await this.uploadCommitBundle(groupIdBytes, commitBundle);
691
+ }
757
692
  await this.cancelPendingProposalsTask(groupId);
758
693
  }
759
694
  catch (error) {
760
695
  if (!shouldRetry) {
761
696
  throw error;
762
697
  }
763
- if ((0, core_crypto_1.isMlsMessageRejectedError)(error)) {
764
- this.logger.warn('Failed to commit proposals, conversation is broken, letting the error bubble up', {
765
- error,
766
- groupId,
767
- });
768
- throw error;
769
- }
770
- this.logger.warn('Failed to commit proposals, clearing the pending commit and retrying', {
771
- error,
772
- groupId,
773
- shouldRetry,
774
- });
698
+ this.logger.warn('Failed to commit proposals, clearing the pending commit and retrying', error);
699
+ // If we failed to commit the proposals, we need to clear the pending commit and retry
700
+ // this is to avoid a situation where we are stuck with pending proposals that we can't commit.
701
+ // If there's nothing to clear the methods might throw an error, which we can ignore.
702
+ await this.coreCryptoClient.clearPendingCommit(groupIdBytes).catch(() => undefined);
703
+ await this.coreCryptoClient.clearPendingGroupFromExternalCommit(groupIdBytes).catch(() => undefined);
775
704
  return this.commitPendingProposals(groupId, false);
776
705
  }
777
706
  }
@@ -802,9 +731,9 @@ class MLSService extends commons_1.TypedEventEmitter {
802
731
  */
803
732
  async getClientIds(groupId) {
804
733
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
805
- const rawClientIds = await this.coreCryptoClient.getClientIds(new core_crypto_1.ConversationId(groupIdBytes));
734
+ const rawClientIds = await this.coreCryptoClient.getClientIds(groupIdBytes);
806
735
  const clientIds = rawClientIds.map(id => {
807
- const { user, client, domain } = (0, fullyQualifiedClientIdUtils_1.parseFullQualifiedClientId)(this.textDecoder.decode(id.copyBytes()));
736
+ const { user, client, domain } = (0, fullyQualifiedClientIdUtils_1.parseFullQualifiedClientId)(this.textDecoder.decode(id));
808
737
  return { userId: user, clientId: client, domain };
809
738
  });
810
739
  return clientIds;
@@ -816,7 +745,7 @@ class MLSService extends commons_1.TypedEventEmitter {
816
745
  if (!groupId) {
817
746
  throw new Error(`Could not find a group_id for conversation ${qualifiedConversationId.id}@${qualifiedConversationId.domain}${event.subconv ? `/subconversation:${event.subconv}` : ''}`);
818
747
  }
819
- return (0, events_1.handleMLSMessageAdd)({ event, mlsService: this, groupId });
748
+ return (0, messageAdd_1.queueIncomingMLSMessage)(groupId, () => (0, events_1.handleMLSMessageAdd)({ event, mlsService: this, groupId }));
820
749
  }
821
750
  async handleMLSWelcomeMessageEvent(event, clientId) {
822
751
  // Every time we've received a welcome message, it means that our key package was consumed,
@@ -840,20 +769,32 @@ class MLSService extends commons_1.TypedEventEmitter {
840
769
  * @param oAuthIdToken The OAuth id token if the user is already authenticated
841
770
  * @returns AcmeChallenge if the user is not authenticated, true if the user is authenticated
842
771
  */
843
- async enrollE2EI(discoveryUrl, user, client, nbPrekeys, certificateTtl, getOAuthToken, getAllConversations) {
772
+ async enrollE2EI(discoveryUrl, user, client, nbPrekeys, certificateTtl, getOAuthToken) {
844
773
  const isCertificateRenewal = await this.coreCryptoClient.e2eiIsEnabled(this.config.defaultCiphersuite);
845
774
  const e2eiServiceInternal = new E2EIServiceInternal_1.E2EIServiceInternal(this.coreDatabase, this.coreCryptoClient, this.apiClient, certificateTtl, nbPrekeys, { user, clientId: client.id, discoveryUrl });
846
- const { keyPackages, newCrlDistributionPoints } = await e2eiServiceInternal.generateCertificate(getOAuthToken, isCertificateRenewal, getAllConversations, this.config.defaultCiphersuite);
847
- this.dispatchNewCrlDistributionPoints(newCrlDistributionPoints);
775
+ const rotateBundle = await e2eiServiceInternal.generateCertificate(getOAuthToken, isCertificateRenewal, this.config.defaultCiphersuite);
776
+ this.dispatchNewCrlDistributionPoints(rotateBundle);
848
777
  // upload the clients public keys
849
778
  if (!this.isInitializedMLSClient(client)) {
850
779
  // we only upload public keys for the initial certification process if the device is not already a registered MLS device.
851
780
  await this.uploadMLSPublicKeys(client);
852
781
  }
853
782
  // replace old key packages with new key packages with x509 certificate
854
- await this.replaceKeyPackages(client.id, keyPackages);
783
+ await this.replaceKeyPackages(client.id, rotateBundle.newKeyPackages);
855
784
  // Verify that we have enough key packages
856
785
  await this.verifyRemoteMLSKeyPackagesAmount(client.id);
786
+ // Update keying material
787
+ for (const [groupId, commitBundle] of rotateBundle.commits) {
788
+ const groupIdAsBytes = bazinga64_1.Converter.hexStringToArrayBufferView(groupId);
789
+ // manual copy of the commit bundle data because of a problem while cloning it
790
+ const newCommitBundle = {
791
+ commit: commitBundle.commit,
792
+ // @ts-ignore
793
+ groupInfo: commitBundle?.group_info || commitBundle.groupInfo,
794
+ welcome: commitBundle?.welcome,
795
+ };
796
+ await this.uploadCommitBundle(groupIdAsBytes, newCommitBundle);
797
+ }
857
798
  }
858
799
  }
859
800
  exports.MLSService = MLSService;