@wireapp/core 42.19.0 → 42.19.2
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 +7 -3
- package/lib/Account.d.ts.map +1 -1
- package/lib/Account.js +15 -6
- package/lib/conversation/ConversationService/ConversationService.d.ts +3 -2
- package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
- package/lib/conversation/ConversationService/ConversationService.js +3 -2
- package/lib/conversation/ConversationService/ConversationService.test.js +2 -1
- package/lib/conversation/SubconversationService/SubconversationService.d.ts +71 -0
- package/lib/conversation/SubconversationService/SubconversationService.d.ts.map +1 -0
- package/lib/conversation/SubconversationService/SubconversationService.js +221 -0
- package/lib/conversation/SubconversationService/SubconversationService.test.d.ts +2 -0
- package/lib/conversation/SubconversationService/SubconversationService.test.d.ts.map +1 -0
- package/lib/conversation/SubconversationService/SubconversationService.test.js +374 -0
- package/lib/conversation/SubconversationService/subconversationUtil.d.ts +4 -0
- package/lib/conversation/SubconversationService/subconversationUtil.d.ts.map +1 -0
- package/lib/conversation/SubconversationService/subconversationUtil.js +25 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts +4 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.js +2 -2
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.js +8 -8
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +2 -36
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.js +8 -94
- package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +5 -4
- package/lib/messagingProtocols/mls/types.d.ts +2 -3
- package/lib/messagingProtocols/mls/types.d.ts.map +1 -1
- package/lib/storage/CoreDB.d.ts +10 -0
- package/lib/storage/CoreDB.d.ts.map +1 -1
- package/lib/storage/CoreDB.js +3 -1
- package/package.json +3 -3
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.d.ts +0 -13
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.js +0 -67
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.test.d.ts +0 -2
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.test.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.test.js +0 -72
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Wire
|
|
4
|
+
* Copyright (C) 2023 Wire Swiss GmbH
|
|
5
|
+
*
|
|
6
|
+
* This program is free software: you can redistribute it and/or modify
|
|
7
|
+
* it under the terms of the GNU General Public License as published by
|
|
8
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
* (at your option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
* GNU General Public License for more details.
|
|
15
|
+
*
|
|
16
|
+
* You should have received a copy of the GNU General Public License
|
|
17
|
+
* along with this program. If not, see http://www.gnu.org/licenses/.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const conversation_1 = require("@wireapp/api-client/lib/conversation");
|
|
22
|
+
const http_1 = require("@wireapp/api-client/lib/http");
|
|
23
|
+
const api_client_1 = require("@wireapp/api-client");
|
|
24
|
+
const SubconversationService_1 = require("./SubconversationService");
|
|
25
|
+
const CoreDB_1 = require("../../storage/CoreDB");
|
|
26
|
+
const fullyQualifiedClientIdUtils_1 = require("../../util/fullyQualifiedClientIdUtils");
|
|
27
|
+
const getSubconversationResponse = ({ epoch, epochTimestamp, parentConversationId, groupId, members = [], subconversationId = conversation_1.SUBCONVERSATION_ID.CONFERENCE, }) => {
|
|
28
|
+
return {
|
|
29
|
+
cipher_suite: 1,
|
|
30
|
+
epoch,
|
|
31
|
+
parent_qualified_id: parentConversationId,
|
|
32
|
+
group_id: groupId,
|
|
33
|
+
members,
|
|
34
|
+
subconv_id: subconversationId,
|
|
35
|
+
epoch_timestamp: epochTimestamp,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const buildSubconversationService = async () => {
|
|
39
|
+
const apiClient = new api_client_1.APIClient({ urls: api_client_1.APIClient.BACKEND.STAGING });
|
|
40
|
+
const mlsService = {
|
|
41
|
+
conversationExists: jest.fn(),
|
|
42
|
+
wipeConversation: jest.fn(),
|
|
43
|
+
registerConversation: jest.fn(),
|
|
44
|
+
getEpoch: jest.fn(),
|
|
45
|
+
joinByExternalCommit: jest.fn(),
|
|
46
|
+
getGroupIdFromConversationId: jest.fn(),
|
|
47
|
+
exportSecretKey: jest.fn(),
|
|
48
|
+
getClientIds: jest.fn(),
|
|
49
|
+
renewKeyMaterial: jest.fn(),
|
|
50
|
+
on: jest.fn(),
|
|
51
|
+
off: jest.fn(),
|
|
52
|
+
removeClientsFromConversation: jest.fn(),
|
|
53
|
+
};
|
|
54
|
+
const coreDatabase = await (0, CoreDB_1.openDB)('core-test-db');
|
|
55
|
+
const subconversationService = new SubconversationService_1.SubconversationService(apiClient, coreDatabase, mlsService);
|
|
56
|
+
return [subconversationService, { apiClient, mlsService, coreDatabase }];
|
|
57
|
+
};
|
|
58
|
+
describe('SubconversationService', () => {
|
|
59
|
+
describe('joinConferenceSubconversation', () => {
|
|
60
|
+
afterEach(() => {
|
|
61
|
+
jest.useRealTimers();
|
|
62
|
+
jest.clearAllMocks();
|
|
63
|
+
});
|
|
64
|
+
it('wipes group locally (if it exists) before registering a group if remote epoch is equal 0', async () => {
|
|
65
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
66
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
67
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
68
|
+
const subconversationResponse = getSubconversationResponse({
|
|
69
|
+
epoch: 0,
|
|
70
|
+
epochTimestamp: '',
|
|
71
|
+
parentConversationId,
|
|
72
|
+
groupId: subconversationGroupId,
|
|
73
|
+
subconversationId: conversation_1.SUBCONVERSATION_ID.CONFERENCE,
|
|
74
|
+
});
|
|
75
|
+
jest.spyOn(apiClient.api.conversation, 'getSubconversation').mockResolvedValueOnce(subconversationResponse);
|
|
76
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
|
|
77
|
+
await subconversationService.joinConferenceSubconversation(parentConversationId);
|
|
78
|
+
expect(mlsService.wipeConversation).toHaveBeenCalledWith(subconversationGroupId);
|
|
79
|
+
expect(mlsService.registerConversation).toHaveBeenCalledWith(subconversationGroupId, []);
|
|
80
|
+
});
|
|
81
|
+
it('registers a group if remote epoch is 0 and group does not exist locally', async () => {
|
|
82
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
83
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
84
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
85
|
+
const subconversationResponse = getSubconversationResponse({
|
|
86
|
+
epoch: 0,
|
|
87
|
+
epochTimestamp: '',
|
|
88
|
+
parentConversationId,
|
|
89
|
+
groupId: subconversationGroupId,
|
|
90
|
+
subconversationId: conversation_1.SUBCONVERSATION_ID.CONFERENCE,
|
|
91
|
+
});
|
|
92
|
+
jest.spyOn(apiClient.api.conversation, 'getSubconversation').mockResolvedValueOnce(subconversationResponse);
|
|
93
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
|
|
94
|
+
await subconversationService.joinConferenceSubconversation(parentConversationId);
|
|
95
|
+
expect(mlsService.wipeConversation).not.toHaveBeenCalled();
|
|
96
|
+
expect(mlsService.registerConversation).toHaveBeenCalledWith(subconversationGroupId, []);
|
|
97
|
+
});
|
|
98
|
+
it('deletes conference subconversation from backend if group is already established and epoch is older than one day, then rejoins', async () => {
|
|
99
|
+
jest.useFakeTimers();
|
|
100
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
101
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
102
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
103
|
+
const initialSubconversationEpoch = 1;
|
|
104
|
+
const currentTimeISO = '2023-10-24T12:00:00.000Z';
|
|
105
|
+
jest.setSystemTime(new Date(currentTimeISO));
|
|
106
|
+
jest.spyOn(apiClient.api.conversation, 'deleteSubconversation').mockResolvedValueOnce();
|
|
107
|
+
// epoch time is older than 24h
|
|
108
|
+
const epochTimestamp = '2023-10-23T11:00:00.000Z';
|
|
109
|
+
const subconversationResponse = getSubconversationResponse({
|
|
110
|
+
epoch: initialSubconversationEpoch,
|
|
111
|
+
epochTimestamp: epochTimestamp,
|
|
112
|
+
parentConversationId,
|
|
113
|
+
groupId: subconversationGroupId,
|
|
114
|
+
subconversationId: conversation_1.SUBCONVERSATION_ID.CONFERENCE,
|
|
115
|
+
});
|
|
116
|
+
jest.spyOn(apiClient.api.conversation, 'getSubconversation').mockResolvedValueOnce(subconversationResponse);
|
|
117
|
+
// After deletion, epoch is 0
|
|
118
|
+
const subconversationEpochAfterDeletion = 0;
|
|
119
|
+
const subconversationResponse2 = getSubconversationResponse({
|
|
120
|
+
epoch: subconversationEpochAfterDeletion,
|
|
121
|
+
epochTimestamp: epochTimestamp,
|
|
122
|
+
parentConversationId,
|
|
123
|
+
groupId: subconversationGroupId,
|
|
124
|
+
subconversationId: conversation_1.SUBCONVERSATION_ID.CONFERENCE,
|
|
125
|
+
});
|
|
126
|
+
jest.spyOn(apiClient.api.conversation, 'getSubconversation').mockResolvedValueOnce(subconversationResponse2);
|
|
127
|
+
await subconversationService.joinConferenceSubconversation(parentConversationId);
|
|
128
|
+
expect(apiClient.api.conversation.deleteSubconversation).toHaveBeenCalledWith(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, {
|
|
129
|
+
groupId: subconversationGroupId,
|
|
130
|
+
epoch: initialSubconversationEpoch,
|
|
131
|
+
});
|
|
132
|
+
expect(mlsService.registerConversation).toHaveBeenCalledTimes(1);
|
|
133
|
+
expect(mlsService.wipeConversation).toHaveBeenCalledWith(subconversationGroupId);
|
|
134
|
+
});
|
|
135
|
+
it('joins conference subconversation with external commit if group is already established and epoch is younger than one day', async () => {
|
|
136
|
+
jest.useFakeTimers();
|
|
137
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
138
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
139
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
140
|
+
const subconversationEpoch = 1;
|
|
141
|
+
const currentTimeISO = '2023-10-24T12:00:00.000Z';
|
|
142
|
+
jest.setSystemTime(new Date(currentTimeISO));
|
|
143
|
+
jest.spyOn(apiClient.api.conversation, 'deleteSubconversation').mockResolvedValueOnce();
|
|
144
|
+
// epoch time is younger than 24h
|
|
145
|
+
const epochTimestamp = '2023-10-23T13:00:00.000Z';
|
|
146
|
+
const subconversationResponse = getSubconversationResponse({
|
|
147
|
+
epoch: subconversationEpoch,
|
|
148
|
+
epochTimestamp: epochTimestamp,
|
|
149
|
+
parentConversationId,
|
|
150
|
+
groupId: subconversationGroupId,
|
|
151
|
+
subconversationId: conversation_1.SUBCONVERSATION_ID.CONFERENCE,
|
|
152
|
+
});
|
|
153
|
+
jest.spyOn(apiClient.api.conversation, 'getSubconversation').mockResolvedValueOnce(subconversationResponse);
|
|
154
|
+
await subconversationService.joinConferenceSubconversation(parentConversationId);
|
|
155
|
+
expect(apiClient.api.conversation.deleteSubconversation).not.toHaveBeenCalled();
|
|
156
|
+
expect(mlsService.registerConversation).not.toHaveBeenCalled();
|
|
157
|
+
expect(mlsService.wipeConversation).not.toHaveBeenCalled();
|
|
158
|
+
expect(mlsService.joinByExternalCommit).toHaveBeenCalled();
|
|
159
|
+
});
|
|
160
|
+
it('retries to join if registering a conversations throws an error', async () => {
|
|
161
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
162
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
163
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
164
|
+
const subconversationResponse = getSubconversationResponse({
|
|
165
|
+
epoch: 0,
|
|
166
|
+
epochTimestamp: '',
|
|
167
|
+
parentConversationId,
|
|
168
|
+
groupId: subconversationGroupId,
|
|
169
|
+
subconversationId: conversation_1.SUBCONVERSATION_ID.CONFERENCE,
|
|
170
|
+
});
|
|
171
|
+
jest.spyOn(apiClient.api.conversation, 'getSubconversation').mockResolvedValue(subconversationResponse);
|
|
172
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
|
|
173
|
+
jest
|
|
174
|
+
.spyOn(mlsService, 'registerConversation')
|
|
175
|
+
.mockRejectedValueOnce(new http_1.BackendError('', http_1.BackendErrorLabel.MLS_STALE_MESSAGE, http_1.StatusCode.CONFLICT));
|
|
176
|
+
await subconversationService.joinConferenceSubconversation(parentConversationId);
|
|
177
|
+
expect(mlsService.wipeConversation).not.toHaveBeenCalled();
|
|
178
|
+
expect(mlsService.registerConversation).toHaveBeenCalledWith(subconversationGroupId, []);
|
|
179
|
+
expect(mlsService.registerConversation).toHaveBeenCalledTimes(2);
|
|
180
|
+
});
|
|
181
|
+
it('returns fresh epoch number after joining the group', async () => {
|
|
182
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
183
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
184
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
185
|
+
const subconversationResponse = getSubconversationResponse({
|
|
186
|
+
epoch: 0,
|
|
187
|
+
epochTimestamp: '',
|
|
188
|
+
parentConversationId,
|
|
189
|
+
groupId: subconversationGroupId,
|
|
190
|
+
subconversationId: conversation_1.SUBCONVERSATION_ID.CONFERENCE,
|
|
191
|
+
});
|
|
192
|
+
jest.spyOn(apiClient.api.conversation, 'getSubconversation').mockResolvedValueOnce(subconversationResponse);
|
|
193
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
|
|
194
|
+
const updatedEpoch = 1;
|
|
195
|
+
jest.spyOn(mlsService, 'getEpoch').mockResolvedValueOnce(updatedEpoch);
|
|
196
|
+
const response = await subconversationService.joinConferenceSubconversation(parentConversationId);
|
|
197
|
+
expect(mlsService.wipeConversation).not.toHaveBeenCalled();
|
|
198
|
+
expect(mlsService.registerConversation).toHaveBeenCalledWith(subconversationGroupId, []);
|
|
199
|
+
expect(response).toEqual({ epoch: updatedEpoch, groupId: subconversationGroupId });
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
describe('leaveConferenceSubconversation', () => {
|
|
203
|
+
it('does nothing if subconversation id is not found in the store', async () => {
|
|
204
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
205
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
206
|
+
await subconversationService.leaveConferenceSubconversation(parentConversationId);
|
|
207
|
+
expect(mlsService.wipeConversation).not.toHaveBeenCalled();
|
|
208
|
+
});
|
|
209
|
+
it('removes subconversation id from the store if conversations was known but not established locally', async () => {
|
|
210
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
211
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
212
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
213
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
214
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
|
|
215
|
+
await subconversationService.leaveConferenceSubconversation(parentConversationId);
|
|
216
|
+
const groupId = await subconversationService.getSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
217
|
+
expect(groupId).toEqual(undefined);
|
|
218
|
+
expect(mlsService.wipeConversation).not.toHaveBeenCalled();
|
|
219
|
+
});
|
|
220
|
+
it('deletes self client from conference subconversation', async () => {
|
|
221
|
+
const [subconversationService, { apiClient, mlsService }] = await buildSubconversationService();
|
|
222
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
223
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
224
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
225
|
+
jest.spyOn(apiClient.api.conversation, 'deleteSubconversationSelf');
|
|
226
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
|
|
227
|
+
await subconversationService.leaveConferenceSubconversation(parentConversationId);
|
|
228
|
+
const groupId = await subconversationService.getSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
229
|
+
expect(groupId).toEqual(undefined);
|
|
230
|
+
expect(apiClient.api.conversation.deleteSubconversationSelf).toHaveBeenCalledWith(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
231
|
+
expect(mlsService.wipeConversation).toHaveBeenCalledWith(subconversationGroupId);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
describe('getSubconversationEpochInfo', () => {
|
|
235
|
+
it('returns null if subconversation id is not known by a client', async () => {
|
|
236
|
+
const [subconversationService] = await buildSubconversationService();
|
|
237
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
238
|
+
const parentConversationGroupId = 'parentConversationGroupId';
|
|
239
|
+
const response = await subconversationService.getSubconversationEpochInfo(parentConversationId, parentConversationGroupId);
|
|
240
|
+
expect(response).toEqual(null);
|
|
241
|
+
});
|
|
242
|
+
it('returns null if MLS group for subconversation does not exist locally', async () => {
|
|
243
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
244
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
245
|
+
const parentConversationGroupId = 'parentConversationGroupId';
|
|
246
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
|
|
247
|
+
const response = await subconversationService.getSubconversationEpochInfo(parentConversationId, parentConversationGroupId);
|
|
248
|
+
expect(response).toEqual(null);
|
|
249
|
+
});
|
|
250
|
+
it('returns epoch info and advances epoch number', async () => {
|
|
251
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
252
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
253
|
+
const parentConversationGroupId = 'parentConversationGroupId';
|
|
254
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
255
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
|
|
256
|
+
const mockedEpoch = 2;
|
|
257
|
+
jest.spyOn(mlsService, 'getEpoch').mockResolvedValueOnce(mockedEpoch);
|
|
258
|
+
const mockedSecretKey = 'mockedSecretKey';
|
|
259
|
+
jest.spyOn(mlsService, 'exportSecretKey').mockResolvedValueOnce(mockedSecretKey);
|
|
260
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
261
|
+
const subconversationMemberIds = [{ userId: 'userId1', clientId: 'clientId1', domain: 'domain' }];
|
|
262
|
+
const parentConversationMemberIds = [
|
|
263
|
+
{ userId: 'userId1', clientId: 'clientId1', domain: 'domain' },
|
|
264
|
+
{ userId: 'userId2', clientId: 'clientId2', domain: 'domain' },
|
|
265
|
+
];
|
|
266
|
+
jest.spyOn(mlsService, 'getClientIds').mockImplementation(async (groupId) => {
|
|
267
|
+
if (groupId === parentConversationGroupId) {
|
|
268
|
+
return parentConversationMemberIds;
|
|
269
|
+
}
|
|
270
|
+
return subconversationMemberIds;
|
|
271
|
+
});
|
|
272
|
+
const response = await subconversationService.getSubconversationEpochInfo(parentConversationId, parentConversationGroupId, true);
|
|
273
|
+
const expected = {
|
|
274
|
+
epoch: mockedEpoch,
|
|
275
|
+
keyLength: 32,
|
|
276
|
+
members: [
|
|
277
|
+
{ clientid: 'clientId1', in_subconv: true, userid: 'userId1@domain' },
|
|
278
|
+
{ clientid: 'clientId2', in_subconv: false, userid: 'userId2@domain' },
|
|
279
|
+
],
|
|
280
|
+
secretKey: mockedSecretKey,
|
|
281
|
+
};
|
|
282
|
+
expect(response).toEqual(expected);
|
|
283
|
+
expect(mlsService.renewKeyMaterial).toHaveBeenCalledWith(subconversationGroupId);
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
describe('subscribeToEpochUpdates', () => {
|
|
287
|
+
it('should subscribe to newEpoch event', async () => {
|
|
288
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
289
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
290
|
+
const parentConversationGroupId = 'parentConversationGroupId';
|
|
291
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
292
|
+
const mockedInitialEpoch = 1;
|
|
293
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
294
|
+
const mockedEpochInfo = { epoch: mockedInitialEpoch, keyLength: 32, members: [], secretKey: '' };
|
|
295
|
+
jest.spyOn(subconversationService, 'getSubconversationEpochInfo').mockResolvedValueOnce(mockedEpochInfo);
|
|
296
|
+
jest
|
|
297
|
+
.spyOn(subconversationService, 'joinConferenceSubconversation')
|
|
298
|
+
.mockResolvedValue({ epoch: mockedInitialEpoch, groupId: subconversationGroupId });
|
|
299
|
+
const findConversationByGroupId = (groupId) => {
|
|
300
|
+
if (groupId === parentConversationGroupId) {
|
|
301
|
+
return parentConversationId;
|
|
302
|
+
}
|
|
303
|
+
return undefined;
|
|
304
|
+
};
|
|
305
|
+
const onEpochUpdateCallback = jest.fn();
|
|
306
|
+
const unsubscribe = await subconversationService.subscribeToEpochUpdates(parentConversationId, parentConversationGroupId, findConversationByGroupId, onEpochUpdateCallback);
|
|
307
|
+
expect(mlsService.on).toHaveBeenCalledWith('newEpoch', expect.any(Function));
|
|
308
|
+
expect(subconversationService.getSubconversationEpochInfo).toHaveBeenCalledWith(parentConversationId, parentConversationGroupId);
|
|
309
|
+
expect(onEpochUpdateCallback).toHaveBeenCalledWith(mockedEpochInfo);
|
|
310
|
+
unsubscribe();
|
|
311
|
+
expect(mlsService.off).toHaveBeenCalledWith('newEpoch', expect.any(Function));
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
describe('removeClientFromConferenceSubconversation', () => {
|
|
315
|
+
it('does nothing if subconversation group is not known', async () => {
|
|
316
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
317
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
318
|
+
const user = { id: 'userId', domain: 'domain' };
|
|
319
|
+
const clientId = 'clientId';
|
|
320
|
+
const clientToRemove = { user, clientId };
|
|
321
|
+
await subconversationService.removeClientFromConferenceSubconversation(parentConversationId, clientToRemove);
|
|
322
|
+
expect(mlsService.removeClientsFromConversation).not.toHaveBeenCalled();
|
|
323
|
+
});
|
|
324
|
+
it('does nothing if subconversation group is not established', async () => {
|
|
325
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
326
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
327
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
328
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
329
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValue(false);
|
|
330
|
+
const user = { id: 'userId', domain: 'domain' };
|
|
331
|
+
const clientId = 'clientId';
|
|
332
|
+
const clientToRemove = { user, clientId };
|
|
333
|
+
await subconversationService.removeClientFromConferenceSubconversation(parentConversationId, clientToRemove);
|
|
334
|
+
expect(mlsService.removeClientsFromConversation).not.toHaveBeenCalled();
|
|
335
|
+
});
|
|
336
|
+
it('does nothing if client is not a subconversation group member', async () => {
|
|
337
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
338
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
339
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
340
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
341
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValue(true);
|
|
342
|
+
const subconversationMemberIds = [
|
|
343
|
+
{ userId: 'userId1', clientId: 'clientId1', domain: 'domain' },
|
|
344
|
+
{ userId: 'userId2', clientId: 'clientId2', domain: 'domain2' },
|
|
345
|
+
];
|
|
346
|
+
jest.spyOn(mlsService, 'getClientIds').mockResolvedValueOnce(subconversationMemberIds);
|
|
347
|
+
const user = { id: 'userId3', domain: 'domain3' };
|
|
348
|
+
const clientId = 'clientId3';
|
|
349
|
+
const clientToRemove = { user, clientId };
|
|
350
|
+
await subconversationService.removeClientFromConferenceSubconversation(parentConversationId, clientToRemove);
|
|
351
|
+
expect(mlsService.removeClientsFromConversation).not.toHaveBeenCalled();
|
|
352
|
+
});
|
|
353
|
+
it('removes client from subconversation group', async () => {
|
|
354
|
+
const [subconversationService, { mlsService }] = await buildSubconversationService();
|
|
355
|
+
const parentConversationId = { id: 'parentConversationId', domain: 'domain' };
|
|
356
|
+
const subconversationGroupId = 'subconversationGroupId';
|
|
357
|
+
await subconversationService.saveSubconversationGroupId(parentConversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, subconversationGroupId);
|
|
358
|
+
jest.spyOn(mlsService, 'conversationExists').mockResolvedValue(true);
|
|
359
|
+
const user = { id: 'userId3', domain: 'domain3' };
|
|
360
|
+
const clientId = 'clientId3';
|
|
361
|
+
const clientToRemove = { user, clientId };
|
|
362
|
+
const subconversationMemberIds = [
|
|
363
|
+
{ userId: 'userId1', clientId: 'clientId1', domain: 'domain' },
|
|
364
|
+
{ userId: 'userId2', clientId: 'clientId2', domain: 'domain2' },
|
|
365
|
+
{ userId: clientToRemove.user.id, clientId: clientToRemove.clientId, domain: clientToRemove.user.domain },
|
|
366
|
+
];
|
|
367
|
+
jest.spyOn(mlsService, 'getClientIds').mockResolvedValueOnce(subconversationMemberIds);
|
|
368
|
+
await subconversationService.removeClientFromConferenceSubconversation(parentConversationId, clientToRemove);
|
|
369
|
+
expect(mlsService.removeClientsFromConversation).toHaveBeenCalledWith(subconversationGroupId, [
|
|
370
|
+
(0, fullyQualifiedClientIdUtils_1.constructFullyQualifiedClientId)(clientToRemove.user.id, clientToRemove.clientId, clientToRemove.user.domain),
|
|
371
|
+
]);
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SUBCONVERSATION_ID } from '@wireapp/api-client/lib/conversation';
|
|
2
|
+
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
3
|
+
export declare const generateSubconversationStoreKey: (parentConversationId: QualifiedId, subconversationId: SUBCONVERSATION_ID) => `${string}@${string}:${SUBCONVERSATION_ID}`;
|
|
4
|
+
//# sourceMappingURL=subconversationUtil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subconversationUtil.d.ts","sourceRoot":"","sources":["../../../src/conversation/SubconversationService/subconversationUtil.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAEzD,eAAO,MAAM,+BAA+B,yBACpB,WAAW,qBACd,kBAAkB,KACpC,GAAG,MAAM,IAAI,MAAM,IAAI,kBAAkB,EAE3C,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Wire
|
|
4
|
+
* Copyright (C) 2023 Wire Swiss GmbH
|
|
5
|
+
*
|
|
6
|
+
* This program is free software: you can redistribute it and/or modify
|
|
7
|
+
* it under the terms of the GNU General Public License as published by
|
|
8
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
* (at your option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
* GNU General Public License for more details.
|
|
15
|
+
*
|
|
16
|
+
* You should have received a copy of the GNU General Public License
|
|
17
|
+
* along with this program. If not, see http://www.gnu.org/licenses/.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.generateSubconversationStoreKey = void 0;
|
|
22
|
+
const generateSubconversationStoreKey = (parentConversationId, subconversationId) => {
|
|
23
|
+
return `${parentConversationId.id}@${parentConversationId.domain}:${subconversationId}`;
|
|
24
|
+
};
|
|
25
|
+
exports.generateSubconversationStoreKey = generateSubconversationStoreKey;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { SUBCONVERSATION_ID } from '@wireapp/api-client/lib/conversation';
|
|
1
2
|
import { ConversationMLSMessageAddEvent } from '@wireapp/api-client/lib/event';
|
|
3
|
+
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
2
4
|
import { HandledEventPayload } from '../../../../../notification';
|
|
3
5
|
import { MLSService } from '../../../MLSService/MLSService';
|
|
4
6
|
interface HandleMLSMessageAddParams {
|
|
5
7
|
event: ConversationMLSMessageAddEvent;
|
|
6
8
|
mlsService: MLSService;
|
|
9
|
+
groupIdFromConversationId: (conversationId: QualifiedId, subconversationId?: SUBCONVERSATION_ID) => Promise<string | undefined>;
|
|
7
10
|
}
|
|
8
|
-
export declare const handleMLSMessageAdd: ({ event, mlsService, }: HandleMLSMessageAddParams) => Promise<HandledEventPayload | null>;
|
|
11
|
+
export declare const handleMLSMessageAdd: ({ event, mlsService, groupIdFromConversationId, }: HandleMLSMessageAddParams) => Promise<HandledEventPayload | null>;
|
|
9
12
|
export {};
|
|
10
13
|
//# sourceMappingURL=messageAdd.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messageAdd.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,8BAA8B,EAAC,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"messageAdd.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAC,8BAA8B,EAAC,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAKzD,OAAO,EAAC,mBAAmB,EAAC,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAC,UAAU,EAAuB,MAAM,gCAAgC,CAAC;AAEhF,UAAU,yBAAyB;IACjC,KAAK,EAAE,8BAA8B,CAAC;IACtC,UAAU,EAAE,UAAU,CAAC;IACvB,yBAAyB,EAAE,CACzB,cAAc,EAAE,WAAW,EAC3B,iBAAiB,CAAC,EAAE,kBAAkB,KACnC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAClC;AAED,eAAO,MAAM,mBAAmB,sDAI7B,yBAAyB,KAAG,QAAQ,mBAAmB,GAAG,IAAI,CA+ChE,CAAC"}
|
|
@@ -22,11 +22,11 @@ exports.handleMLSMessageAdd = void 0;
|
|
|
22
22
|
const bazinga64_1 = require("bazinga64");
|
|
23
23
|
const protocol_messaging_1 = require("@wireapp/protocol-messaging");
|
|
24
24
|
const MLSService_1 = require("../../../MLSService/MLSService");
|
|
25
|
-
const handleMLSMessageAdd = async ({ event, mlsService, }) => {
|
|
25
|
+
const handleMLSMessageAdd = async ({ event, mlsService, groupIdFromConversationId, }) => {
|
|
26
26
|
var _a;
|
|
27
27
|
const encryptedData = bazinga64_1.Decoder.fromBase64(event.data).asBytes;
|
|
28
28
|
const qualifiedConversationId = (_a = event.qualified_conversation) !== null && _a !== void 0 ? _a : { id: event.conversation, domain: '' };
|
|
29
|
-
const groupId = await
|
|
29
|
+
const groupId = await groupIdFromConversationId(qualifiedConversationId, event.subconv);
|
|
30
30
|
// We should not receive a message for a group the client is not aware of
|
|
31
31
|
if (!groupId) {
|
|
32
32
|
throw new Error(`Could not find a group_id for conversation ${qualifiedConversationId.id}@${qualifiedConversationId.domain}`);
|
|
@@ -46,13 +46,13 @@ const createMockedMessage = () => {
|
|
|
46
46
|
describe('handleMLSMessageAdd', () => {
|
|
47
47
|
it('throws when received a message for a group that is not known by a client', async () => {
|
|
48
48
|
const event = createMLSMessageAddEventMock({ id: 'conversationId', domain: 'staging.zinfra.io' });
|
|
49
|
-
|
|
50
|
-
await expect((0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService })).rejects.toThrow();
|
|
49
|
+
const groupIdFromConversationId = () => Promise.resolve(undefined);
|
|
50
|
+
await expect((0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService, groupIdFromConversationId })).rejects.toThrow();
|
|
51
51
|
});
|
|
52
52
|
it('does not handle pending proposals if message does not contain proposals', async () => {
|
|
53
53
|
const event = createMLSMessageAddEventMock({ id: 'conversationId', domain: 'staging.zinfra.io' });
|
|
54
54
|
const mockGroupId = 'AAEAAH87aajaQ011i+rNLmwpy0sAZGl5YS53aXJlLmxpbms=';
|
|
55
|
-
|
|
55
|
+
const groupIdFromConversationId = () => Promise.resolve(mockGroupId);
|
|
56
56
|
const message = createMockedMessage();
|
|
57
57
|
jest.spyOn(mockedMLSService, 'decryptMessage').mockResolvedValueOnce({
|
|
58
58
|
proposals: [],
|
|
@@ -61,13 +61,13 @@ describe('handleMLSMessageAdd', () => {
|
|
|
61
61
|
hasEpochChanged: false,
|
|
62
62
|
isActive: true,
|
|
63
63
|
});
|
|
64
|
-
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService });
|
|
64
|
+
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService, groupIdFromConversationId });
|
|
65
65
|
expect(mockedMLSService.handlePendingProposals).not.toHaveBeenCalled();
|
|
66
66
|
});
|
|
67
67
|
it('handles pending proposals if message includes proposals', async () => {
|
|
68
68
|
const event = createMLSMessageAddEventMock({ id: 'conversationId', domain: 'staging.zinfra.io' });
|
|
69
69
|
const mockGroupId = 'AAEAAH87aajaQ011i+rNLmwpy0sAZGl5YS53aXJlLmxpbms=';
|
|
70
|
-
|
|
70
|
+
const groupIdFromConversationId = () => Promise.resolve(mockGroupId);
|
|
71
71
|
const message = createMockedMessage();
|
|
72
72
|
jest.spyOn(mockedMLSService, 'decryptMessage').mockResolvedValueOnce({
|
|
73
73
|
proposals: [{ proposal: new Uint8Array(), proposalRef: new Uint8Array() }],
|
|
@@ -76,7 +76,7 @@ describe('handleMLSMessageAdd', () => {
|
|
|
76
76
|
hasEpochChanged: false,
|
|
77
77
|
isActive: true,
|
|
78
78
|
});
|
|
79
|
-
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService });
|
|
79
|
+
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService, groupIdFromConversationId });
|
|
80
80
|
expect(mockedMLSService.handlePendingProposals).toHaveBeenCalledWith({
|
|
81
81
|
groupId: mockGroupId,
|
|
82
82
|
delayInMs: 2000,
|
|
@@ -86,7 +86,7 @@ describe('handleMLSMessageAdd', () => {
|
|
|
86
86
|
it('emits "newEpoch" event if incoming message has advanced epoch number', async () => {
|
|
87
87
|
const event = createMLSMessageAddEventMock({ id: 'conversationId', domain: 'staging.zinfra.io' });
|
|
88
88
|
const mockGroupId = 'AAEAAH87aajaQ011i+rNLmwpy0sAZGl5YS53aXJlLmxpbms=';
|
|
89
|
-
|
|
89
|
+
const groupIdFromConversationId = () => Promise.resolve(mockGroupId);
|
|
90
90
|
const message = createMockedMessage();
|
|
91
91
|
jest.spyOn(mockedMLSService, 'decryptMessage').mockResolvedValueOnce({
|
|
92
92
|
proposals: [],
|
|
@@ -96,7 +96,7 @@ describe('handleMLSMessageAdd', () => {
|
|
|
96
96
|
});
|
|
97
97
|
const mockedNewEpoch = 5;
|
|
98
98
|
jest.spyOn(mockedMLSService, 'getEpoch').mockResolvedValueOnce(mockedNewEpoch);
|
|
99
|
-
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService });
|
|
99
|
+
await (0, messageAdd_1.handleMLSMessageAdd)({ event, mlsService: mockedMLSService, groupIdFromConversationId });
|
|
100
100
|
expect(mockedMLSService.emit).toHaveBeenCalledWith('newEpoch', {
|
|
101
101
|
groupId: mockGroupId,
|
|
102
102
|
epoch: mockedNewEpoch,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { RegisteredClient } from '@wireapp/api-client/lib/client';
|
|
2
2
|
import { PostMlsMessageResponse, SUBCONVERSATION_ID } from '@wireapp/api-client/lib/conversation';
|
|
3
|
-
import { Subconversation } from '@wireapp/api-client/lib/conversation/Subconversation';
|
|
4
3
|
import { ConversationMLSMessageAddEvent, ConversationMLSWelcomeEvent } from '@wireapp/api-client/lib/event';
|
|
5
4
|
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
6
5
|
import logdown from 'logdown';
|
|
@@ -12,7 +11,7 @@ import { KeyPackageClaimUser } from '../../../conversation';
|
|
|
12
11
|
import { CoreDatabase } from '../../../storage/CoreDB';
|
|
13
12
|
import { RecurringTaskScheduler } from '../../../util/RecurringTaskScheduler';
|
|
14
13
|
import { AcmeChallenge, E2EIServiceExternal, User } from '../E2EIdentityService';
|
|
15
|
-
import { ClientId, CommitPendingProposalsParams, HandlePendingProposalsParams
|
|
14
|
+
import { ClientId, CommitPendingProposalsParams, HandlePendingProposalsParams } from '../types';
|
|
16
15
|
export declare const optionalToUint8Array: (array: Uint8Array | []) => Uint8Array;
|
|
17
16
|
interface LocalMLSServiceConfig extends MLSServiceConfig {
|
|
18
17
|
/**
|
|
@@ -20,11 +19,6 @@ interface LocalMLSServiceConfig extends MLSServiceConfig {
|
|
|
20
19
|
*/
|
|
21
20
|
minRequiredNumberOfAvailableKeyPackages: number;
|
|
22
21
|
}
|
|
23
|
-
export interface SubconversationEpochInfoMember {
|
|
24
|
-
userid: string;
|
|
25
|
-
clientid: ClientId;
|
|
26
|
-
in_subconv: boolean;
|
|
27
|
-
}
|
|
28
22
|
type Events = {
|
|
29
23
|
newEpoch: {
|
|
30
24
|
epoch: number;
|
|
@@ -38,7 +32,6 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
38
32
|
private readonly recurringTaskScheduler;
|
|
39
33
|
logger: logdown.Logger;
|
|
40
34
|
config: LocalMLSServiceConfig;
|
|
41
|
-
groupIdFromConversationId?: MLSCallbacks['groupIdFromConversationId'];
|
|
42
35
|
private readonly textEncoder;
|
|
43
36
|
private readonly textDecoder;
|
|
44
37
|
constructor(apiClient: APIClient, coreCryptoClient: CoreCrypto, coreDatabase: CoreDatabase, recurringTaskScheduler: RecurringTaskScheduler, { keyingMaterialUpdateThreshold, nbKeyPackages, defaultCiphersuite, defaultCredentialType, }: Partial<MLSServiceConfig>);
|
|
@@ -52,7 +45,6 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
52
45
|
* @param invitee - the list of keys of clients to add to the MLS group
|
|
53
46
|
*/
|
|
54
47
|
addUsersToExistingConversation(groupId: string, invitee: Invitee[]): Promise<PostMlsMessageResponse>;
|
|
55
|
-
configureMLSCallbacks({ groupIdFromConversationId, ...coreCryptoCallbacks }: MLSCallbacks): void;
|
|
56
48
|
getKeyPackagesPayload(qualifiedUsers: KeyPackageClaimUser[]): Promise<{
|
|
57
49
|
coreCryptoKeyPackagesPayload: Invitee[];
|
|
58
50
|
failedToFetchKeyPackages: QualifiedId[];
|
|
@@ -60,25 +52,6 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
60
52
|
getEpoch(groupId: string | Uint8Array): Promise<number>;
|
|
61
53
|
newProposal(proposalType: ProposalType, args: ProposalArgs | AddProposalArgs | RemoveProposalArgs): Promise<import("@wireapp/core-crypto").ProposalBundle>;
|
|
62
54
|
joinByExternalCommit(getGroupInfo: () => Promise<Uint8Array>): Promise<PostMlsMessageResponse>;
|
|
63
|
-
getConferenceSubconversation(conversationId: QualifiedId): Promise<Subconversation>;
|
|
64
|
-
private deleteConferenceSubconversation;
|
|
65
|
-
/**
|
|
66
|
-
* Will leave conference subconversation if it's known by client and established.
|
|
67
|
-
*
|
|
68
|
-
* @param conversationId Id of the parent conversation which subconversation we want to leave
|
|
69
|
-
*/
|
|
70
|
-
leaveConferenceSubconversation(conversationId: QualifiedId): Promise<void>;
|
|
71
|
-
leaveStaleConferenceSubconversations(): Promise<void>;
|
|
72
|
-
/**
|
|
73
|
-
* Will join or register an mls subconversation for conference calls.
|
|
74
|
-
* Will return the secret key derived from the subconversation
|
|
75
|
-
*
|
|
76
|
-
* @param conversationId Id of the parent conversation in which the call should happen
|
|
77
|
-
*/
|
|
78
|
-
joinConferenceSubconversation(conversationId: QualifiedId): Promise<{
|
|
79
|
-
groupId: string;
|
|
80
|
-
epoch: number;
|
|
81
|
-
}>;
|
|
82
55
|
exportSecretKey(groupId: string, keyLength: number): Promise<string>;
|
|
83
56
|
newExternalProposal(externalProposalType: ExternalProposalType, args: ExternalAddProposalArgs): Promise<Uint8Array>;
|
|
84
57
|
processWelcomeMessage(welcomeMessage: Uint8Array): Promise<ConversationId>;
|
|
@@ -188,13 +161,6 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
188
161
|
private uploadMLSPublicKeys;
|
|
189
162
|
private uploadMLSKeyPackages;
|
|
190
163
|
wipeConversation(groupId: string): Promise<void>;
|
|
191
|
-
/**
|
|
192
|
-
* If there is a matching conversationId => groupId pair in the database,
|
|
193
|
-
* we can find the groupId and return it as a string
|
|
194
|
-
*
|
|
195
|
-
* @param conversationQualifiedId
|
|
196
|
-
*/
|
|
197
|
-
getGroupIdFromConversationId(conversationQualifiedId: QualifiedId, subconversationId?: SUBCONVERSATION_ID): Promise<string | undefined>;
|
|
198
164
|
/**
|
|
199
165
|
* If there are pending proposals, we need to either process them,
|
|
200
166
|
* or save them in the database for later processing
|
|
@@ -230,7 +196,7 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
230
196
|
clientId: ClientId;
|
|
231
197
|
domain: string;
|
|
232
198
|
}[]>;
|
|
233
|
-
handleMLSMessageAddEvent(event: ConversationMLSMessageAddEvent): Promise<import("../../../notification").HandledEventPayload | null>;
|
|
199
|
+
handleMLSMessageAddEvent(event: ConversationMLSMessageAddEvent, groupIdFromConversationId: (conversationId: QualifiedId, subconversationId?: SUBCONVERSATION_ID) => Promise<string | undefined>): Promise<import("../../../notification").HandledEventPayload | null>;
|
|
234
200
|
handleMLSWelcomeMessageEvent(event: ConversationMLSWelcomeEvent, clientId: string): Promise<import("../../../notification").HandledEventPayload>;
|
|
235
201
|
deleteMLSKeyPackages(clientId: ClientId, keyPackagRefs: Uint8Array[]): Promise<void>;
|
|
236
202
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAqB,gBAAgB,EAAC,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAC,sBAAsB,EAAE,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AAChG,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"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"}
|