@wireapp/core 39.0.2 → 39.1.1
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/broadcast/BroadcastService.d.ts +0 -9
- package/lib/broadcast/BroadcastService.d.ts.map +1 -1
- package/lib/broadcast/BroadcastService.js +1 -28
- package/lib/conversation/message/MessageService.js +2 -2
- package/lib/conversation/message/MessageService.test.js +21 -7
- package/lib/conversation/message/UserClientsUtil.d.ts +14 -10
- package/lib/conversation/message/UserClientsUtil.d.ts.map +1 -1
- package/lib/conversation/message/UserClientsUtil.js +21 -11
- package/lib/conversation/message/UserClientsUtils.test.js +5 -9
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts +2 -0
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.js +2 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.test.js +20 -16
- package/lib/messagingProtocols/proteus/Utility/Recipients.d.ts +2 -2
- package/lib/messagingProtocols/proteus/Utility/Recipients.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/Utility/Recipients.js +10 -2
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.d.ts +2 -0
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.js +8 -6
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.test.js +42 -32
- package/package.json +3 -3
- package/lib/messagingProtocols/proteus/Utility/PreKeyBundle/PreKeyBundle.d.ts +0 -25
- package/lib/messagingProtocols/proteus/Utility/PreKeyBundle/PreKeyBundle.d.ts.map +0 -1
- package/lib/messagingProtocols/proteus/Utility/PreKeyBundle/PreKeyBundle.js +0 -93
- package/lib/messagingProtocols/proteus/Utility/PreKeyBundle/PreKeyBundle.test.d.ts +0 -2
- package/lib/messagingProtocols/proteus/Utility/PreKeyBundle/PreKeyBundle.test.d.ts.map +0 -1
- package/lib/messagingProtocols/proteus/Utility/PreKeyBundle/PreKeyBundle.test.js +0 -66
- package/lib/messagingProtocols/proteus/Utility/PreKeyBundle/index.d.ts +0 -2
- package/lib/messagingProtocols/proteus/Utility/PreKeyBundle/index.d.ts.map +0 -1
- package/lib/messagingProtocols/proteus/Utility/PreKeyBundle/index.js +0 -35
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ClientMismatch, MessageSendingStatus, QualifiedUserClients } from '@wireapp/api-client/lib/conversation';
|
|
2
|
-
import { UserPreKeyBundleMap } from '@wireapp/api-client/lib/user/';
|
|
3
2
|
import { APIClient } from '@wireapp/api-client';
|
|
4
3
|
import { GenericMessage } from '@wireapp/protocol-messaging';
|
|
5
4
|
import { ProteusService } from '../messagingProtocols/proteus';
|
|
@@ -8,14 +7,6 @@ export declare class BroadcastService {
|
|
|
8
7
|
private readonly proteusService;
|
|
9
8
|
private readonly messageService;
|
|
10
9
|
constructor(apiClient: APIClient, proteusService: ProteusService);
|
|
11
|
-
/**
|
|
12
|
-
* Will create a key bundle for all the users of the team
|
|
13
|
-
*
|
|
14
|
-
* @param teamId
|
|
15
|
-
* @param skipOwnClients=false
|
|
16
|
-
* @param onlyDirectConnections=false Will generate a bundle only for directly connected users (users the self user has conversation with). Allows avoiding broadcasting messages to too many people
|
|
17
|
-
*/
|
|
18
|
-
getPreKeyBundlesFromTeam(teamId: string, skipOwnClients?: boolean, onlyDirectConnections?: boolean): Promise<UserPreKeyBundleMap>;
|
|
19
10
|
broadcastGenericMessage(genericMessage: GenericMessage, recipients: QualifiedUserClients, onClientMismatch?: (mismatch: ClientMismatch | MessageSendingStatus) => void | boolean | Promise<boolean>): Promise<ClientMismatch | MessageSendingStatus>;
|
|
20
11
|
}
|
|
21
12
|
//# sourceMappingURL=BroadcastService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BroadcastService.d.ts","sourceRoot":"","sources":["../../src/broadcast/BroadcastService.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAC,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"BroadcastService.d.ts","sourceRoot":"","sources":["../../src/broadcast/BroadcastService.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAC,MAAM,sCAAsC,CAAC;AAEhH,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC;AAK3D,OAAO,EAAC,cAAc,EAAC,MAAM,+BAA+B,CAAC;AAE7D,qBAAa,gBAAgB;IAGf,OAAO,CAAC,QAAQ,CAAC,SAAS;IAAa,OAAO,CAAC,QAAQ,CAAC,cAAc;IAFlF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;gBAEnB,SAAS,EAAE,SAAS,EAAmB,cAAc,EAAE,cAAc;IAIrF,uBAAuB,CAClC,cAAc,EAAE,cAAc,EAC9B,UAAU,EAAE,oBAAoB,EAChC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,GAAG,oBAAoB,KAAK,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAY5G"}
|
|
@@ -29,38 +29,11 @@ class BroadcastService {
|
|
|
29
29
|
this.proteusService = proteusService;
|
|
30
30
|
this.messageService = new MessageService_1.MessageService(this.apiClient, this.proteusService);
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Will create a key bundle for all the users of the team
|
|
34
|
-
*
|
|
35
|
-
* @param teamId
|
|
36
|
-
* @param skipOwnClients=false
|
|
37
|
-
* @param onlyDirectConnections=false Will generate a bundle only for directly connected users (users the self user has conversation with). Allows avoiding broadcasting messages to too many people
|
|
38
|
-
*/
|
|
39
|
-
async getPreKeyBundlesFromTeam(teamId, skipOwnClients = false, onlyDirectConnections = false) {
|
|
40
|
-
const teamMembers = onlyDirectConnections
|
|
41
|
-
? (await this.apiClient.api.conversation.getConversations()).conversations
|
|
42
|
-
.map(({ members }) => members.others.map(user => user.id).concat(members.self.id))
|
|
43
|
-
.flat()
|
|
44
|
-
: (await this.apiClient.api.teams.member.getAllMembers(teamId)).members.map(({ user }) => user);
|
|
45
|
-
let members = Array.from(new Set(teamMembers)).map(member => ({ id: member }));
|
|
46
|
-
if (skipOwnClients) {
|
|
47
|
-
const selfUser = await this.apiClient.api.self.getSelf();
|
|
48
|
-
members = members.filter(member => member.id !== selfUser.id);
|
|
49
|
-
}
|
|
50
|
-
const preKeys = await Promise.all(members.map(member => this.apiClient.api.user.getUserPreKeys(member.id)));
|
|
51
|
-
return preKeys.reduce((bundleMap, bundle) => {
|
|
52
|
-
bundleMap[bundle.user] = {};
|
|
53
|
-
for (const client of bundle.clients) {
|
|
54
|
-
bundleMap[bundle.user][client.client] = client.prekey;
|
|
55
|
-
}
|
|
56
|
-
return bundleMap;
|
|
57
|
-
}, {});
|
|
58
|
-
}
|
|
59
32
|
async broadcastGenericMessage(genericMessage, recipients, onClientMismatch) {
|
|
60
33
|
const plainTextArray = protocol_messaging_1.GenericMessage.encode(genericMessage).finish();
|
|
61
34
|
const send = () => {
|
|
62
35
|
return this.messageService.sendMessage(this.apiClient.validatedClientId, recipients, plainTextArray, {
|
|
63
|
-
reportMissing: (0, UserClientsUtil_1.
|
|
36
|
+
reportMissing: (0, UserClientsUtil_1.flattenUserMap)(recipients).map(({ userId }) => userId),
|
|
64
37
|
onClientMismatch,
|
|
65
38
|
});
|
|
66
39
|
};
|
|
@@ -127,12 +127,12 @@ class MessageService {
|
|
|
127
127
|
* @return resolves with a new message payload that can be sent
|
|
128
128
|
*/
|
|
129
129
|
async reencryptAfterMismatch(mismatch, recipients, plainText) {
|
|
130
|
-
const deleted = (0, UserClientsUtil_1.
|
|
130
|
+
const deleted = (0, UserClientsUtil_1.flattenUserMap)(mismatch.deleted);
|
|
131
131
|
// remove deleted clients to the recipients
|
|
132
132
|
deleted.forEach(({ userId, data }) => data.forEach(clientId => delete recipients[userId.domain][userId.id][clientId]));
|
|
133
133
|
if (Object.keys(mismatch.missing).length) {
|
|
134
134
|
const { payloads } = await this.proteusService.encrypt(plainText, mismatch.missing);
|
|
135
|
-
const reEncryptedPayloads = (0, UserClientsUtil_1.
|
|
135
|
+
const reEncryptedPayloads = (0, UserClientsUtil_1.flattenUserMap)(payloads);
|
|
136
136
|
reEncryptedPayloads.forEach(({ data, userId }) => {
|
|
137
137
|
var _a;
|
|
138
138
|
const domainRecipients = (_a = recipients[userId.domain]) !== null && _a !== void 0 ? _a : {};
|
|
@@ -150,7 +150,9 @@ describe('MessageService', () => {
|
|
|
150
150
|
}
|
|
151
151
|
return Promise.resolve(baseClientMismatch);
|
|
152
152
|
});
|
|
153
|
-
jest
|
|
153
|
+
jest
|
|
154
|
+
.spyOn(apiClient.api.user, 'postMultiPreKeyBundles')
|
|
155
|
+
.mockReturnValue(Promise.resolve({ qualified_user_client_prekeys: {} }));
|
|
154
156
|
const recipients = generateRecipients([]);
|
|
155
157
|
await messageService.sendMessage('senderclientid', recipients, new Uint8Array(), {
|
|
156
158
|
reportMissing: true,
|
|
@@ -174,7 +176,9 @@ describe('MessageService', () => {
|
|
|
174
176
|
}
|
|
175
177
|
return Promise.resolve(baseClientMismatch);
|
|
176
178
|
});
|
|
177
|
-
jest
|
|
179
|
+
jest
|
|
180
|
+
.spyOn(apiClient.api.user, 'postMultiPreKeyBundles')
|
|
181
|
+
.mockReturnValue(Promise.resolve({ qualified_user_client_prekeys: {} }));
|
|
178
182
|
const recipients = generateRecipients([user1, user2]);
|
|
179
183
|
await messageService.sendMessage('senderclientid', recipients, new Uint8Array(), {
|
|
180
184
|
reportMissing: true,
|
|
@@ -199,7 +203,9 @@ describe('MessageService', () => {
|
|
|
199
203
|
}
|
|
200
204
|
return Promise.resolve(baseClientMismatch);
|
|
201
205
|
});
|
|
202
|
-
jest
|
|
206
|
+
jest
|
|
207
|
+
.spyOn(apiClient.api.user, 'postMultiPreKeyBundles')
|
|
208
|
+
.mockReturnValue(Promise.resolve({ qualified_user_client_prekeys: {} }));
|
|
203
209
|
const recipients = generateRecipients([user1, user2]);
|
|
204
210
|
await messageService.sendMessage('senderclientid', recipients, new Uint8Array(), {
|
|
205
211
|
reportMissing: true,
|
|
@@ -221,7 +227,9 @@ describe('MessageService', () => {
|
|
|
221
227
|
};
|
|
222
228
|
return Promise.reject(error);
|
|
223
229
|
});
|
|
224
|
-
jest
|
|
230
|
+
jest
|
|
231
|
+
.spyOn(apiClient.api.user, 'postMultiPreKeyBundles')
|
|
232
|
+
.mockReturnValue(Promise.resolve({ qualified_user_client_prekeys: {} }));
|
|
225
233
|
const recipients = generateRecipients([user1, user2]);
|
|
226
234
|
await messageService.sendMessage('senderclientid', recipients, new Uint8Array(), {
|
|
227
235
|
reportMissing: true,
|
|
@@ -249,7 +257,9 @@ describe('MessageService', () => {
|
|
|
249
257
|
}
|
|
250
258
|
return Promise.resolve(baseMessageSendingStatus);
|
|
251
259
|
});
|
|
252
|
-
jest
|
|
260
|
+
jest
|
|
261
|
+
.spyOn(apiClient.api.user, 'postMultiPreKeyBundles')
|
|
262
|
+
.mockReturnValue(Promise.resolve({ qualified_user_client_prekeys: {} }));
|
|
253
263
|
const recipients = generateQualifiedRecipients([user1, user2]);
|
|
254
264
|
await messageService.sendMessage('senderclientid', recipients, new Uint8Array(), {
|
|
255
265
|
reportMissing: true,
|
|
@@ -274,7 +284,9 @@ describe('MessageService', () => {
|
|
|
274
284
|
}
|
|
275
285
|
return Promise.resolve(baseMessageSendingStatus);
|
|
276
286
|
});
|
|
277
|
-
jest
|
|
287
|
+
jest
|
|
288
|
+
.spyOn(apiClient.api.user, 'postMultiPreKeyBundles')
|
|
289
|
+
.mockReturnValue(Promise.resolve({ qualified_user_client_prekeys: {} }));
|
|
278
290
|
const recipients = generateQualifiedRecipients([user1, user2]);
|
|
279
291
|
await messageService.sendMessage('senderclientid', recipients, new Uint8Array(), {
|
|
280
292
|
reportMissing: true,
|
|
@@ -317,7 +329,9 @@ describe('MessageService', () => {
|
|
|
317
329
|
};
|
|
318
330
|
return Promise.reject(error);
|
|
319
331
|
});
|
|
320
|
-
jest
|
|
332
|
+
jest
|
|
333
|
+
.spyOn(apiClient.api.user, 'postMultiPreKeyBundles')
|
|
334
|
+
.mockReturnValue(Promise.resolve({ qualified_user_client_prekeys: {} }));
|
|
321
335
|
const recipients = generateQualifiedRecipients([user1, user2]);
|
|
322
336
|
await messageService.sendMessage('senderclientid', recipients, new Uint8Array(), {
|
|
323
337
|
reportMissing: true,
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
2
|
-
type
|
|
2
|
+
type UserMap<T> = {
|
|
3
3
|
[userId: string]: T;
|
|
4
4
|
};
|
|
5
|
-
type
|
|
6
|
-
[domain: string]:
|
|
5
|
+
type QualifiedUserMap<T> = {
|
|
6
|
+
[domain: string]: UserMap<T>;
|
|
7
7
|
};
|
|
8
|
-
export declare function flattenUserClients<T>(userClients: UserClientsContainer<T>, domain?: string): {
|
|
9
|
-
data: T;
|
|
10
|
-
userId: QualifiedId;
|
|
11
|
-
}[];
|
|
12
8
|
/**
|
|
13
|
-
* Will flatten a container of users=>
|
|
9
|
+
* Will flatten a container of domain=>users=>anything infos to an array
|
|
14
10
|
*
|
|
15
|
-
* @param
|
|
11
|
+
* @param userMap The qualified UserMap to flatten
|
|
16
12
|
* @return An array containing the qualified user Ids and the clients info
|
|
17
13
|
*/
|
|
18
|
-
export declare function
|
|
14
|
+
export declare function flattenUserMap<T = unknown>(userMap: QualifiedUserMap<T>): {
|
|
19
15
|
data: T;
|
|
20
16
|
userId: QualifiedId;
|
|
21
17
|
}[];
|
|
18
|
+
/**
|
|
19
|
+
* Will convert a list of qualified users to a UserMap
|
|
20
|
+
* @param users the list of users to convert
|
|
21
|
+
*/
|
|
22
|
+
export declare function nestUsersList<T = unknown>(users: {
|
|
23
|
+
data: T;
|
|
24
|
+
userId: QualifiedId;
|
|
25
|
+
}[]): QualifiedUserMap<T>;
|
|
22
26
|
export {};
|
|
23
27
|
//# sourceMappingURL=UserClientsUtil.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserClientsUtil.d.ts","sourceRoot":"","sources":["../../../src/conversation/message/UserClientsUtil.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAEzD,KAAK,
|
|
1
|
+
{"version":3,"file":"UserClientsUtil.d.ts","sourceRoot":"","sources":["../../../src/conversation/message/UserClientsUtil.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAEzD,KAAK,OAAO,CAAC,CAAC,IAAI;IAAC,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAA;CAAC,CAAC;AACxC,KAAK,gBAAgB,CAAC,CAAC,IAAI;IAAC,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CAAC,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAC,EAAE,CAI1G;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAC,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAQvG"}
|
|
@@ -18,20 +18,30 @@
|
|
|
18
18
|
*
|
|
19
19
|
*/
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.
|
|
22
|
-
function flattenUserClients(userClients, domain = '') {
|
|
23
|
-
return Object.entries(userClients).map(([id, data]) => ({ data, userId: { domain, id } }));
|
|
24
|
-
}
|
|
25
|
-
exports.flattenUserClients = flattenUserClients;
|
|
21
|
+
exports.nestUsersList = exports.flattenUserMap = void 0;
|
|
26
22
|
/**
|
|
27
|
-
* Will flatten a container of users=>
|
|
23
|
+
* Will flatten a container of domain=>users=>anything infos to an array
|
|
28
24
|
*
|
|
29
|
-
* @param
|
|
25
|
+
* @param userMap The qualified UserMap to flatten
|
|
30
26
|
* @return An array containing the qualified user Ids and the clients info
|
|
31
27
|
*/
|
|
32
|
-
function
|
|
33
|
-
return Object.entries(
|
|
34
|
-
return [...ids, ...
|
|
28
|
+
function flattenUserMap(userMap) {
|
|
29
|
+
return Object.entries(userMap).reduce((ids, [domain, userClients]) => {
|
|
30
|
+
return [...ids, ...Object.entries(userClients).map(([id, data]) => ({ data, userId: { domain, id } }))];
|
|
35
31
|
}, []);
|
|
36
32
|
}
|
|
37
|
-
exports.
|
|
33
|
+
exports.flattenUserMap = flattenUserMap;
|
|
34
|
+
/**
|
|
35
|
+
* Will convert a list of qualified users to a UserMap
|
|
36
|
+
* @param users the list of users to convert
|
|
37
|
+
*/
|
|
38
|
+
function nestUsersList(users) {
|
|
39
|
+
return users.reduce((users, { data, userId: { domain, id } }) => {
|
|
40
|
+
if (!users[domain]) {
|
|
41
|
+
users[domain] = {};
|
|
42
|
+
}
|
|
43
|
+
users[domain][id] = data;
|
|
44
|
+
return users;
|
|
45
|
+
}, {});
|
|
46
|
+
}
|
|
47
|
+
exports.nestUsersList = nestUsersList;
|
|
@@ -27,15 +27,11 @@ describe('userClientsUtils', () => {
|
|
|
27
27
|
{ data: ['client11'], userId: { domain: 'domain1', id: 'user2' } },
|
|
28
28
|
{ data: ['client1', 'client2'], userId: { domain: 'domain2', id: 'user3' } },
|
|
29
29
|
];
|
|
30
|
-
expect((0, UserClientsUtil_1.
|
|
30
|
+
expect((0, UserClientsUtil_1.flattenUserMap)(payload)).toEqual(expected);
|
|
31
31
|
});
|
|
32
|
-
it('
|
|
33
|
-
const payload = { user1: ['client1'], user2: ['client11'], user3: ['client1', 'client2'] };
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
{ data: ['client11'], userId: { domain: '', id: 'user2' } },
|
|
37
|
-
{ data: ['client1', 'client2'], userId: { domain: '', id: 'user3' } },
|
|
38
|
-
];
|
|
39
|
-
expect((0, UserClientsUtil_1.flattenUserClients)(payload)).toEqual(expected);
|
|
32
|
+
it('nest and flatten are inverse operations', () => {
|
|
33
|
+
const payload = { domain1: { user1: ['client1'], user2: ['client11'] }, domain2: { user3: ['client1', 'client2'] } };
|
|
34
|
+
const result = (0, UserClientsUtil_1.nestUsersList)((0, UserClientsUtil_1.flattenUserMap)(payload));
|
|
35
|
+
expect(result).toEqual(payload);
|
|
40
36
|
});
|
|
41
37
|
});
|
|
@@ -13,6 +13,8 @@ type EncryptionResult = {
|
|
|
13
13
|
payloads: QualifiedOTRRecipients;
|
|
14
14
|
/** user-client that do not have prekeys on backend (deleted clients) */
|
|
15
15
|
unknowns?: QualifiedUserClients;
|
|
16
|
+
/** users for whom we could retrieve a prekey and, thus, for which we could not encrypt the message */
|
|
17
|
+
failed?: QualifiedId[];
|
|
16
18
|
};
|
|
17
19
|
export declare class ProteusService {
|
|
18
20
|
private readonly apiClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProteusService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/proteus/ProteusService/ProteusService.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,mCAAmC,CAAC;AACjE,OAAO,KAAK,EAAC,MAAM,EAAE,OAAO,EAAC,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EACV,YAAY,EAEZ,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAC,WAAW,EAAE,4BAA4B,EAAC,MAAM,8BAA8B,CAAC;AAI5F,OAAO,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAI5C,OAAO,KAAK,EACV,mCAAmC,EACnC,+BAA+B,EAC/B,oBAAoB,EACpB,wBAAwB,EACzB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAA0C,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAE1F,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAC,kBAAkB,EAAqB,MAAM,iBAAiB,CAAC;AAWvE,KAAK,gBAAgB,GAAG;IACtB,wEAAwE;IACxE,QAAQ,EAAE,sBAAsB,CAAC;IACjC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"ProteusService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/proteus/ProteusService/ProteusService.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,mCAAmC,CAAC;AACjE,OAAO,KAAK,EAAC,MAAM,EAAE,OAAO,EAAC,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EACV,YAAY,EAEZ,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAC,WAAW,EAAE,4BAA4B,EAAC,MAAM,8BAA8B,CAAC;AAI5F,OAAO,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAI5C,OAAO,KAAK,EACV,mCAAmC,EACnC,+BAA+B,EAC/B,oBAAoB,EACpB,wBAAwB,EACzB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAA0C,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAE1F,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAC,kBAAkB,EAAqB,MAAM,iBAAiB,CAAC;AAWvE,KAAK,gBAAgB,GAAG;IACtB,wEAAwE;IACxE,QAAQ,EAAE,sBAAsB,CAAC;IACjC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,sGAAsG;IACtG,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;CACxB,CAAC;AACF,qBAAa,cAAc;IAKvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IANzB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;gBAG/C,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,oBAAoB;IAKlC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC,GAAG,kBAAkB;IAiBhG,UAAU,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO;IAyB1D,YAAY,CAAC,OAAO,CAAC,EAAE,UAAU;IAIxC;;OAEG;IACI,mBAAmB;IAInB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAIxE;;;;;;OAMG;IACU,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAQ3E,kBAAkB,CAAC,EAC9B,gBAAgB,EAChB,YAAY,GACb,EAAE,+BAA+B,GAAG,OAAO,CAAC,YAAY,CAAC;IAiB7C,sBAAsB,CAAC,EAAC,cAAc,EAAE,gBAAgB,EAAC,EAAE,mCAAmC;IAI9F,WAAW,CAAC,EACvB,OAAO,EACP,cAAc,EACd,UAAU,EACV,UAAU,EACV,OAAO,EACP,gBAAgB,GACjB,EAAE,wBAAwB,GAAG,OAAO,CAAC,UAAU,CAAC;YA0CnC,OAAO;IAuBd,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM;IAQ7C,OAAO,CAClB,SAAS,EAAE,UAAU,EACrB,UAAU,EAAE,4BAA4B,GAAG,oBAAoB,GAC9D,OAAO,CAAC,gBAAgB,CAAC;IAiBtB,IAAI,CAAC,WAAW,CAAC,EAAE,UAAU;CAMpC"}
|
|
@@ -181,7 +181,7 @@ class ProteusService {
|
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
183
|
async encrypt(plainText, recipients) {
|
|
184
|
-
const { sessions, unknowns } = await (0, SessionHandler_1.initSessions)({
|
|
184
|
+
const { sessions, unknowns, failed } = await (0, SessionHandler_1.initSessions)({
|
|
185
185
|
recipients,
|
|
186
186
|
apiClient: this.apiClient,
|
|
187
187
|
cryptoClient: this.cryptoClient,
|
|
@@ -191,6 +191,7 @@ class ProteusService {
|
|
|
191
191
|
return {
|
|
192
192
|
payloads: (0, SessionHandler_1.buildEncryptedPayloads)(payloads),
|
|
193
193
|
unknowns,
|
|
194
|
+
failed,
|
|
194
195
|
};
|
|
195
196
|
}
|
|
196
197
|
async wipe(storeEngine) {
|
|
@@ -129,11 +129,13 @@ describe('ProteusService', () => {
|
|
|
129
129
|
const userId = { id: 'user1', domain: 'domain.com' };
|
|
130
130
|
const clientId = 'client1';
|
|
131
131
|
jest.spyOn(apiClient.api.user, 'postMultiPreKeyBundles').mockResolvedValue({
|
|
132
|
-
|
|
133
|
-
[userId.
|
|
134
|
-
[
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
qualified_user_client_prekeys: {
|
|
133
|
+
[userId.domain]: {
|
|
134
|
+
[userId.id]: {
|
|
135
|
+
[clientId]: {
|
|
136
|
+
id: 123,
|
|
137
|
+
key: 'pQABARhIAqEAWCCaJpFa9c626ORmjj1aV6OnOYgmTjfoiE3ynOfNfGAOmgOhAKEAWCD60VMzRrLfO+1GSjgyhnVp2N7L58DM+eeJhZJi1tBLfQT2',
|
|
138
|
+
},
|
|
137
139
|
},
|
|
138
140
|
},
|
|
139
141
|
},
|
|
@@ -281,18 +283,20 @@ describe('ProteusService', () => {
|
|
|
281
283
|
[secondUser.sessions.first, encryptedMessageBuffer],
|
|
282
284
|
]);
|
|
283
285
|
jest.spyOn(services.apiClient.api.user, 'postMultiPreKeyBundles').mockResolvedValue({
|
|
284
|
-
|
|
285
|
-
[
|
|
286
|
-
[firstUser.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
286
|
+
qualified_user_client_prekeys: {
|
|
287
|
+
[domain]: {
|
|
288
|
+
[firstUser.id.id]: {
|
|
289
|
+
[firstUser.clients.first]: null,
|
|
290
|
+
[firstUser.clients.second]: {
|
|
291
|
+
id: 123,
|
|
292
|
+
key: 'pQABARhIAqEAWCCaJpFa9c626ORmjj1aV6OnOYgmTjfoiE3ynOfNfGAOmgOhAKEAWCD60VMzRrLfO+1GSjgyhnVp2N7L58DM+eeJhZJi1tBLfQT2',
|
|
293
|
+
},
|
|
290
294
|
},
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
295
|
+
[secondUser.id.id]: {
|
|
296
|
+
[secondUser.clients.first]: {
|
|
297
|
+
id: 123,
|
|
298
|
+
key: 'pQABARhIAqEAWCCaJpFa9c626ORmjj1aV6OnOYgmTjfoiE3ynOfNfGAOmgOhAKEAWCD60VMzRrLfO+1GSjgyhnVp2N7L58DM+eeJhZJi1tBLfQT2',
|
|
299
|
+
},
|
|
296
300
|
},
|
|
297
301
|
},
|
|
298
302
|
},
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { APIClient } from '@wireapp/api-client/lib/APIClient';
|
|
2
2
|
import { QualifiedUserClients } from '@wireapp/api-client/lib/conversation';
|
|
3
|
-
import { QualifiedId
|
|
3
|
+
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
4
4
|
interface GetRecipientsForConversationQualifiedParams {
|
|
5
5
|
apiClient: APIClient;
|
|
6
6
|
conversationId: QualifiedId;
|
|
7
7
|
userIds?: QualifiedId[] | QualifiedUserClients;
|
|
8
8
|
}
|
|
9
|
-
declare const getRecipientsForConversation: ({ apiClient, conversationId, userIds, }: GetRecipientsForConversationQualifiedParams) => Promise<QualifiedUserClients
|
|
9
|
+
declare const getRecipientsForConversation: ({ apiClient, conversationId, userIds, }: GetRecipientsForConversationQualifiedParams) => Promise<QualifiedUserClients>;
|
|
10
10
|
export { getRecipientsForConversation };
|
|
11
11
|
//# sourceMappingURL=Recipients.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Recipients.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/proteus/Utility/Recipients.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,SAAS,EAAC,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"Recipients.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/proteus/Utility/Recipients.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,SAAS,EAAC,MAAM,mCAAmC,CAAC;AAE5D,OAAO,EAAC,oBAAoB,EAAC,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAczD,UAAU,2CAA2C;IACnD,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,WAAW,CAAC;IAC5B,OAAO,CAAC,EAAE,WAAW,EAAE,GAAG,oBAAoB,CAAC;CAChD;AAED,QAAA,MAAM,4BAA4B,4CAI/B,2CAA2C,KAAG,QAAQ,oBAAoB,CAQ5E,CAAC;AAEF,OAAO,EAAC,4BAA4B,EAAC,CAAC"}
|
|
@@ -19,14 +19,22 @@
|
|
|
19
19
|
*/
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
exports.getRecipientsForConversation = void 0;
|
|
22
|
-
const PreKeyBundle_1 = require("./PreKeyBundle/PreKeyBundle");
|
|
23
22
|
const getConversationQualifiedMembers_1 = require("../../../conversation/ConversationService/Utility/getConversationQualifiedMembers");
|
|
23
|
+
const UserClientsUtil_1 = require("../../../conversation/message/UserClientsUtil");
|
|
24
24
|
const util_1 = require("../../../util");
|
|
25
|
+
function toQualifiedUserClients(publicClients) {
|
|
26
|
+
const userList = (0, UserClientsUtil_1.flattenUserMap)(publicClients).map(({ userId, data: clientInfo }) => ({
|
|
27
|
+
userId,
|
|
28
|
+
data: clientInfo.map(client => client.id),
|
|
29
|
+
}));
|
|
30
|
+
return (0, UserClientsUtil_1.nestUsersList)(userList);
|
|
31
|
+
}
|
|
25
32
|
const getRecipientsForConversation = async ({ apiClient, conversationId, userIds, }) => {
|
|
26
33
|
if ((0, util_1.isQualifiedUserClients)(userIds)) {
|
|
27
34
|
return userIds;
|
|
28
35
|
}
|
|
29
36
|
const recipientIds = userIds || (await (0, getConversationQualifiedMembers_1.getConversationQualifiedMembers)({ apiClient: apiClient, conversationId }));
|
|
30
|
-
|
|
37
|
+
const allClients = await apiClient.api.user.postListClients({ qualified_users: recipientIds });
|
|
38
|
+
return toQualifiedUserClients(allClients.qualified_user_map);
|
|
31
39
|
};
|
|
32
40
|
exports.getRecipientsForConversation = getRecipientsForConversation;
|
|
@@ -14,6 +14,8 @@ type InitSessionsResult = {
|
|
|
14
14
|
sessions: string[];
|
|
15
15
|
/** client that do we do not have sessions with and that do not have existence on backend (deleted clients) */
|
|
16
16
|
unknowns?: QualifiedUserClients;
|
|
17
|
+
/** clients for which we had problem fetch prekeys (federated server down) */
|
|
18
|
+
failed?: QualifiedId[];
|
|
17
19
|
};
|
|
18
20
|
declare const constructSessionId: ({ userId, clientId }: ConstructSessionIdParams) => string;
|
|
19
21
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionHandler.d.ts","sourceRoot":"","sources":["../../../../../src/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,MAAM,EAAC,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAC,oBAAoB,EAAC,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAC,WAAW,EAAE,4BAA4B,EAAC,MAAM,8BAA8B,CAAC;AAEvF,OAAO,EAAC,MAAM,EAAC,MAAM,SAAS,CAAC;AAE/B,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAK9C,OAAO,EAAC,YAAY,EAAC,MAAM,mCAAmC,CAAC;AAE/D,UAAU,wBAAwB;IAChC,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,kBAAkB,GAAG;IACxB,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8GAA8G;IAC9G,QAAQ,CAAC,EAAE,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionHandler.d.ts","sourceRoot":"","sources":["../../../../../src/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,MAAM,EAAC,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAC,oBAAoB,EAAC,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAC,WAAW,EAAE,4BAA4B,EAAC,MAAM,8BAA8B,CAAC;AAEvF,OAAO,EAAC,MAAM,EAAC,MAAM,SAAS,CAAC;AAE/B,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAK9C,OAAO,EAAC,YAAY,EAAC,MAAM,mCAAmC,CAAC;AAE/D,UAAU,wBAAwB;IAChC,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,kBAAkB,GAAG;IACxB,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8GAA8G;IAC9G,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;CACxB,CAAC;AAEF,QAAA,MAAM,kBAAkB,yBAAwB,wBAAwB,KAAG,MAI1E,CAAC;AA6BF;;;GAGG;AACH,QAAA,MAAM,WAAW;YAC6B,WAAW;cAAY,MAAM;;;eAClC,SAAS;kBAAgB,YAAY;MAC3E,QAAQ,MAAM,CAUhB,CAAC;AAqBF,UAAU,wCAAwC;IAChD,UAAU,EAAE,oBAAoB,GAAG,4BAA4B,CAAC;IAChE,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,QAAA,MAAM,YAAY,qDAKf,wCAAwC,KAAG,QAAQ,kBAAkB,CAwDvE,CAAC;AAEF,UAAU,mBAAmB;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;CAC5B;AACD,iBAAe,aAAa,CAAC,MAAM,EAAE,mBAAmB,iBAGvD;AA4CD,KAAK,iBAAiB,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E;;GAEG;AACH,QAAA,MAAM,sBAAsB,uDAY3B,CAAC;AAEF,OAAO,EAAC,kBAAkB,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAC,CAAC"}
|
|
@@ -63,11 +63,12 @@ exports.initSession = initSession;
|
|
|
63
63
|
* @param {userClientMap} map of domain to (map of user IDs to client IDs) or map of user IDs containg the lists of clients
|
|
64
64
|
*/
|
|
65
65
|
const createSessions = async ({ recipients, apiClient, cryptoClient }) => {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
recipients:
|
|
66
|
+
const { qualified_user_client_prekeys: prekeysBundle, failed_to_list: failed } = await apiClient.api.user.postMultiPreKeyBundles(recipients);
|
|
67
|
+
const result = await createSessionsFromPreKeys({
|
|
68
|
+
recipients: prekeysBundle,
|
|
69
69
|
cryptoClient,
|
|
70
70
|
});
|
|
71
|
+
return Object.assign(Object.assign({}, result), { failed });
|
|
71
72
|
};
|
|
72
73
|
/**
|
|
73
74
|
* Will make sure all the sessions need to encrypt for those user/clients pair are set
|
|
@@ -77,7 +78,7 @@ const initSessions = async ({ recipients, apiClient, cryptoClient, logger, }) =>
|
|
|
77
78
|
const missingClients = {};
|
|
78
79
|
const missingClientsWithPrekeys = {};
|
|
79
80
|
const existingSessions = [];
|
|
80
|
-
const users = (0, UserClientsUtil_1.
|
|
81
|
+
const users = (0, UserClientsUtil_1.flattenUserMap)(recipients);
|
|
81
82
|
for (const user of users) {
|
|
82
83
|
const { userId, data } = user;
|
|
83
84
|
const clients = Array.isArray(data) ? data : Object.keys(data);
|
|
@@ -106,17 +107,18 @@ const initSessions = async ({ recipients, apiClient, cryptoClient, logger, }) =>
|
|
|
106
107
|
cryptoClient,
|
|
107
108
|
})
|
|
108
109
|
: { sessions: [], unknowns: {} };
|
|
109
|
-
const { sessions: created, unknowns } = Object.keys(missingClients).length > 0
|
|
110
|
+
const { sessions: created, failed, unknowns, } = Object.keys(missingClients).length > 0
|
|
110
111
|
? await createSessions({
|
|
111
112
|
recipients: missingClients,
|
|
112
113
|
apiClient,
|
|
113
114
|
cryptoClient,
|
|
114
115
|
logger,
|
|
115
116
|
})
|
|
116
|
-
: { sessions: [], unknowns:
|
|
117
|
+
: { sessions: [], failed: undefined, unknowns: undefined };
|
|
117
118
|
const allUnknowns = Object.assign(Object.assign({}, prekeyUnknows), unknowns);
|
|
118
119
|
return {
|
|
119
120
|
sessions: [...existingSessions, ...prekeyCreated, ...created],
|
|
121
|
+
failed,
|
|
120
122
|
unknowns: Object.keys(allUnknowns).length > 0 ? allUnknowns : undefined,
|
|
121
123
|
};
|
|
122
124
|
};
|
|
@@ -20,14 +20,29 @@
|
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
const api_client_1 = require("@wireapp/api-client");
|
|
22
22
|
const SessionHandler_1 = require("./SessionHandler");
|
|
23
|
-
function generatePrekeys(
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
function generatePrekeys(recipients) {
|
|
24
|
+
const prekeys = {};
|
|
25
|
+
const failed = [];
|
|
26
|
+
Object.entries(recipients).forEach(([domain, userClients]) => {
|
|
27
|
+
Object.entries(userClients).forEach(([userId, clientIds]) => {
|
|
28
|
+
if (domain.startsWith('offline:')) {
|
|
29
|
+
failed.push({ id: userId, domain });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const domainUsers = prekeys[domain] || {};
|
|
33
|
+
domainUsers[userId] = clientIds.reduce((acc, clientId, index) => {
|
|
34
|
+
const payload = clientId.startsWith('deleted:')
|
|
35
|
+
? null
|
|
36
|
+
: {
|
|
37
|
+
id: index,
|
|
38
|
+
key: 'pQABARn//wKhAFggJ1Fbpg5l6wnzKOJE+vXpRnkqUYhIvVnR5lNXEbO2o/0DoQChAFggHxZvgvtDktY/vqBcpjjo6rQnXvcNQhfwmy8AJQJKlD0E9g==',
|
|
39
|
+
};
|
|
40
|
+
return Object.assign(Object.assign({}, acc), { [clientId]: payload });
|
|
41
|
+
}, {});
|
|
42
|
+
prekeys[domain] = domainUsers;
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
return Promise.resolve({ qualified_user_client_prekeys: prekeys, failed_to_list: failed });
|
|
31
46
|
}
|
|
32
47
|
describe('SessionHandler', () => {
|
|
33
48
|
const cryptoClient = {
|
|
@@ -38,6 +53,9 @@ describe('SessionHandler', () => {
|
|
|
38
53
|
deleteSession: jest.fn(),
|
|
39
54
|
};
|
|
40
55
|
const apiClient = new api_client_1.APIClient({ urls: api_client_1.APIClient.BACKEND.STAGING });
|
|
56
|
+
beforeAll(() => {
|
|
57
|
+
jest.spyOn(apiClient.api.user, 'postMultiPreKeyBundles').mockImplementation(generatePrekeys);
|
|
58
|
+
});
|
|
41
59
|
describe('constructSessionId', () => {
|
|
42
60
|
describe('constructs a session ID', () => {
|
|
43
61
|
it('without a domain', () => {
|
|
@@ -70,22 +88,6 @@ describe('SessionHandler', () => {
|
|
|
70
88
|
const userId = { id: 'user1', domain: 'domain' };
|
|
71
89
|
const clientId = 'client1';
|
|
72
90
|
jest.spyOn(cryptoClient, 'sessionExists').mockResolvedValue(false);
|
|
73
|
-
jest
|
|
74
|
-
.spyOn(apiClient.api.user, 'postMultiPreKeyBundles')
|
|
75
|
-
.mockResolvedValue({ domain: generatePrekeys(userId, [clientId]) });
|
|
76
|
-
const sessionId = (0, SessionHandler_1.constructSessionId)({
|
|
77
|
-
userId,
|
|
78
|
-
clientId,
|
|
79
|
-
});
|
|
80
|
-
await (0, SessionHandler_1.initSession)({ userId, clientId }, { apiClient, cryptoClient });
|
|
81
|
-
expect(cryptoClient.sessionFromPrekey).toHaveBeenCalledWith(sessionId, expect.any(Object));
|
|
82
|
-
});
|
|
83
|
-
it('indicates the consumer if a session could not be created', async () => {
|
|
84
|
-
const userId = { id: 'user1', domain: 'domain' };
|
|
85
|
-
const clientId = 'client1';
|
|
86
|
-
jest
|
|
87
|
-
.spyOn(apiClient.api.user, 'postMultiPreKeyBundles')
|
|
88
|
-
.mockResolvedValue({ domain: generatePrekeys(userId, [clientId]) });
|
|
89
91
|
const sessionId = (0, SessionHandler_1.constructSessionId)({
|
|
90
92
|
userId,
|
|
91
93
|
clientId,
|
|
@@ -104,9 +106,6 @@ describe('SessionHandler', () => {
|
|
|
104
106
|
'missing-user1': ['client1'],
|
|
105
107
|
'missing-user2': ['client1', 'client2'],
|
|
106
108
|
};
|
|
107
|
-
jest.spyOn(apiClient.api.user, 'postMultiPreKeyBundles').mockResolvedValue({
|
|
108
|
-
domain: Object.assign(Object.assign({}, generatePrekeys({ id: 'missing-user1', domain: '' }, ['client1'])), generatePrekeys({ id: 'missing-user2', domain: '' }, ['client1', 'client2'])),
|
|
109
|
-
});
|
|
110
109
|
jest
|
|
111
110
|
.spyOn(cryptoClient, 'sessionExists')
|
|
112
111
|
.mockImplementation(sessionId => Promise.resolve(sessionId.includes('missing')));
|
|
@@ -121,18 +120,15 @@ describe('SessionHandler', () => {
|
|
|
121
120
|
});
|
|
122
121
|
it('returns the list of deleted clients (clients with null prekeys)', async () => {
|
|
123
122
|
const userClients = {
|
|
124
|
-
'existing-user1': ['client1', '
|
|
123
|
+
'existing-user1': ['client1', 'deleted:client2'],
|
|
125
124
|
};
|
|
126
|
-
const allKeys = { domain: generatePrekeys({ id: 'existing-user1', domain: 'domain' }, ['client1']) };
|
|
127
|
-
allKeys['domain']['existing-user1']['deleteclient'] = null;
|
|
128
|
-
jest.spyOn(apiClient.api.user, 'postMultiPreKeyBundles').mockResolvedValue(allKeys);
|
|
129
125
|
const { sessions, unknowns } = await (0, SessionHandler_1.initSessions)({
|
|
130
126
|
recipients: { domain: userClients },
|
|
131
127
|
apiClient,
|
|
132
128
|
cryptoClient,
|
|
133
129
|
});
|
|
134
130
|
expect(sessions).toEqual(['domain@existing-user1@client1']);
|
|
135
|
-
expect(unknowns).toEqual({ domain: { 'existing-user1': ['
|
|
131
|
+
expect(unknowns).toEqual({ domain: { 'existing-user1': ['deleted:client2'] } });
|
|
136
132
|
});
|
|
137
133
|
it('initializes sessions across multiple domains', async () => {
|
|
138
134
|
const userClients = {
|
|
@@ -148,5 +144,19 @@ describe('SessionHandler', () => {
|
|
|
148
144
|
expect(sessions).toEqual(['domain1@existing-user1@client11', 'domain2@existing-user2@client21']);
|
|
149
145
|
expect(unknowns).toBeUndefined();
|
|
150
146
|
});
|
|
147
|
+
it('returns failed session creation', async () => {
|
|
148
|
+
const recipients = {
|
|
149
|
+
domain1: { 'existing-user1': ['client1'] },
|
|
150
|
+
'offline:domain': { user2: ['client12'] },
|
|
151
|
+
};
|
|
152
|
+
jest.spyOn(cryptoClient, 'sessionExists').mockResolvedValue(false);
|
|
153
|
+
const { sessions, failed } = await (0, SessionHandler_1.initSessions)({
|
|
154
|
+
recipients,
|
|
155
|
+
apiClient,
|
|
156
|
+
cryptoClient,
|
|
157
|
+
});
|
|
158
|
+
expect(sessions).toEqual(['domain1@existing-user1@client1']);
|
|
159
|
+
expect(failed).toEqual([{ id: 'user2', domain: 'offline:domain' }]);
|
|
160
|
+
});
|
|
151
161
|
});
|
|
152
162
|
});
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"./lib/cryptography/AssetCryptography/crypto.node": "./lib/cryptography/AssetCryptography/crypto.browser.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@wireapp/api-client": "^23.
|
|
14
|
+
"@wireapp/api-client": "^23.1.0",
|
|
15
15
|
"@wireapp/commons": "^5.0.4",
|
|
16
16
|
"@wireapp/core-crypto": "0.6.2",
|
|
17
17
|
"@wireapp/cryptobox": "12.8.0",
|
|
@@ -60,6 +60,6 @@
|
|
|
60
60
|
"test:coverage": "jest --coverage",
|
|
61
61
|
"watch": "tsc --watch"
|
|
62
62
|
},
|
|
63
|
-
"version": "39.
|
|
64
|
-
"gitHead": "
|
|
63
|
+
"version": "39.1.1",
|
|
64
|
+
"gitHead": "1113dc9010564d42a335f3eb8a53f0797c92c746"
|
|
65
65
|
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { APIClient } from '@wireapp/api-client/lib/APIClient';
|
|
2
|
-
import { QualifiedUserClients, UserClients } from '@wireapp/api-client/lib/conversation';
|
|
3
|
-
import { QualifiedId, QualifiedUserPreKeyBundleMap, UserPreKeyBundleMap } from '@wireapp/api-client/lib/user';
|
|
4
|
-
declare const preKeyBundleToUserClients: (users: UserPreKeyBundleMap) => UserClients;
|
|
5
|
-
interface GetPreKeyBundleMapParams {
|
|
6
|
-
apiClient: APIClient;
|
|
7
|
-
conversationId: QualifiedId;
|
|
8
|
-
userIds?: string[] | QualifiedId[] | UserClients;
|
|
9
|
-
}
|
|
10
|
-
declare const getPreKeyBundleMap: ({ apiClient, conversationId, userIds, }: GetPreKeyBundleMapParams) => Promise<UserPreKeyBundleMap>;
|
|
11
|
-
/**
|
|
12
|
-
* Will generate a prekey bundle for specific users.
|
|
13
|
-
* If a QualifiedId array is given the bundle will contain all the clients from those users fetched from the server.
|
|
14
|
-
* If a QualifiedUserClients is provided then only the clients in the payload will be targeted (which could generate a ClientMismatch when sending messages)
|
|
15
|
-
*
|
|
16
|
-
* @param {QualifiedId[]|QualifiedUserClients} userIds - Targeted users.
|
|
17
|
-
* @returns {Promise<QualifiedUserPreKeyBundleMap}
|
|
18
|
-
*/
|
|
19
|
-
interface GetQualifiedPreKeyBundleMapParams {
|
|
20
|
-
apiClient: APIClient;
|
|
21
|
-
userIds?: QualifiedId[] | QualifiedUserClients;
|
|
22
|
-
}
|
|
23
|
-
declare const getQualifiedPreKeyBundle: ({ apiClient, userIds, }: GetQualifiedPreKeyBundleMapParams) => Promise<QualifiedUserPreKeyBundleMap>;
|
|
24
|
-
export { getPreKeyBundleMap, getQualifiedPreKeyBundle, preKeyBundleToUserClients };
|
|
25
|
-
//# sourceMappingURL=PreKeyBundle.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PreKeyBundle.d.ts","sourceRoot":"","sources":["../../../../../src/messagingProtocols/proteus/Utility/PreKeyBundle/PreKeyBundle.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,SAAS,EAAC,MAAM,mCAAmC,CAAC;AAC5D,OAAO,EAAC,oBAAoB,EAAE,WAAW,EAAC,MAAM,sCAAsC,CAAC;AACvF,OAAO,EAAC,WAAW,EAAE,4BAA4B,EAAE,mBAAmB,EAAC,MAAM,8BAA8B,CAAC;AAI5G,QAAA,MAAM,yBAAyB,UAAW,mBAAmB,KAAG,WAK/D,CAAC;AAEF,UAAU,wBAAwB;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,WAAW,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,GAAG,WAAW,CAAC;CAClD;AACD,QAAA,MAAM,kBAAkB,4CAIrB,wBAAwB,KAAG,QAAQ,mBAAmB,CA+BxD,CAAC;AAEF;;;;;;;GAOG;AACH,UAAU,iCAAiC;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,CAAC,EAAE,WAAW,EAAE,GAAG,oBAAoB,CAAC;CAChD;AACD,QAAA,MAAM,wBAAwB,4BAG3B,iCAAiC,KAAG,QAAQ,4BAA4B,CAoC1E,CAAC;AAEF,OAAO,EAAC,kBAAkB,EAAE,wBAAwB,EAAE,yBAAyB,EAAC,CAAC"}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Wire
|
|
4
|
-
* Copyright (C) 2022 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.preKeyBundleToUserClients = exports.getQualifiedPreKeyBundle = exports.getPreKeyBundleMap = void 0;
|
|
22
|
-
const util_1 = require("../../../../util");
|
|
23
|
-
const preKeyBundleToUserClients = (users) => {
|
|
24
|
-
return Object.entries(users).reduce((acc, [userId, clientsObj]) => {
|
|
25
|
-
acc[userId] = Object.keys(clientsObj);
|
|
26
|
-
return acc;
|
|
27
|
-
}, {});
|
|
28
|
-
};
|
|
29
|
-
exports.preKeyBundleToUserClients = preKeyBundleToUserClients;
|
|
30
|
-
const getPreKeyBundleMap = async ({ apiClient, conversationId, userIds = [], }) => {
|
|
31
|
-
let members = [];
|
|
32
|
-
if (userIds) {
|
|
33
|
-
if ((0, util_1.isStringArray)(userIds)) {
|
|
34
|
-
members = userIds;
|
|
35
|
-
}
|
|
36
|
-
else if ((0, util_1.isUserClients)(userIds)) {
|
|
37
|
-
members = Object.keys(userIds);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
if (!members.length) {
|
|
41
|
-
const conversation = await apiClient.api.conversation.getConversation(conversationId);
|
|
42
|
-
/*
|
|
43
|
-
* If you are sending a message to a conversation, you have to include
|
|
44
|
-
* yourself in the list of users if you want to sync a message also to your
|
|
45
|
-
* other clients.
|
|
46
|
-
*/
|
|
47
|
-
members = conversation.members.others.map(member => member.id).concat(conversation.members.self.id);
|
|
48
|
-
}
|
|
49
|
-
const preKeys = await Promise.all(members.map(member => apiClient.api.user.getUserPreKeys(member)));
|
|
50
|
-
return preKeys.reduce((bundleMap, bundle) => {
|
|
51
|
-
const userId = bundle.user;
|
|
52
|
-
bundleMap[userId] || (bundleMap[userId] = {});
|
|
53
|
-
for (const client of bundle.clients) {
|
|
54
|
-
bundleMap[userId][client.client] = client.prekey;
|
|
55
|
-
}
|
|
56
|
-
return bundleMap;
|
|
57
|
-
}, {});
|
|
58
|
-
};
|
|
59
|
-
exports.getPreKeyBundleMap = getPreKeyBundleMap;
|
|
60
|
-
const getQualifiedPreKeyBundle = async ({ apiClient, userIds, }) => {
|
|
61
|
-
let targets = [];
|
|
62
|
-
if (userIds) {
|
|
63
|
-
if ((0, util_1.isQualifiedIdArray)(userIds)) {
|
|
64
|
-
targets = userIds.map(id => ({ id }));
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
targets = Object.entries(userIds).reduce((accumulator, [domain, userClients]) => {
|
|
68
|
-
for (const userId in userClients) {
|
|
69
|
-
accumulator.push({ id: { id: userId, domain }, clients: userClients[userId] });
|
|
70
|
-
}
|
|
71
|
-
return accumulator;
|
|
72
|
-
}, []);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const preKeys = await Promise.all(targets.map(async ({ id: userId, clients }) => {
|
|
76
|
-
const prekeyBundle = await apiClient.api.user.getUserPreKeys(userId);
|
|
77
|
-
// We filter the clients that should not receive the message (if a QualifiedUserClients was given as parameter)
|
|
78
|
-
const userClients = clients
|
|
79
|
-
? prekeyBundle.clients.filter(client => clients.includes(client.client))
|
|
80
|
-
: prekeyBundle.clients;
|
|
81
|
-
return { user: userId, clients: userClients };
|
|
82
|
-
}));
|
|
83
|
-
return preKeys.reduce((bundleMap, qualifiedPrekey) => {
|
|
84
|
-
var _a, _b, _c;
|
|
85
|
-
bundleMap[_a = qualifiedPrekey.user.domain] || (bundleMap[_a] = {});
|
|
86
|
-
for (const client of qualifiedPrekey.clients) {
|
|
87
|
-
(_b = bundleMap[qualifiedPrekey.user.domain])[_c = qualifiedPrekey.user.id] || (_b[_c] = {});
|
|
88
|
-
bundleMap[qualifiedPrekey.user.domain][qualifiedPrekey.user.id][client.client] = client.prekey;
|
|
89
|
-
}
|
|
90
|
-
return bundleMap;
|
|
91
|
-
}, {});
|
|
92
|
-
};
|
|
93
|
-
exports.getQualifiedPreKeyBundle = getQualifiedPreKeyBundle;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PreKeyBundle.test.d.ts","sourceRoot":"","sources":["../../../../../src/messagingProtocols/proteus/Utility/PreKeyBundle/PreKeyBundle.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Wire
|
|
4
|
-
* Copyright (C) 2022 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 PreKeyBundle_1 = require("./PreKeyBundle");
|
|
22
|
-
const firstUser = {
|
|
23
|
-
id: 'bc0c99f1-49a5-4ad2-889a-62885af37088',
|
|
24
|
-
clients: { first: 'be67218b77d02d30', second: 'ae87218e77d02d30' },
|
|
25
|
-
};
|
|
26
|
-
const secondUser = {
|
|
27
|
-
id: 'bc0c99ff-ffa5-ffd2-ff9a-6ff85af3ff88',
|
|
28
|
-
clients: { first: 'kk67218b77d02d30', second: 'kk87218e77d02d30' },
|
|
29
|
-
};
|
|
30
|
-
const validPreKey = {
|
|
31
|
-
id: 1337,
|
|
32
|
-
key: 'pQABARn//wKhAFggJ1Fbpg5l6wnzKOJE+vXpRnkqUYhIvVnR5lNXEbO2o/0DoQChAFggHxZvgvtDktY/vqBcpjjo6rQnXvcNQhfwmy8AJQJKlD0E9g==',
|
|
33
|
-
};
|
|
34
|
-
describe('PrekeyHandler', () => {
|
|
35
|
-
describe('preKeyBundleToUserClients', () => {
|
|
36
|
-
it('maps preKeyBundle to userClients', () => {
|
|
37
|
-
const input = {
|
|
38
|
-
[firstUser.id]: { [firstUser.clients.first]: validPreKey },
|
|
39
|
-
};
|
|
40
|
-
const output = {
|
|
41
|
-
[firstUser.id]: [firstUser.clients.first],
|
|
42
|
-
};
|
|
43
|
-
expect((0, PreKeyBundle_1.preKeyBundleToUserClients)(input)).toEqual(output);
|
|
44
|
-
});
|
|
45
|
-
it('maps preKeyBundle to userClients (multiple clients)', () => {
|
|
46
|
-
const input = {
|
|
47
|
-
[firstUser.id]: { [firstUser.clients.first]: validPreKey, [firstUser.clients.second]: validPreKey },
|
|
48
|
-
};
|
|
49
|
-
const output = {
|
|
50
|
-
[firstUser.id]: [firstUser.clients.first, firstUser.clients.second],
|
|
51
|
-
};
|
|
52
|
-
expect((0, PreKeyBundle_1.preKeyBundleToUserClients)(input)).toEqual(output);
|
|
53
|
-
});
|
|
54
|
-
it('maps preKeyBundle to userClients (multiple users)', () => {
|
|
55
|
-
const input = {
|
|
56
|
-
[firstUser.id]: { [firstUser.clients.first]: validPreKey, [firstUser.clients.second]: validPreKey },
|
|
57
|
-
[secondUser.id]: { [secondUser.clients.first]: validPreKey, [secondUser.clients.second]: validPreKey },
|
|
58
|
-
};
|
|
59
|
-
const output = {
|
|
60
|
-
[firstUser.id]: [firstUser.clients.first, firstUser.clients.second],
|
|
61
|
-
[secondUser.id]: [secondUser.clients.first, secondUser.clients.second],
|
|
62
|
-
};
|
|
63
|
-
expect((0, PreKeyBundle_1.preKeyBundleToUserClients)(input)).toEqual(output);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/messagingProtocols/proteus/Utility/PreKeyBundle/index.ts"],"names":[],"mappings":"AAmBA,cAAc,gBAAgB,CAAC"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Wire
|
|
4
|
-
* Copyright (C) 2022 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
|
-
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
32
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
33
|
-
};
|
|
34
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
__exportStar(require("./PreKeyBundle"), exports);
|