@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.
- package/lib/Account.d.ts +156 -51
- package/lib/Account.d.ts.map +1 -1
- package/lib/Account.js +503 -127
- package/lib/Account.test.js +158 -147
- package/lib/broadcast/AvailabilityType.d.ts +1 -1
- package/lib/broadcast/AvailabilityType.d.ts.map +1 -1
- package/lib/broadcast/BroadcastService.d.ts +1 -1
- package/lib/broadcast/BroadcastService.d.ts.map +1 -1
- package/lib/broadcast/BroadcastService.js +1 -1
- package/lib/client/ClientService.d.ts +4 -3
- package/lib/client/ClientService.d.ts.map +1 -1
- package/lib/client/ClientService.js +19 -5
- package/lib/conversation/AbortReason.d.ts +1 -1
- package/lib/conversation/AbortReason.d.ts.map +1 -1
- package/lib/conversation/AssetService/AssetService.d.ts +12 -30
- package/lib/conversation/AssetService/AssetService.d.ts.map +1 -1
- package/lib/conversation/AssetService/AssetService.js +1 -10
- package/lib/conversation/AssetService/AssetService.test.js +8 -3
- package/lib/conversation/ClientActionType.d.ts +1 -1
- package/lib/conversation/ClientActionType.d.ts.map +1 -1
- package/lib/conversation/ClientActionType.js +1 -1
- package/lib/conversation/ConversationService/ConversationService.d.ts +98 -14
- package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
- package/lib/conversation/ConversationService/ConversationService.js +314 -101
- package/lib/conversation/ConversationService/ConversationService.test.js +441 -47
- package/lib/conversation/ConversationService/ConversationService.types.d.ts +5 -4
- package/lib/conversation/ConversationService/ConversationService.types.d.ts.map +1 -1
- package/lib/conversation/ConversationService/Utility/getConversationQualifiedMembers.d.ts.map +1 -1
- package/lib/conversation/ConversationService/Utility/getConversationQualifiedMembers.js +6 -3
- package/lib/conversation/SubconversationService/SubconversationService.d.ts.map +1 -1
- package/lib/conversation/SubconversationService/SubconversationService.js +158 -11
- package/lib/conversation/SubconversationService/SubconversationService.test.js +8 -2
- package/lib/conversation/content/AssetContent.d.ts +1 -1
- package/lib/conversation/content/AssetContent.d.ts.map +1 -1
- package/lib/conversation/content/ButtonActionConfirmationContent.d.ts +1 -1
- package/lib/conversation/content/ButtonActionConfirmationContent.d.ts.map +1 -1
- package/lib/conversation/content/ButtonActionContent.d.ts +1 -1
- package/lib/conversation/content/ButtonActionContent.d.ts.map +1 -1
- package/lib/conversation/content/ClearedContent.d.ts +1 -1
- package/lib/conversation/content/ClearedContent.d.ts.map +1 -1
- package/lib/conversation/content/ClientActionContent.d.ts +1 -1
- package/lib/conversation/content/ClientActionContent.d.ts.map +1 -1
- package/lib/conversation/content/CompositeContent.d.ts +1 -1
- package/lib/conversation/content/CompositeContent.d.ts.map +1 -1
- package/lib/conversation/content/ConfirmationContent.d.ts +1 -1
- package/lib/conversation/content/ConfirmationContent.d.ts.map +1 -1
- package/lib/conversation/content/DeletedContent.d.ts +1 -1
- package/lib/conversation/content/DeletedContent.d.ts.map +1 -1
- package/lib/conversation/content/HiddenContent.d.ts +1 -1
- package/lib/conversation/content/HiddenContent.d.ts.map +1 -1
- package/lib/conversation/content/KnockContent.d.ts +1 -1
- package/lib/conversation/content/KnockContent.d.ts.map +1 -1
- package/lib/conversation/content/LinkPreviewContent.d.ts +1 -1
- package/lib/conversation/content/LinkPreviewContent.d.ts.map +1 -1
- package/lib/conversation/content/MentionContent.d.ts +1 -1
- package/lib/conversation/content/MentionContent.d.ts.map +1 -1
- package/lib/conversation/content/MultipartContent.d.ts +1 -1
- package/lib/conversation/content/MultipartContent.d.ts.map +1 -1
- package/lib/conversation/content/QuoteContent.d.ts +1 -1
- package/lib/conversation/content/QuoteContent.d.ts.map +1 -1
- package/lib/conversation/content/TweetContent.d.ts +1 -1
- package/lib/conversation/content/TweetContent.d.ts.map +1 -1
- package/lib/conversation/content/index.d.ts +1 -1
- package/lib/conversation/content/index.d.ts.map +1 -1
- package/lib/conversation/content/index.js +1 -1
- package/lib/conversation/message/MessageBuilder.d.ts +1 -1
- package/lib/conversation/message/MessageBuilder.d.ts.map +1 -1
- package/lib/conversation/message/MessageBuilder.js +1 -1
- package/lib/conversation/message/MessageService.d.ts.map +1 -1
- package/lib/conversation/message/MessageService.js +1 -1
- package/lib/conversation/message/MessageService.test.js +7 -1
- package/lib/conversation/message/MessageToProtoMapper.d.ts +1 -1
- package/lib/conversation/message/MessageToProtoMapper.d.ts.map +1 -1
- package/lib/conversation/message/MessageToProtoMapper.js +1 -1
- package/lib/conversation/message/messageSender.js +2 -2
- package/lib/cryptography/AssetCryptography/EncryptedAsset.d.ts +2 -2
- package/lib/cryptography/AssetCryptography/EncryptedAsset.d.ts.map +1 -1
- package/lib/messagingProtocols/common.types.d.ts +9 -0
- package/lib/messagingProtocols/common.types.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.d.ts +2 -2
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.js +2 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.d.ts +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.js +13 -11
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.test.js +21 -16
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts +9 -3
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.js +31 -12
- package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts +6 -0
- package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.js +19 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts +7 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.js +48 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/index.d.ts +2 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingMessagesQueue → IncomingProposalsQueue}/index.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingMessagesQueue → IncomingProposalsQueue}/index.js +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts +0 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.js +0 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.js +23 -14
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.js +5 -2
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.test.js +13 -3
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts +38 -2
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.js +41 -6
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts +2 -0
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.js +124 -0
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +38 -34
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.js +267 -208
- package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +157 -160
- package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.js +3 -3
- package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.test.js +5 -5
- package/lib/messagingProtocols/mls/conversationRejoinQueue.js +2 -2
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.d.ts +78 -0
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.js +173 -0
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts +2 -0
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.js +117 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts +167 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.js +317 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts +2 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.js +248 -0
- package/lib/messagingProtocols/mls/recovery/index.d.ts +5 -0
- package/lib/messagingProtocols/mls/recovery/index.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/recovery/index.js +28 -0
- package/lib/messagingProtocols/mls/types.d.ts +0 -8
- package/lib/messagingProtocols/mls/types.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/EventHandler/events/otrMessageAdd/otrMessageAdd.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/EventHandler/events/otrMessageAdd/otrMessageAdd.js +7 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts +8 -15
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.js +97 -62
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts +0 -6
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts +1 -6
- package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.js +19 -22
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts +5 -3
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.js +11 -24
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts +1 -0
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.js +11 -2
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.test.js +13 -9
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts +3 -2
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/WithMockedGenerics.test.js +11 -4
- package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts +0 -4
- package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.js +0 -5
- package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts +2 -1
- package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/identityClearer.js +8 -2
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.test.js +4 -0
- package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts +1 -1
- package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.js +1 -1
- package/lib/notification/NotificationService.d.ts +20 -6
- package/lib/notification/NotificationService.d.ts.map +1 -1
- package/lib/notification/NotificationService.js +23 -14
- package/lib/notification/NotificationService.test.js +8 -0
- package/lib/secretStore/secretKeyGenerator.d.ts +1 -0
- package/lib/secretStore/secretKeyGenerator.d.ts.map +1 -1
- package/lib/secretStore/secretKeyGenerator.js +3 -1
- package/lib/self/SelfService.d.ts +2 -2
- package/lib/self/SelfService.d.ts.map +1 -1
- package/lib/self/SelfService.test.js +5 -2
- package/lib/team/TeamService.d.ts +5 -2
- package/lib/team/TeamService.d.ts.map +1 -1
- package/lib/team/TeamService.js +12 -2
- package/lib/test/StoreHelper.d.ts +2 -0
- package/lib/test/StoreHelper.d.ts.map +1 -0
- package/lib/test/StoreHelper.js +27 -0
- package/lib/user/UserService.d.ts +2 -2
- package/lib/user/UserService.d.ts.map +1 -1
- package/lib/user/UserService.js +3 -3
- package/lib/util/TypePredicateUtil.d.ts.map +1 -1
- package/lib/util/TypePredicateUtil.js +2 -2
- package/package.json +3 -3
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts +0 -4
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.js +0 -69
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/index.d.ts +0 -2
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts +0 -2
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts.map +0 -1
- 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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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
|
-
|
|
58
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
383
|
+
const [mlsService, { recurringTaskScheduler, coreCrypto, transactionContext }] = await createMLSService();
|
|
369
384
|
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm4OQFc=';
|
|
370
|
-
jest.
|
|
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(
|
|
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, {
|
|
395
|
+
const [mlsService, { recurringTaskScheduler, transactionContext, coreCrypto }] = await createMLSService();
|
|
380
396
|
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm4OQFc=';
|
|
381
|
-
jest.
|
|
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(
|
|
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
|
|
423
|
-
const [mlsService, { coreCrypto
|
|
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(
|
|
433
|
-
jest.spyOn(
|
|
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(
|
|
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
|
|
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(
|
|
461
|
-
jest.spyOn(
|
|
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(
|
|
475
|
-
|
|
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,
|
|
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(
|
|
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(
|
|
486
|
+
jest.spyOn(transactionContext, 'clientValidKeypackagesCount').mockResolvedValue(numberOfKeysBelowThreshold);
|
|
489
487
|
jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages').mockResolvedValueOnce(undefined);
|
|
490
|
-
jest
|
|
491
|
-
.
|
|
492
|
-
|
|
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(
|
|
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,
|
|
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(
|
|
510
|
+
jest.spyOn(transactionContext, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
|
|
512
511
|
const numberOfKeysAboveThreshold = mlsService['minRequiredKeyPackages'] + 1;
|
|
513
|
-
jest.spyOn(
|
|
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
|
-
.
|
|
518
|
-
|
|
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(
|
|
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,
|
|
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(
|
|
537
|
+
jest.spyOn(transactionContext, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
|
|
538
538
|
const numberOfKeysBelowThreshold = mlsService['minRequiredKeyPackages'] - 1;
|
|
539
539
|
const numberOfKeysAboveThreshold = mlsService['minRequiredKeyPackages'] + 1;
|
|
540
|
-
jest.spyOn(
|
|
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
|
-
.
|
|
545
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
596
|
-
jest.spyOn(mlsService, '
|
|
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("@
|
|
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
|
}
|