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

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 +156 -51
  2. package/lib/Account.d.ts.map +1 -1
  3. package/lib/Account.js +503 -127
  4. package/lib/Account.test.js +158 -147
  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 +4 -3
  11. package/lib/client/ClientService.d.ts.map +1 -1
  12. package/lib/client/ClientService.js +19 -5
  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 +12 -30
  16. package/lib/conversation/AssetService/AssetService.d.ts.map +1 -1
  17. package/lib/conversation/AssetService/AssetService.js +1 -10
  18. package/lib/conversation/AssetService/AssetService.test.js +8 -3
  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 +98 -14
  23. package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
  24. package/lib/conversation/ConversationService/ConversationService.js +314 -101
  25. package/lib/conversation/ConversationService/ConversationService.test.js +441 -47
  26. package/lib/conversation/ConversationService/ConversationService.types.d.ts +5 -4
  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 +6 -3
  30. package/lib/conversation/SubconversationService/SubconversationService.d.ts.map +1 -1
  31. package/lib/conversation/SubconversationService/SubconversationService.js +158 -11
  32. package/lib/conversation/SubconversationService/SubconversationService.test.js +8 -2
  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 +7 -1
  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 +9 -0
  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 +2 -1
  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 +13 -11
  86. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.test.js +21 -16
  87. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts +9 -3
  88. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts.map +1 -1
  89. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.js +31 -12
  90. package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts +6 -0
  91. package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts.map +1 -1
  92. package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.js +19 -1
  93. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts +7 -0
  94. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts.map +1 -0
  95. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.js +48 -0
  96. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/index.d.ts +2 -0
  97. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingMessagesQueue → IncomingProposalsQueue}/index.d.ts.map +1 -1
  98. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingMessagesQueue → IncomingProposalsQueue}/index.js +1 -1
  99. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts +0 -1
  100. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts.map +1 -1
  101. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.js +0 -1
  102. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts.map +1 -1
  103. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.js +23 -14
  104. package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.d.ts.map +1 -1
  105. package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.js +5 -2
  106. package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.test.js +13 -3
  107. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts +38 -2
  108. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts.map +1 -1
  109. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.js +41 -6
  110. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts +2 -0
  111. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts.map +1 -0
  112. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.js +124 -0
  113. package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +38 -34
  114. package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
  115. package/lib/messagingProtocols/mls/MLSService/MLSService.js +267 -208
  116. package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +157 -160
  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/recovery/MlsErrorMapper.d.ts +78 -0
  121. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.d.ts.map +1 -0
  122. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.js +173 -0
  123. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts +2 -0
  124. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts.map +1 -0
  125. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.js +117 -0
  126. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts +167 -0
  127. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts.map +1 -0
  128. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.js +317 -0
  129. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts +2 -0
  130. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts.map +1 -0
  131. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.js +248 -0
  132. package/lib/messagingProtocols/mls/recovery/index.d.ts +5 -0
  133. package/lib/messagingProtocols/mls/recovery/index.d.ts.map +1 -0
  134. package/lib/messagingProtocols/mls/recovery/index.js +28 -0
  135. package/lib/messagingProtocols/mls/types.d.ts +0 -8
  136. package/lib/messagingProtocols/mls/types.d.ts.map +1 -1
  137. package/lib/messagingProtocols/proteus/EventHandler/events/otrMessageAdd/otrMessageAdd.d.ts.map +1 -1
  138. package/lib/messagingProtocols/proteus/EventHandler/events/otrMessageAdd/otrMessageAdd.js +7 -1
  139. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts +8 -15
  140. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts.map +1 -1
  141. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.js +97 -62
  142. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts +0 -6
  143. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts.map +1 -1
  144. package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts +1 -6
  145. package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts.map +1 -1
  146. package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.js +19 -22
  147. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts +5 -3
  148. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts.map +1 -1
  149. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.js +11 -24
  150. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts +1 -0
  151. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts.map +1 -1
  152. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.js +11 -2
  153. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.test.js +13 -9
  154. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts +3 -2
  155. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts.map +1 -1
  156. package/lib/messagingProtocols/proteus/ProteusService/WithMockedGenerics.test.js +11 -4
  157. package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts +0 -4
  158. package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts.map +1 -1
  159. package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.js +0 -5
  160. package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts +2 -1
  161. package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts.map +1 -1
  162. package/lib/messagingProtocols/proteus/ProteusService/identityClearer.js +8 -2
  163. package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.test.js +4 -0
  164. package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts +1 -1
  165. package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts.map +1 -1
  166. package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.js +1 -1
  167. package/lib/notification/NotificationService.d.ts +20 -6
  168. package/lib/notification/NotificationService.d.ts.map +1 -1
  169. package/lib/notification/NotificationService.js +23 -14
  170. package/lib/notification/NotificationService.test.js +8 -0
  171. package/lib/secretStore/secretKeyGenerator.d.ts +1 -0
  172. package/lib/secretStore/secretKeyGenerator.d.ts.map +1 -1
  173. package/lib/secretStore/secretKeyGenerator.js +3 -1
  174. package/lib/self/SelfService.d.ts +2 -2
  175. package/lib/self/SelfService.d.ts.map +1 -1
  176. package/lib/self/SelfService.test.js +5 -2
  177. package/lib/team/TeamService.d.ts +5 -2
  178. package/lib/team/TeamService.d.ts.map +1 -1
  179. package/lib/team/TeamService.js +12 -2
  180. package/lib/test/StoreHelper.d.ts +2 -0
  181. package/lib/test/StoreHelper.d.ts.map +1 -0
  182. package/lib/test/StoreHelper.js +27 -0
  183. package/lib/user/UserService.d.ts +2 -2
  184. package/lib/user/UserService.d.ts.map +1 -1
  185. package/lib/user/UserService.js +3 -3
  186. package/lib/util/TypePredicateUtil.d.ts.map +1 -1
  187. package/lib/util/TypePredicateUtil.js +2 -2
  188. package/package.json +3 -3
  189. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts +0 -4
  190. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts.map +0 -1
  191. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.js +0 -69
  192. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/index.d.ts +0 -2
  193. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts +0 -2
  194. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts.map +0 -1
  195. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.js +0 -98
@@ -17,6 +17,29 @@
17
17
  * along with this program. If not, see http://www.gnu.org/licenses/.
18
18
  *
19
19
  */
20
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ var desc = Object.getOwnPropertyDescriptor(m, k);
23
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
24
+ desc = { enumerable: true, get: function() { return m[k]; } };
25
+ }
26
+ Object.defineProperty(o, k2, desc);
27
+ }) : (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ o[k2] = m[k];
30
+ }));
31
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
32
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
33
+ }) : function(o, v) {
34
+ o["default"] = v;
35
+ });
36
+ var __importStar = (this && this.__importStar) || function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
20
43
  Object.defineProperty(exports, "__esModule", { value: true });
21
44
  const client_1 = require("@wireapp/api-client/lib/client");
22
45
  const event_1 = require("@wireapp/api-client/lib/event");
@@ -31,6 +54,11 @@ const conversation_1 = require("../../../conversation");
31
54
  const CoreDB_1 = require("../../../storage/CoreDB");
32
55
  const RecurringTaskScheduler_1 = require("../../../util/RecurringTaskScheduler");
33
56
  const TaskScheduler_1 = require("../../../util/TaskScheduler");
57
+ const Helper = __importStar(require("../E2EIdentityService/Helper"));
58
+ jest.mock('../E2EIdentityService/Helper', () => ({
59
+ ...jest.requireActual('../E2EIdentityService/Helper'),
60
+ getMLSDeviceStatus: jest.fn(),
61
+ }));
34
62
  jest.createMockFromModule('@wireapp/api-client');
35
63
  function createUserId() {
36
64
  return { id: (0, crypto_1.randomUUID)(), domain: '' };
@@ -39,25 +67,36 @@ const defaultMLSInitConfig = {
39
67
  ciphersuites: [core_crypto_1.Ciphersuite.MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519],
40
68
  defaultCiphersuite: core_crypto_1.Ciphersuite.MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519,
41
69
  };
70
+ // Needs to be divisible by 4 to be a valid base64 string
71
+ const mockGroupId = 'Z3JvdXAtdGVzdC0x';
72
+ const mockedMLSWelcomeEventData = '';
73
+ const apiClients = [];
42
74
  const createMLSService = async () => {
43
75
  const apiClient = new api_client_1.APIClient();
44
- const mockCoreCrypto = {
45
- createConversation: jest.fn(),
46
- conversationExists: jest.fn(),
76
+ apiClients.push(apiClient);
77
+ const transactionContext = {
78
+ mlsInit: jest.fn(),
47
79
  wipeConversation: jest.fn(),
48
- clientValidKeypackagesCount: jest.fn(),
49
80
  clientKeypackages: jest.fn(),
50
- mlsInit: jest.fn(),
51
- clientPublicKey: jest.fn(),
81
+ createConversation: jest.fn(),
82
+ clientValidKeypackagesCount: jest.fn(),
83
+ conversationExists: jest.fn(),
52
84
  processWelcomeMessage: jest.fn(),
53
- conversationEpoch: jest.fn(),
54
85
  commitPendingProposals: jest.fn(),
55
- registerCallbacks: jest.fn(),
86
+ decryptMessage: jest.fn(),
87
+ updateKeyingMaterial: jest.fn(),
88
+ };
89
+ const mockCoreCrypto = {
90
+ transaction: jest.fn(fn => {
91
+ return fn(transactionContext);
92
+ }),
93
+ registerEpochObserver: jest.fn(),
94
+ provideTransport: jest.fn(),
95
+ version: jest.fn(),
96
+ conversationExists: jest.fn(),
56
97
  e2eiIsEnabled: jest.fn(() => false),
57
- clearPendingGroupFromExternalCommit: async () => { },
58
- clearPendingCommit: async () => { },
59
- commitAccepted: jest.fn(),
60
- transaction: jest.fn(),
98
+ clientPublicKey: jest.fn(),
99
+ conversationEpoch: jest.fn(),
61
100
  };
62
101
  const mockedDb = await (0, CoreDB_1.openDB)('core-test-db');
63
102
  const recurringTaskScheduler = new RecurringTaskScheduler_1.RecurringTaskScheduler({
@@ -69,9 +108,15 @@ const createMLSService = async () => {
69
108
  });
70
109
  const mlsService = new MLSService_1.MLSService(apiClient, mockCoreCrypto, mockedDb, recurringTaskScheduler);
71
110
  mlsService['_config'] = { ...defaultMLSInitConfig, nbKeyPackages: 100, keyingMaterialUpdateThreshold: 1 };
72
- return [mlsService, { apiClient, coreCrypto: mockCoreCrypto, recurringTaskScheduler }];
111
+ return [mlsService, { apiClient, coreCrypto: mockCoreCrypto, recurringTaskScheduler, transactionContext }];
73
112
  };
113
+ afterAll(() => {
114
+ jest.clearAllTimers();
115
+ });
74
116
  describe('MLSService', () => {
117
+ afterAll(() => {
118
+ apiClients.forEach(client => client.disconnect());
119
+ });
75
120
  describe('registerConversation', () => {
76
121
  let mlsService;
77
122
  let apiClient;
@@ -84,12 +129,6 @@ describe('MLSService', () => {
84
129
  .mockResolvedValue({ removal: { ed25519: 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=' } });
85
130
  jest.spyOn(apiClient.api.client, 'claimMLSKeyPackages').mockResolvedValue({ key_packages: [] });
86
131
  jest.spyOn(mlsService, 'scheduleKeyMaterialRenewal').mockImplementation();
87
- jest.spyOn(mlsService, 'processCommitAction').mockImplementation(() => ({
88
- failed_to_send: [],
89
- failed: [],
90
- events: [],
91
- time: '',
92
- }));
93
132
  jest.spyOn(mlsService, 'cancelKeyMaterialRenewal').mockImplementation();
94
133
  });
95
134
  it('creates a new mls conversation and avoid adding the selfUser', async () => {
@@ -117,37 +156,10 @@ describe('MLSService', () => {
117
156
  keyPackages: [],
118
157
  failures: [failure],
119
158
  });
120
- const { failures } = await mlsService.registerConversation(groupId, [...users, selfUser], { creator });
159
+ const failures = await mlsService.registerConversation(groupId, [...users, selfUser], { creator });
121
160
  expect(failures).toEqual([failure]);
122
161
  expect(mlsService.scheduleKeyMaterialRenewal).toHaveBeenCalledWith(groupId);
123
162
  });
124
- it("returns a list of failure reasons if it was not possible to upload users' keys", async () => {
125
- const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
126
- const selfUser = createUserId();
127
- const creator = { user: selfUser, client: 'client-1' };
128
- const users = [createUserId(), createUserId()];
129
- const failureKeysClaiming = {
130
- reason: conversation_1.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG,
131
- users: [users[0]],
132
- };
133
- const failureKeysUpload = {
134
- reason: conversation_1.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
135
- users: [users[1]],
136
- backends: [users[1].domain],
137
- };
138
- jest.spyOn(mlsService, 'getKeyPackagesPayload').mockResolvedValueOnce({
139
- keyPackages: [new Uint8Array()],
140
- failures: [failureKeysClaiming],
141
- });
142
- jest.spyOn(mlsService, 'addUsersToExistingConversation').mockResolvedValueOnce({
143
- failures: [failureKeysUpload],
144
- events: [],
145
- time: '',
146
- });
147
- const { failures } = await mlsService.registerConversation(groupId, [...users, selfUser], { creator });
148
- expect(failures).toEqual([failureKeysClaiming, failureKeysUpload]);
149
- expect(mlsService.scheduleKeyMaterialRenewal).toHaveBeenCalledWith(groupId);
150
- });
151
163
  });
152
164
  describe('getKeyPackagesPayload', () => {
153
165
  it('succesfully claims keys for all users', async () => {
@@ -182,24 +194,24 @@ describe('MLSService', () => {
182
194
  });
183
195
  describe('isConversationEstablished', () => {
184
196
  it('returns false if conversation does not exist locally', async () => {
185
- const [mlsService] = await createMLSService();
197
+ const [mlsService, { coreCrypto }] = await createMLSService();
186
198
  const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
187
- jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
199
+ jest.spyOn(coreCrypto, 'conversationExists').mockResolvedValueOnce(false);
188
200
  const isEstablshed = await mlsService.isConversationEstablished(groupId);
189
201
  expect(isEstablshed).toBe(false);
190
202
  });
191
203
  it('returns false if epoch number is 0', async () => {
192
- const [mlsService] = await createMLSService();
204
+ const [mlsService, { coreCrypto }] = await createMLSService();
193
205
  const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
194
- jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
206
+ jest.spyOn(coreCrypto, 'conversationExists').mockResolvedValueOnce(true);
195
207
  jest.spyOn(mlsService, 'getEpoch').mockResolvedValueOnce(0);
196
208
  const isEstablshed = await mlsService.isConversationEstablished(groupId);
197
209
  expect(isEstablshed).toBe(false);
198
210
  });
199
211
  it.each([1, 2, 100])('returns false if epoch number is 1 or more', async (epoch) => {
200
- const [mlsService] = await createMLSService();
212
+ const [mlsService, { coreCrypto }] = await createMLSService();
201
213
  const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
202
- jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
214
+ jest.spyOn(coreCrypto, 'conversationExists').mockResolvedValueOnce(true);
203
215
  jest.spyOn(mlsService, 'getEpoch').mockResolvedValueOnce(epoch);
204
216
  const isEstablshed = await mlsService.isConversationEstablished(groupId);
205
217
  expect(isEstablshed).toBe(true);
@@ -269,7 +281,7 @@ describe('MLSService', () => {
269
281
  });
270
282
  describe('initClient', () => {
271
283
  it('uses the default config if config is not provided by the consumer', async () => {
272
- const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
284
+ const [mlsService, { apiClient, coreCrypto, transactionContext }] = await createMLSService();
273
285
  const mockUserId = { id: 'user-1', domain: 'local.zinfra.io' };
274
286
  const mockClientId = 'client-1';
275
287
  const mockClient = { mls_public_keys: {}, id: mockClientId };
@@ -280,11 +292,11 @@ describe('MLSService', () => {
280
292
  jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(mlsService.config.nbKeyPackages);
281
293
  const config = { ...defaultMLSInitConfig };
282
294
  await mlsService.initClient(mockUserId, mockClient, config);
283
- expect(coreCrypto.mlsInit).toHaveBeenCalledWith(expect.any(Uint8Array), [core_crypto_1.Ciphersuite.MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519], 100);
295
+ expect(transactionContext.mlsInit).toHaveBeenCalledWith(expect.any(core_crypto_1.ClientId), [core_crypto_1.Ciphersuite.MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519], 100);
284
296
  expect(mlsService.config.nbKeyPackages).toEqual(100);
285
297
  });
286
298
  it('uses the config provided by the consumer', async () => {
287
- const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
299
+ const [mlsService, { apiClient, transactionContext, coreCrypto }] = await createMLSService();
288
300
  const mockUserId = { id: 'user-1', domain: 'local.zinfra.io' };
289
301
  const mockClientId = 'client-1';
290
302
  const mockClient = { mls_public_keys: {}, id: mockClientId };
@@ -295,11 +307,11 @@ describe('MLSService', () => {
295
307
  jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(mlsService.config.nbKeyPackages);
296
308
  const config = { ...defaultMLSInitConfig, nbKeyPackages: 40, keyingMaterialUpdateThreshold: TimeUtil_1.TimeInMillis.DAY };
297
309
  await mlsService.initClient(mockUserId, mockClient, config);
298
- expect(coreCrypto.mlsInit).toHaveBeenCalledWith(expect.any(Uint8Array), [core_crypto_1.Ciphersuite.MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519], config.nbKeyPackages);
310
+ expect(transactionContext.mlsInit).toHaveBeenCalledWith(expect.any(core_crypto_1.ClientId), [core_crypto_1.Ciphersuite.MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519], config.nbKeyPackages);
299
311
  expect(mlsService.config).toEqual(config);
300
312
  });
301
313
  it('uses the default config value when provided with undefined by the consumer', async () => {
302
- const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
314
+ const [mlsService, { apiClient, transactionContext, coreCrypto }] = await createMLSService();
303
315
  const mockUserId = { id: 'user-1', domain: 'local.zinfra.io' };
304
316
  const mockClientId = 'client-1';
305
317
  const mockClient = { mls_public_keys: {}, id: mockClientId };
@@ -314,41 +326,43 @@ describe('MLSService', () => {
314
326
  keyingMaterialUpdateThreshold: TimeUtil_1.TimeInMillis.DAY,
315
327
  };
316
328
  await mlsService.initClient(mockUserId, mockClient, config);
317
- expect(coreCrypto.mlsInit).toHaveBeenCalledWith(expect.any(Uint8Array), [core_crypto_1.Ciphersuite.MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519], 100);
329
+ expect(transactionContext.mlsInit).toHaveBeenCalledWith(expect.any(core_crypto_1.ClientId), [core_crypto_1.Ciphersuite.MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519], 100);
318
330
  expect(mlsService.config).toEqual({ ...config, nbKeyPackages: 100 });
319
331
  });
320
332
  it('uploads public key only if it was not yet defined on client entity', async () => {
321
- const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
333
+ const [mlsService, { apiClient, transactionContext, coreCrypto }] = await createMLSService();
322
334
  const mockUserId = { id: 'user-1', domain: 'local.zinfra.io' };
323
335
  const mockClientId = 'client-1';
324
336
  const mockClient = { mls_public_keys: {}, id: mockClientId };
325
337
  apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
326
- const mockedClientPublicKey = new Uint8Array();
327
- jest.spyOn(coreCrypto, 'clientPublicKey').mockResolvedValueOnce(mockedClientPublicKey);
328
338
  jest.spyOn(apiClient.api.client, 'putClient').mockResolvedValueOnce(undefined);
329
339
  jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(mlsService.config.nbKeyPackages);
340
+ jest.spyOn(Helper, 'getMLSDeviceStatus').mockReturnValueOnce(Helper.MLSDeviceStatus.FRESH);
341
+ jest.spyOn(coreCrypto, 'clientPublicKey').mockResolvedValue(new Uint8Array());
330
342
  await mlsService.initClient(mockUserId, mockClient, defaultMLSInitConfig);
331
- expect(coreCrypto.mlsInit).toHaveBeenCalled();
343
+ expect(transactionContext.mlsInit).toHaveBeenCalled();
332
344
  expect(apiClient.api.client.putClient).toHaveBeenCalledWith(mockClientId, expect.anything());
333
345
  });
334
346
  it('uploads key packages if there are not enough keys on backend', async () => {
335
- const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
347
+ const [mlsService, { apiClient, transactionContext, coreCrypto }] = await createMLSService();
336
348
  const mockUserId = { id: 'user-1', domain: 'local.zinfra.io' };
337
349
  const mockClientId = 'client-1';
338
350
  const mockClient = { mls_public_keys: { ed25519: 'key' }, id: mockClientId };
339
351
  apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
340
352
  const mockedClientKeyPackages = [new Uint8Array()];
341
- jest.spyOn(coreCrypto, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
353
+ jest.spyOn(transactionContext, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
354
+ jest.spyOn(coreCrypto, 'clientPublicKey').mockResolvedValueOnce(new Uint8Array());
355
+ jest.spyOn(Helper, 'getMLSDeviceStatus').mockReturnValueOnce(Helper.MLSDeviceStatus.REGISTERED);
356
+ jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages').mockResolvedValueOnce(undefined);
342
357
  jest
343
358
  .spyOn(apiClient.api.client, 'getMLSKeyPackageCount')
344
359
  .mockResolvedValueOnce(mlsService['minRequiredKeyPackages'] - 1);
345
- jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages').mockResolvedValueOnce(undefined);
346
360
  await mlsService.initClient(mockUserId, mockClient, defaultMLSInitConfig);
347
- expect(coreCrypto.mlsInit).toHaveBeenCalled();
361
+ expect(transactionContext.mlsInit).toHaveBeenCalled();
348
362
  expect(apiClient.api.client.uploadMLSKeyPackages).toHaveBeenCalledWith(mockClientId, expect.anything());
349
363
  });
350
364
  it('does not upload public key or key packages if both are already uploaded', async () => {
351
- const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
365
+ const [mlsService, { apiClient, transactionContext, coreCrypto }] = await createMLSService();
352
366
  const mockUserId = { id: 'user-1', domain: 'local.zinfra.io' };
353
367
  const mockClientId = 'client-1';
354
368
  const mockClient = { mls_public_keys: { ed25519: 'key' }, id: mockClientId };
@@ -357,95 +371,64 @@ describe('MLSService', () => {
357
371
  jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(mlsService.config.nbKeyPackages);
358
372
  jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages');
359
373
  jest.spyOn(apiClient.api.client, 'putClient');
374
+ jest.spyOn(coreCrypto, 'clientPublicKey').mockResolvedValueOnce(new Uint8Array());
360
375
  await mlsService.initClient(mockUserId, mockClient, defaultMLSInitConfig);
361
- expect(coreCrypto.mlsInit).toHaveBeenCalled();
376
+ expect(transactionContext.mlsInit).toHaveBeenCalled();
362
377
  expect(apiClient.api.client.uploadMLSKeyPackages).not.toHaveBeenCalled();
363
378
  expect(apiClient.api.client.putClient).not.toHaveBeenCalled();
364
379
  });
365
380
  });
366
381
  describe('wipeConversation', () => {
367
382
  it('wipes a group and cancels its timers', async () => {
368
- const [mlsService, { coreCrypto, recurringTaskScheduler }] = await createMLSService();
383
+ const [mlsService, { recurringTaskScheduler, coreCrypto, transactionContext }] = await createMLSService();
369
384
  const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm4OQFc=';
370
- jest.spyOn(coreCrypto, 'conversationExists').mockResolvedValueOnce(true);
385
+ coreCrypto.conversationExists = jest.fn().mockResolvedValue(true);
386
+ transactionContext.wipeConversation = jest.fn().mockResolvedValue(undefined);
371
387
  jest.spyOn(recurringTaskScheduler, 'cancelTask');
372
388
  jest.spyOn(TaskScheduler_1.TaskScheduler, 'cancelTask');
373
389
  await mlsService.wipeConversation(groupId);
374
390
  expect(recurringTaskScheduler.cancelTask).toHaveBeenCalledWith(expect.stringContaining(groupId));
375
391
  expect(TaskScheduler_1.TaskScheduler.cancelTask).toHaveBeenCalledWith(expect.stringContaining(groupId));
376
- expect(coreCrypto.wipeConversation).toHaveBeenCalled();
392
+ expect(transactionContext.wipeConversation).toHaveBeenCalled();
377
393
  });
378
394
  it('does not try to wipe a group if it does not exist already', async () => {
379
- const [mlsService, { coreCrypto, recurringTaskScheduler }] = await createMLSService();
395
+ const [mlsService, { recurringTaskScheduler, transactionContext, coreCrypto }] = await createMLSService();
380
396
  const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm4OQFc=';
381
- jest.spyOn(coreCrypto, 'conversationExists').mockResolvedValueOnce(false);
397
+ coreCrypto.conversationExists = jest.fn().mockResolvedValue(false);
398
+ transactionContext.wipeConversation = jest.fn().mockResolvedValue(undefined);
382
399
  jest.spyOn(recurringTaskScheduler, 'cancelTask');
383
400
  jest.spyOn(TaskScheduler_1.TaskScheduler, 'cancelTask');
384
401
  await mlsService.wipeConversation(groupId);
385
402
  expect(recurringTaskScheduler.cancelTask).toHaveBeenCalledWith(expect.stringContaining(groupId));
386
403
  expect(TaskScheduler_1.TaskScheduler.cancelTask).toHaveBeenCalledWith(expect.stringContaining(groupId));
387
- expect(coreCrypto.wipeConversation).not.toHaveBeenCalled();
388
- });
389
- });
390
- describe('commitPendingProposals', () => {
391
- it('commits pending proposals and uploads received commit bundle to backend', async () => {
392
- const [mlsService, { coreCrypto: mockCoreCrypto, apiClient }] = await createMLSService();
393
- const mockGroupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
394
- jest.spyOn(mockCoreCrypto, 'commitPendingProposals').mockResolvedValueOnce({
395
- commit: new Uint8Array(),
396
- groupInfo: { payload: new Uint8Array() },
397
- });
398
- jest.spyOn(apiClient.api.conversation, 'postMlsCommitBundle').mockResolvedValueOnce({ events: [], time: '' });
399
- await mlsService.commitPendingProposals(mockGroupId);
400
- expect(mockCoreCrypto.commitPendingProposals).toHaveBeenCalled();
401
- expect(apiClient.api.conversation.postMlsCommitBundle).toHaveBeenCalled();
402
- });
403
- it('clears pending commit and retries when failed committing pending proposals', async () => {
404
- const [mlsService, { coreCrypto: mockCoreCrypto, apiClient }] = await createMLSService();
405
- const mockGroupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
406
- jest.spyOn(mockCoreCrypto, 'commitPendingProposals').mockRejectedValueOnce(new Error('mocked error'));
407
- jest.spyOn(mockCoreCrypto, 'commitPendingProposals').mockResolvedValueOnce({
408
- commit: new Uint8Array(),
409
- groupInfo: { payload: new Uint8Array() },
410
- });
411
- jest.spyOn(apiClient.api.conversation, 'postMlsCommitBundle').mockResolvedValueOnce({ events: [], time: '' });
412
- jest.spyOn(mockCoreCrypto, 'clearPendingCommit');
413
- jest.spyOn(mockCoreCrypto, 'clearPendingGroupFromExternalCommit');
414
- await mlsService.commitPendingProposals(mockGroupId);
415
- expect(mockCoreCrypto.clearPendingCommit).toHaveBeenCalledTimes(1);
416
- expect(mockCoreCrypto.clearPendingGroupFromExternalCommit).toHaveBeenCalledTimes(1);
417
- expect(mockCoreCrypto.commitPendingProposals).toHaveBeenCalledTimes(2);
418
- expect(apiClient.api.conversation.postMlsCommitBundle).toHaveBeenCalledTimes(1);
404
+ expect(transactionContext.wipeConversation).not.toHaveBeenCalled();
419
405
  });
420
406
  });
421
407
  describe('handleMLSMessageAddEvent', () => {
422
- it('decrypts a message and emits new epoch event if epoch has changed', async () => {
423
- const [mlsService, { coreCrypto: mockCoreCrypto }] = await createMLSService();
408
+ it('decrypts a message', async () => {
409
+ const [mlsService, { transactionContext, coreCrypto }] = await createMLSService();
424
410
  const mockGroupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
425
411
  const mockedNewEpoch = 3;
426
412
  const getGroupIdFromConversationId = () => Promise.resolve(mockGroupId);
427
413
  const mockedDecryptoedMessage = {
428
414
  hasEpochChanged: true,
429
415
  isActive: false,
430
- proposals: [],
431
416
  };
432
- jest.spyOn(mockCoreCrypto, 'transaction').mockResolvedValueOnce(mockedDecryptoedMessage);
433
- jest.spyOn(mockCoreCrypto, 'conversationEpoch').mockResolvedValueOnce(mockedNewEpoch);
434
- jest.spyOn(mlsService, 'emit').mockImplementation(jest.fn());
417
+ jest.spyOn(transactionContext, 'decryptMessage').mockResolvedValueOnce(mockedDecryptoedMessage);
418
+ jest.spyOn(coreCrypto, 'conversationEpoch').mockResolvedValueOnce(mockedNewEpoch);
435
419
  const mockedMLSWelcomeEvent = {
436
420
  type: event_1.CONVERSATION_EVENT.MLS_MESSAGE_ADD,
437
421
  senderClientId: '',
438
422
  conversation: '',
439
- data: '',
423
+ data: mockedMLSWelcomeEventData,
440
424
  from: '',
441
425
  time: '',
442
426
  };
443
427
  await mlsService.handleMLSMessageAddEvent(mockedMLSWelcomeEvent, getGroupIdFromConversationId);
444
- expect(mockCoreCrypto.transaction).toHaveBeenCalled();
445
- expect(mlsService.emit).toHaveBeenCalledWith('newEpoch', { epoch: mockedNewEpoch, groupId: mockGroupId });
428
+ expect(transactionContext.decryptMessage).toHaveBeenCalled();
446
429
  });
447
430
  it('handles pending propoals with a delay after decrypting a message', async () => {
448
- const [mlsService, { coreCrypto: mockCoreCrypto }] = await createMLSService();
431
+ const [mlsService, { transactionContext, coreCrypto }] = await createMLSService();
449
432
  jest.useFakeTimers();
450
433
  const mockGroupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
451
434
  const mockedNewEpoch = 3;
@@ -454,122 +437,138 @@ describe('MLSService', () => {
454
437
  const mockedDecryptoedMessage = {
455
438
  hasEpochChanged: true,
456
439
  isActive: false,
457
- proposals: [],
458
440
  commitDelay,
459
441
  };
460
- jest.spyOn(mockCoreCrypto, 'transaction').mockResolvedValueOnce(mockedDecryptoedMessage);
461
- jest.spyOn(mockCoreCrypto, 'conversationEpoch').mockResolvedValueOnce(mockedNewEpoch);
442
+ jest.spyOn(transactionContext, 'decryptMessage').mockResolvedValueOnce(mockedDecryptoedMessage);
443
+ jest.spyOn(coreCrypto, 'conversationEpoch').mockResolvedValueOnce(mockedNewEpoch);
462
444
  jest.spyOn(mlsService, 'commitPendingProposals');
463
445
  const mockedMLSWelcomeEvent = {
464
446
  type: event_1.CONVERSATION_EVENT.MLS_MESSAGE_ADD,
465
447
  senderClientId: '',
466
448
  conversation: '',
467
- data: '',
449
+ data: mockedMLSWelcomeEventData,
468
450
  from: '',
469
451
  time: new Date().toISOString(),
470
452
  };
471
453
  await mlsService.handleMLSMessageAddEvent(mockedMLSWelcomeEvent, getGroupIdFromConversationId);
472
- expect(mockCoreCrypto.commitPendingProposals).not.toHaveBeenCalled();
473
454
  jest.advanceTimersByTime(commitDelay);
474
- expect(mockCoreCrypto.transaction).toHaveBeenCalled();
475
- expect(mockCoreCrypto.commitPendingProposals).toHaveBeenCalled();
455
+ expect(transactionContext.decryptMessage).toHaveBeenCalled();
456
+ });
457
+ it('Throws if decryption fails', async () => {
458
+ const [mlsService, { transactionContext }] = await createMLSService();
459
+ const mockGroupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
460
+ const getGroupIdFromConversationId = () => Promise.resolve(mockGroupId);
461
+ jest
462
+ .spyOn(transactionContext, 'decryptMessage')
463
+ .mockRejectedValueOnce(new Error(CoreCryptoMLSError_1.CORE_CRYPTO_ERROR_NAMES.MlsErrorWrongEpoch));
464
+ const mockedMLSMessageAddEvent = {
465
+ type: event_1.CONVERSATION_EVENT.MLS_MESSAGE_ADD,
466
+ senderClientId: '',
467
+ conversation: '',
468
+ data: mockedMLSWelcomeEventData,
469
+ from: '',
470
+ time: '',
471
+ };
472
+ await expect(mlsService.handleMLSMessageAddEvent(mockedMLSMessageAddEvent, getGroupIdFromConversationId)).rejects.toThrow(CoreCryptoMLSError_1.CORE_CRYPTO_ERROR_NAMES.MlsErrorWrongEpoch);
473
+ expect(transactionContext.decryptMessage).toHaveBeenCalled();
476
474
  });
477
475
  });
478
476
  describe('handleMLSWelcomeMessageEvent', () => {
479
477
  it("before processing welcome it verifies that there's enough key packages locally", async () => {
480
- const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
478
+ const [mlsService, { apiClient, transactionContext }] = await createMLSService();
481
479
  const mockClientId = 'client-1';
482
480
  const mockClient = { mls_public_keys: { ed25519: 'key' }, id: mockClientId };
483
481
  apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
484
482
  const mockedClientKeyPackages = [new Uint8Array()];
485
- jest.spyOn(coreCrypto, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
483
+ jest.spyOn(transactionContext, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
486
484
  const numberOfKeysBelowThreshold = mlsService['minRequiredKeyPackages'] - 1;
487
485
  jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(numberOfKeysBelowThreshold);
488
- jest.spyOn(coreCrypto, 'clientValidKeypackagesCount').mockResolvedValueOnce(numberOfKeysBelowThreshold);
486
+ jest.spyOn(transactionContext, 'clientValidKeypackagesCount').mockResolvedValue(numberOfKeysBelowThreshold);
489
487
  jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages').mockResolvedValueOnce(undefined);
490
- jest
491
- .spyOn(coreCrypto, 'processWelcomeMessage')
492
- .mockResolvedValueOnce({ id: new Uint8Array(), crlNewDistributionPoints: [] });
488
+ jest.spyOn(transactionContext, 'processWelcomeMessage').mockResolvedValue({
489
+ id: new core_crypto_1.ConversationId(new Uint8Array()),
490
+ crlNewDistributionPoints: [],
491
+ });
493
492
  jest.spyOn(mlsService, 'scheduleKeyMaterialRenewal').mockImplementation(jest.fn());
494
493
  const mockedMLSWelcomeEvent = {
495
494
  type: event_1.CONVERSATION_EVENT.MLS_WELCOME_MESSAGE,
496
495
  conversation: '',
497
- data: '',
496
+ data: mockedMLSWelcomeEventData,
498
497
  from: '',
499
498
  time: '',
500
499
  };
501
500
  await mlsService.handleMLSWelcomeMessageEvent(mockedMLSWelcomeEvent, mockClient.id);
502
- expect(coreCrypto.processWelcomeMessage).toHaveBeenCalled();
501
+ expect(transactionContext.processWelcomeMessage).toHaveBeenCalled();
503
502
  expect(apiClient.api.client.uploadMLSKeyPackages).toHaveBeenCalledWith(mockClientId, expect.anything());
504
503
  });
505
504
  it('before processing welcome it does not generate new keys if there is enough key packages locally', async () => {
506
- const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
505
+ const [mlsService, { apiClient, transactionContext }] = await createMLSService();
507
506
  const mockClientId = 'client-1';
508
507
  const mockClient = { mls_public_keys: { ed25519: 'key' }, id: mockClientId };
509
508
  apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
510
509
  const mockedClientKeyPackages = [new Uint8Array()];
511
- jest.spyOn(coreCrypto, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
510
+ jest.spyOn(transactionContext, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
512
511
  const numberOfKeysAboveThreshold = mlsService['minRequiredKeyPackages'] + 1;
513
- jest.spyOn(coreCrypto, 'clientValidKeypackagesCount').mockResolvedValueOnce(numberOfKeysAboveThreshold);
512
+ jest.spyOn(transactionContext, 'clientValidKeypackagesCount').mockResolvedValue(numberOfKeysAboveThreshold);
514
513
  jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(numberOfKeysAboveThreshold);
515
514
  jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages').mockResolvedValueOnce(undefined);
516
- jest
517
- .spyOn(coreCrypto, 'processWelcomeMessage')
518
- .mockResolvedValueOnce({ id: new Uint8Array(), crlNewDistributionPoints: [] });
515
+ jest.spyOn(transactionContext, 'processWelcomeMessage').mockResolvedValue({
516
+ id: new core_crypto_1.ConversationId(new Uint8Array()),
517
+ crlNewDistributionPoints: [],
518
+ });
519
519
  jest.spyOn(mlsService, 'scheduleKeyMaterialRenewal').mockImplementation(jest.fn());
520
520
  const mockedMLSWelcomeEvent = {
521
521
  type: event_1.CONVERSATION_EVENT.MLS_WELCOME_MESSAGE,
522
522
  conversation: '',
523
- data: '',
523
+ data: mockedMLSWelcomeEventData,
524
524
  from: '',
525
525
  time: '',
526
526
  };
527
527
  await mlsService.handleMLSWelcomeMessageEvent(mockedMLSWelcomeEvent, mockClient.id);
528
- expect(coreCrypto.processWelcomeMessage).toHaveBeenCalled();
528
+ expect(transactionContext.processWelcomeMessage).toHaveBeenCalled();
529
529
  expect(apiClient.api.client.uploadMLSKeyPackages).not.toHaveBeenCalled();
530
530
  });
531
531
  it('before processing welcome it does not generate new keys if there is enough key packages uploaded to backend', async () => {
532
- const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
532
+ const [mlsService, { apiClient, transactionContext }] = await createMLSService();
533
533
  const mockClientId = 'client-1';
534
534
  const mockClient = { mls_public_keys: { ed25519: 'key' }, id: mockClientId };
535
535
  apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
536
536
  const mockedClientKeyPackages = [new Uint8Array()];
537
- jest.spyOn(coreCrypto, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
537
+ jest.spyOn(transactionContext, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
538
538
  const numberOfKeysBelowThreshold = mlsService['minRequiredKeyPackages'] - 1;
539
539
  const numberOfKeysAboveThreshold = mlsService['minRequiredKeyPackages'] + 1;
540
- jest.spyOn(coreCrypto, 'clientValidKeypackagesCount').mockResolvedValueOnce(numberOfKeysBelowThreshold);
540
+ jest.spyOn(transactionContext, 'clientValidKeypackagesCount').mockResolvedValue(numberOfKeysBelowThreshold);
541
541
  jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(numberOfKeysAboveThreshold);
542
542
  jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages').mockResolvedValueOnce(undefined);
543
- jest
544
- .spyOn(coreCrypto, 'processWelcomeMessage')
545
- .mockResolvedValueOnce({ id: new Uint8Array(), crlNewDistributionPoints: [] });
543
+ jest.spyOn(transactionContext, 'processWelcomeMessage').mockResolvedValue({
544
+ id: new core_crypto_1.ConversationId(new Uint8Array()),
545
+ crlNewDistributionPoints: [],
546
+ });
546
547
  jest.spyOn(mlsService, 'scheduleKeyMaterialRenewal').mockImplementation(jest.fn());
547
548
  const mockedMLSWelcomeEvent = {
548
549
  type: event_1.CONVERSATION_EVENT.MLS_WELCOME_MESSAGE,
549
550
  conversation: '',
550
- data: '',
551
+ data: mockedMLSWelcomeEventData,
551
552
  from: '',
552
553
  time: '',
553
554
  };
554
555
  await mlsService.handleMLSWelcomeMessageEvent(mockedMLSWelcomeEvent, mockClient.id);
555
- expect(coreCrypto.processWelcomeMessage).toHaveBeenCalled();
556
+ expect(transactionContext.processWelcomeMessage).toHaveBeenCalled();
556
557
  expect(apiClient.api.client.uploadMLSKeyPackages).not.toHaveBeenCalled();
557
558
  });
558
559
  });
559
560
  describe('tryEstablishingMLSGroup', () => {
560
561
  it('returns false if group did already exist locally', async () => {
561
- const [mlsService] = await createMLSService();
562
- const mockGroupId = 'mock-group-id';
563
- jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
562
+ const [mlsService, { coreCrypto }] = await createMLSService();
563
+ jest.spyOn(coreCrypto, 'conversationExists').mockResolvedValueOnce(true);
564
564
  jest.spyOn(mlsService, 'registerConversation').mockImplementation(jest.fn());
565
565
  const wasConversationEstablished = await mlsService.tryEstablishingMLSGroup(mockGroupId);
566
566
  expect(mlsService.registerConversation).not.toHaveBeenCalled();
567
567
  expect(wasConversationEstablished).toBe(false);
568
568
  });
569
569
  it('returns false if corecrypto has thrown an error when trying to register group locally', async () => {
570
- const [mlsService] = await createMLSService();
571
- const mockGroupId = 'mock-group-id';
572
- jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
570
+ const [mlsService, { coreCrypto }] = await createMLSService();
571
+ jest.spyOn(coreCrypto, 'conversationExists').mockResolvedValueOnce(false);
573
572
  const conversationAlreadyExistsError = new Error();
574
573
  conversationAlreadyExistsError.name = CoreCryptoMLSError_1.CORE_CRYPTO_ERROR_NAMES.MlsErrorConversationAlreadyExists;
575
574
  jest.spyOn(mlsService, 'registerConversation').mockRejectedValueOnce(conversationAlreadyExistsError);
@@ -578,9 +577,8 @@ describe('MLSService', () => {
578
577
  expect(wasConversationEstablished).toBe(false);
579
578
  });
580
579
  it('returns false and wipes group locally if any backend error was thrown', async () => {
581
- const [mlsService] = await createMLSService();
582
- const mockGroupId = 'mock-group-id2';
583
- jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
580
+ const [mlsService, { transactionContext }] = await createMLSService();
581
+ jest.spyOn(transactionContext, 'conversationExists').mockResolvedValueOnce(false);
584
582
  jest
585
583
  .spyOn(mlsService, 'registerConversation')
586
584
  .mockRejectedValueOnce(new http_1.BackendError('', http_1.BackendErrorLabel.MLS_STALE_MESSAGE, http_1.StatusCode.CONFLICT));
@@ -591,10 +589,9 @@ describe('MLSService', () => {
591
589
  expect(wasConversationEstablished).toBe(false);
592
590
  });
593
591
  it('returns true after MLS group was etablished successfully', async () => {
594
- const [mlsService] = await createMLSService();
595
- const mockGroupId = 'mock-group-id2';
596
- jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
597
- jest.spyOn(mlsService, 'registerConversation').mockResolvedValueOnce({ events: [], time: '', failures: [] });
592
+ const [mlsService, { transactionContext }] = await createMLSService();
593
+ jest.spyOn(transactionContext, 'conversationExists').mockResolvedValueOnce(false);
594
+ jest.spyOn(mlsService, 'registerConversation').mockResolvedValueOnce([]);
598
595
  jest.spyOn(mlsService, 'wipeConversation').mockImplementation(jest.fn());
599
596
  const wasConversationEstablished = await mlsService.tryEstablishingMLSGroup(mockGroupId);
600
597
  expect(mlsService.registerConversation).toHaveBeenCalledWith(mockGroupId, []);
@@ -19,7 +19,7 @@
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.toProtobufCommitBundle = toProtobufCommitBundle;
22
- const mls_1 = require("@pydio/protocol-messaging/web/mls");
22
+ const mls_1 = require("@wireapp/protocol-messaging/web/mls");
23
23
  const core_crypto_1 = require("@wireapp/core-crypto");
24
24
  const ratchetTreeMapping = {
25
25
  [core_crypto_1.RatchetTreeType.Full]: mls_1.mls.RatchetTreeType.FULL,
@@ -40,10 +40,10 @@ function toProtobufCommitBundle({ commit, welcome, groupInfo }) {
40
40
  return mls_1.mls.CommitBundle.encode({
41
41
  groupInfoBundle: {
42
42
  ratchetTreeType: ratchetTreeMapping[ratchetTreeType],
43
- groupInfo: groupInfo.payload,
43
+ groupInfo: groupInfo.payload.copyBytes(),
44
44
  groupInfoType: groupInfoType[encryptionType],
45
45
  },
46
46
  commit,
47
- welcome,
47
+ welcome: welcome?.copyBytes(),
48
48
  }).finish();
49
49
  }