@wireapp/core 41.0.0 → 41.2.0
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/conversation/ConversationService/ConversationService.d.ts +22 -1
- package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
- package/lib/conversation/ConversationService/ConversationService.js +46 -3
- package/lib/conversation/ConversationService/ConversationService.test.js +51 -0
- package/lib/errors/FederatedBackendsError.d.ts +9 -0
- package/lib/errors/FederatedBackendsError.d.ts.map +1 -0
- package/lib/errors/FederatedBackendsError.js +36 -0
- package/lib/errors/index.d.ts +3 -0
- package/lib/errors/index.d.ts.map +1 -0
- package/lib/errors/index.js +36 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts +8 -5
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.js +24 -23
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.test.js +45 -14
- package/lib/messagingProtocols/proteus/ProteusService/WithMockedGenerics.test.js +2 -10
- package/package.json +3 -3
|
@@ -9,6 +9,10 @@ import { MLSService } from '../../messagingProtocols/mls';
|
|
|
9
9
|
import { ProteusService } from '../../messagingProtocols/proteus';
|
|
10
10
|
import { AddUsersToProteusConversationParams, SendProteusMessageParams } from '../../messagingProtocols/proteus/ProteusService/ProteusService.types';
|
|
11
11
|
import { RemoteData } from '../content';
|
|
12
|
+
export declare enum AddUsersFailureReasons {
|
|
13
|
+
NON_FEDERATING_BACKENDS = "NON_FEDERATING_BACKENDS",
|
|
14
|
+
UNREACHABLE_BACKENDS = "UNREACHABLE_BACKENDS"
|
|
15
|
+
}
|
|
12
16
|
export declare class ConversationService {
|
|
13
17
|
private readonly apiClient;
|
|
14
18
|
private readonly proteusService;
|
|
@@ -27,6 +31,8 @@ export declare class ConversationService {
|
|
|
27
31
|
/**
|
|
28
32
|
* Create a group conversation.
|
|
29
33
|
*
|
|
34
|
+
* This method might fail with a `BackendsNotConnectedError` if there are users from not connected backends that are part of the payload
|
|
35
|
+
*
|
|
30
36
|
* @note Do not include yourself as the requestor
|
|
31
37
|
* @see https://staging-nginz-https.zinfra.io/swagger-ui/#!/conversations/createGroupConversation
|
|
32
38
|
*
|
|
@@ -40,7 +46,10 @@ export declare class ConversationService {
|
|
|
40
46
|
getUnencryptedAsset(assetId: string, assetToken?: string): Promise<ArrayBuffer>;
|
|
41
47
|
addUsersToProteusConversation(params: AddUsersToProteusConversationParams): Promise<{
|
|
42
48
|
event?: import("@wireapp/api-client/lib/event").ConversationMemberJoinEvent | undefined;
|
|
43
|
-
failedToAdd?:
|
|
49
|
+
failedToAdd?: {
|
|
50
|
+
reason: AddUsersFailureReasons;
|
|
51
|
+
users: QualifiedId[];
|
|
52
|
+
} | undefined;
|
|
44
53
|
}>;
|
|
45
54
|
removeUserFromConversation(conversationId: QualifiedId, userId: QualifiedId): Promise<ConversationMemberLeaveEvent>;
|
|
46
55
|
/**
|
|
@@ -89,5 +98,17 @@ export declare class ConversationService {
|
|
|
89
98
|
wipeMLSConversation(groupId: string): Promise<void>;
|
|
90
99
|
private matchesEpoch;
|
|
91
100
|
handleEpochMismatch(): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Will try registering mls 1:1 conversation adding the other user.
|
|
103
|
+
* If it fails and the conversation is already established, it will try joining via external commit instead.
|
|
104
|
+
*
|
|
105
|
+
* @param mlsConversation - mls 1:1 conversation
|
|
106
|
+
* @param selfUser - user and client ids of the self user
|
|
107
|
+
* @param otherUserId - id of the other user
|
|
108
|
+
*/
|
|
109
|
+
readonly establishMLS1to1Conversation: (groupId: string, selfUser: {
|
|
110
|
+
user: QualifiedId;
|
|
111
|
+
client: string;
|
|
112
|
+
}, otherUserId: QualifiedId) => Promise<void>;
|
|
92
113
|
}
|
|
93
114
|
//# sourceMappingURL=ConversationService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationService.d.ts","sourceRoot":"","sources":["../../../src/conversation/ConversationService/ConversationService.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,YAAY,EACZ,2BAA2B,EAC3B,WAAW,EACX,eAAe,EACf,oBAAoB,EAEpB,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAAC,4BAA4B,EAAC,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AACzD,OAAO,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAIvD,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAI9C,OAAO,EAAC,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,UAAU,EAAC,MAAM,6BAA6B,CAAC;AAE5G,OAAO,EAAC,YAAY,EAAuB,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AAEzF,OAAO,EAAC,UAAU,EAAuB,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAkC,cAAc,EAAC,MAAM,kCAAkC,CAAC;AACjG,OAAO,EACL,mCAAmC,EACnC,wBAAwB,EACzB,MAAM,sEAAsE,CAAC;AAG9E,OAAO,EAAC,UAAU,EAAC,MAAM,YAAY,CAAC;AAGtC,qBAAa,mBAAmB;IAK5B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAN/B,SAAgB,YAAY,EAAE,YAAY,CAAC;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgD;gBAGpD,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,cAAc,EAC9B,WAAW,CAAC,wBAAY;IAK3C,IAAI,UAAU,IAAI,UAAU,CAK3B;IAED;;;;;OAKG;IACU,2BAA2B,CAAC,cAAc,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAkBpG
|
|
1
|
+
{"version":3,"file":"ConversationService.d.ts","sourceRoot":"","sources":["../../../src/conversation/ConversationService/ConversationService.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,7 +21,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
21
21
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.ConversationService = void 0;
|
|
24
|
+
exports.ConversationService = exports.AddUsersFailureReasons = void 0;
|
|
25
25
|
const conversation_1 = require("@wireapp/api-client/lib/conversation");
|
|
26
26
|
const data_1 = require("@wireapp/api-client/lib/conversation/data");
|
|
27
27
|
const bazinga64_1 = require("bazinga64");
|
|
@@ -35,12 +35,44 @@ const proteus_1 = require("../../messagingProtocols/proteus");
|
|
|
35
35
|
const util_1 = require("../../util");
|
|
36
36
|
const fullyQualifiedClientIdUtils_1 = require("../../util/fullyQualifiedClientIdUtils");
|
|
37
37
|
const messageSender_1 = require("../message/messageSender");
|
|
38
|
+
var AddUsersFailureReasons;
|
|
39
|
+
(function (AddUsersFailureReasons) {
|
|
40
|
+
AddUsersFailureReasons["NON_FEDERATING_BACKENDS"] = "NON_FEDERATING_BACKENDS";
|
|
41
|
+
AddUsersFailureReasons["UNREACHABLE_BACKENDS"] = "UNREACHABLE_BACKENDS";
|
|
42
|
+
})(AddUsersFailureReasons || (exports.AddUsersFailureReasons = AddUsersFailureReasons = {}));
|
|
38
43
|
class ConversationService {
|
|
39
44
|
constructor(apiClient, proteusService, _mlsService) {
|
|
40
45
|
this.apiClient = apiClient;
|
|
41
46
|
this.proteusService = proteusService;
|
|
42
47
|
this._mlsService = _mlsService;
|
|
43
48
|
this.logger = (0, logdown_1.default)('@wireapp/core/ConversationService');
|
|
49
|
+
/**
|
|
50
|
+
* Will try registering mls 1:1 conversation adding the other user.
|
|
51
|
+
* If it fails and the conversation is already established, it will try joining via external commit instead.
|
|
52
|
+
*
|
|
53
|
+
* @param mlsConversation - mls 1:1 conversation
|
|
54
|
+
* @param selfUser - user and client ids of the self user
|
|
55
|
+
* @param otherUserId - id of the other user
|
|
56
|
+
*/
|
|
57
|
+
this.establishMLS1to1Conversation = async (groupId, selfUser, otherUserId) => {
|
|
58
|
+
try {
|
|
59
|
+
await this.mlsService.registerConversation(groupId, [otherUserId, selfUser.user], selfUser);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
this.logger.info(`Could not register MLS group with id ${groupId}.`);
|
|
63
|
+
const mlsConversation = await this.apiClient.api.conversation.getMLS1to1Conversation(otherUserId);
|
|
64
|
+
if (mlsConversation.epoch > 0) {
|
|
65
|
+
this.logger.info(`Conversation (id ${mlsConversation.qualified_id.id}) is already established, joining via external commit`);
|
|
66
|
+
// If its already established, we join with external commit
|
|
67
|
+
await this.joinByExternalCommit(mlsConversation.qualified_id);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
this.logger.info(`Conversation (id ${mlsConversation.qualified_id.id}) is not established, retrying to establish it`);
|
|
71
|
+
// If conversation is not established, we can wipe it and try to establish it again
|
|
72
|
+
await this.wipeMLSConversation(groupId);
|
|
73
|
+
return this.establishMLS1to1Conversation(groupId, selfUser, otherUserId);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
44
76
|
this.messageTimer = new conversation_2.MessageTimer();
|
|
45
77
|
}
|
|
46
78
|
get mlsService() {
|
|
@@ -68,8 +100,19 @@ class ConversationService {
|
|
|
68
100
|
}));
|
|
69
101
|
return qualifiedUserClients;
|
|
70
102
|
}
|
|
71
|
-
|
|
72
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Create a group conversation.
|
|
105
|
+
*
|
|
106
|
+
* This method might fail with a `BackendsNotConnectedError` if there are users from not connected backends that are part of the payload
|
|
107
|
+
*
|
|
108
|
+
* @note Do not include yourself as the requestor
|
|
109
|
+
* @see https://staging-nginz-https.zinfra.io/swagger-ui/#!/conversations/createGroupConversation
|
|
110
|
+
*
|
|
111
|
+
* @param conversationData Payload object for group creation
|
|
112
|
+
* @returns Resolves when the conversation was created
|
|
113
|
+
*/
|
|
114
|
+
async createProteusConversation(conversationData) {
|
|
115
|
+
return this.proteusService.createConversation(conversationData);
|
|
73
116
|
}
|
|
74
117
|
async getConversation(conversationId) {
|
|
75
118
|
return this.apiClient.api.conversation.getConversation(conversationId);
|
|
@@ -56,6 +56,8 @@ const mockedMLSService = {
|
|
|
56
56
|
commitPendingProposals: () => Promise.resolve(),
|
|
57
57
|
getEpoch: () => Promise.resolve(),
|
|
58
58
|
joinByExternalCommit: jest.fn(),
|
|
59
|
+
registerConversation: jest.fn(),
|
|
60
|
+
wipeConversation: jest.fn(),
|
|
59
61
|
};
|
|
60
62
|
const mockedProteusService = {
|
|
61
63
|
encryptGenericMessage: () => Promise.resolve(),
|
|
@@ -186,6 +188,55 @@ describe('ConversationService', () => {
|
|
|
186
188
|
expect(conversationService.joinByExternalCommit).not.toHaveBeenCalled();
|
|
187
189
|
});
|
|
188
190
|
});
|
|
191
|
+
describe('establishMLS1to1Conversation', () => {
|
|
192
|
+
it('successfully register an MLS group if it did not exist before', async () => {
|
|
193
|
+
const [conversationService, { mlsService }] = buildConversationService();
|
|
194
|
+
const mockGroupId = 'mock-group-id';
|
|
195
|
+
const selfUser = { user: { id: 'self-user-id', domain: 'staging.zinfra.io' }, client: 'self-user-client-id' };
|
|
196
|
+
const otherUserId = { id: 'other-user-id', domain: 'staging.zinfra.io' };
|
|
197
|
+
await conversationService.establishMLS1to1Conversation(mockGroupId, selfUser, otherUserId);
|
|
198
|
+
expect(mlsService.registerConversation).toHaveBeenCalledTimes(1);
|
|
199
|
+
expect(mlsService.registerConversation).toHaveBeenCalledWith(mockGroupId, [otherUserId, selfUser.user], selfUser);
|
|
200
|
+
expect(mlsService.joinByExternalCommit).not.toHaveBeenCalled();
|
|
201
|
+
expect(mlsService.wipeConversation).not.toHaveBeenCalled();
|
|
202
|
+
});
|
|
203
|
+
it('joins with external commit if epoch number is higher than 0', async () => {
|
|
204
|
+
const [conversationService, { apiClient, mlsService }] = buildConversationService();
|
|
205
|
+
const mockConversationId = { id: 'mock-conversation-id', domain: 'staging.zinfra.io' };
|
|
206
|
+
const mockGroupId = 'mock-group-id';
|
|
207
|
+
const selfUser = { user: { id: 'self-user-id', domain: 'staging.zinfra.io' }, client: 'self-user-client-id' };
|
|
208
|
+
const otherUserId = { id: 'other-user-id', domain: 'staging.zinfra.io' };
|
|
209
|
+
jest.spyOn(mlsService, 'registerConversation').mockRejectedValueOnce(undefined);
|
|
210
|
+
jest.spyOn(apiClient.api.conversation, 'getMLS1to1Conversation').mockResolvedValueOnce({
|
|
211
|
+
qualified_id: mockConversationId,
|
|
212
|
+
protocol: conversation_1.ConversationProtocol.MLS,
|
|
213
|
+
epoch: 1,
|
|
214
|
+
group_id: mockGroupId,
|
|
215
|
+
});
|
|
216
|
+
await conversationService.establishMLS1to1Conversation(mockGroupId, selfUser, otherUserId);
|
|
217
|
+
expect(mlsService.registerConversation).toHaveBeenCalledTimes(1);
|
|
218
|
+
expect(mlsService.registerConversation).toHaveBeenCalledWith(mockGroupId, [otherUserId, selfUser.user], selfUser);
|
|
219
|
+
expect(conversationService.joinByExternalCommit).toHaveBeenCalledWith(mockConversationId);
|
|
220
|
+
});
|
|
221
|
+
it('retries to register mls group if epoch number is equal 0', async () => {
|
|
222
|
+
const [conversationService, { apiClient, mlsService }] = buildConversationService();
|
|
223
|
+
const mockConversationId = { id: 'mock-conversation-id', domain: 'staging.zinfra.io' };
|
|
224
|
+
const mockGroupId = 'mock-group-id';
|
|
225
|
+
const selfUser = { user: { id: 'self-user-id', domain: 'staging.zinfra.io' }, client: 'self-user-client-id' };
|
|
226
|
+
const otherUserId = { id: 'other-user-id', domain: 'staging.zinfra.io' };
|
|
227
|
+
jest.spyOn(mlsService, 'registerConversation').mockRejectedValueOnce(undefined);
|
|
228
|
+
jest.spyOn(apiClient.api.conversation, 'getMLS1to1Conversation').mockResolvedValueOnce({
|
|
229
|
+
qualified_id: mockConversationId,
|
|
230
|
+
protocol: conversation_1.ConversationProtocol.MLS,
|
|
231
|
+
epoch: 0,
|
|
232
|
+
group_id: mockGroupId,
|
|
233
|
+
});
|
|
234
|
+
await conversationService.establishMLS1to1Conversation(mockGroupId, selfUser, otherUserId);
|
|
235
|
+
expect(mlsService.registerConversation).toHaveBeenCalledWith(mockGroupId, [otherUserId, selfUser.user], selfUser);
|
|
236
|
+
expect(mlsService.wipeConversation).toHaveBeenCalledWith(mockGroupId);
|
|
237
|
+
expect(mlsService.registerConversation).toHaveBeenCalledTimes(2);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
189
240
|
describe('fetchAllParticipantsClients', () => {
|
|
190
241
|
it('gives the members and clients of a federated conversation', async () => {
|
|
191
242
|
const [conversationService, { apiClient }] = buildConversationService();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This error means we are trying to add users that are parts of 2 backends that are not federating with each other to a new conversation.
|
|
3
|
+
*/
|
|
4
|
+
export declare class NonFederatingBackendsError extends Error {
|
|
5
|
+
readonly backends: string[];
|
|
6
|
+
constructor(backends: string[]);
|
|
7
|
+
}
|
|
8
|
+
export declare function isNonFederatingBackendsError(error: unknown): error is NonFederatingBackendsError;
|
|
9
|
+
//# sourceMappingURL=FederatedBackendsError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FederatedBackendsError.d.ts","sourceRoot":"","sources":["../../src/errors/FederatedBackendsError.ts"],"names":[],"mappings":"AAmBA;;GAEG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;aACvB,QAAQ,EAAE,MAAM,EAAE;gBAAlB,QAAQ,EAAE,MAAM,EAAE;CAI/C;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,0BAA0B,CAEhG"}
|
|
@@ -0,0 +1,36 @@
|
|
|
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.isNonFederatingBackendsError = exports.NonFederatingBackendsError = void 0;
|
|
22
|
+
/**
|
|
23
|
+
* This error means we are trying to add users that are parts of 2 backends that are not federating with each other to a new conversation.
|
|
24
|
+
*/
|
|
25
|
+
class NonFederatingBackendsError extends Error {
|
|
26
|
+
constructor(backends) {
|
|
27
|
+
super('2 backends are not connected');
|
|
28
|
+
this.backends = backends;
|
|
29
|
+
this.name = 'NonFederatingBackendError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.NonFederatingBackendsError = NonFederatingBackendsError;
|
|
33
|
+
function isNonFederatingBackendsError(error) {
|
|
34
|
+
return !!error && typeof error === 'object' && 'name' in error && error.name === 'NonFederatingBackendError';
|
|
35
|
+
}
|
|
36
|
+
exports.isNonFederatingBackendsError = isNonFederatingBackendsError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAmBA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
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("./DecryptionError"), exports);
|
|
36
|
+
__exportStar(require("./FederatedBackendsError"), exports);
|
package/lib/index.d.ts
CHANGED
|
@@ -5,4 +5,5 @@ export { CoreError } from './CoreError';
|
|
|
5
5
|
export * as cryptography from './cryptography/';
|
|
6
6
|
export * as util from './util';
|
|
7
7
|
export * as MessageBuilder from './conversation/message/MessageBuilder';
|
|
8
|
+
export * as errors from './errors';
|
|
8
9
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAC,MAAM,WAAW,CAAC;AAC1E,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,YAAY,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,YAAY,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,cAAc,MAAM,uCAAuC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAC,MAAM,WAAW,CAAC;AAC1E,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,YAAY,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,YAAY,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,cAAc,MAAM,uCAAuC,CAAC;AACxE,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -41,7 +41,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
41
41
|
return result;
|
|
42
42
|
};
|
|
43
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
-
exports.MessageBuilder = exports.util = exports.cryptography = exports.CoreError = exports.conversation = exports.auth = exports.ConnectionState = exports.Account = void 0;
|
|
44
|
+
exports.errors = exports.MessageBuilder = exports.util = exports.cryptography = exports.CoreError = exports.conversation = exports.auth = exports.ConnectionState = exports.Account = void 0;
|
|
45
45
|
var Account_1 = require("./Account");
|
|
46
46
|
Object.defineProperty(exports, "Account", { enumerable: true, get: function () { return Account_1.Account; } });
|
|
47
47
|
Object.defineProperty(exports, "ConnectionState", { enumerable: true, get: function () { return Account_1.ConnectionState; } });
|
|
@@ -52,3 +52,4 @@ Object.defineProperty(exports, "CoreError", { enumerable: true, get: function ()
|
|
|
52
52
|
exports.cryptography = __importStar(require("./cryptography/"));
|
|
53
53
|
exports.util = __importStar(require("./util"));
|
|
54
54
|
exports.MessageBuilder = __importStar(require("./conversation/message/MessageBuilder"));
|
|
55
|
+
exports.errors = __importStar(require("./errors"));
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { APIClient } from '@wireapp/api-client/lib/APIClient';
|
|
2
2
|
import type { PreKey, Context } from '@wireapp/api-client/lib/auth';
|
|
3
|
-
import { Conversation, QualifiedOTRRecipients, QualifiedUserClients } from '@wireapp/api-client/lib/conversation';
|
|
3
|
+
import { Conversation, NewConversation, QualifiedOTRRecipients, QualifiedUserClients } from '@wireapp/api-client/lib/conversation';
|
|
4
4
|
import type { ConversationMemberJoinEvent } from '@wireapp/api-client/lib/event';
|
|
5
5
|
import type { QualifiedId, QualifiedUserPreKeyBundleMap } from '@wireapp/api-client/lib/user';
|
|
6
6
|
import { CRUDEngine } from '@wireapp/store-engine';
|
|
7
7
|
import { CryptoClient } from './CryptoClient';
|
|
8
|
-
import type { AddUsersToProteusConversationParams,
|
|
9
|
-
import { SendResult } from '../../../conversation';
|
|
8
|
+
import type { AddUsersToProteusConversationParams, ProteusServiceConfig, SendProteusMessageParams } from './ProteusService.types';
|
|
9
|
+
import { AddUsersFailureReasons, SendResult } from '../../../conversation';
|
|
10
10
|
import type { EventHandlerResult } from '../../common.types';
|
|
11
11
|
import { EventHandlerParams } from '../EventHandler';
|
|
12
12
|
export type EncryptionResult = {
|
|
@@ -40,14 +40,17 @@ export declare class ProteusService {
|
|
|
40
40
|
* If not provided and the session doesn't exists it will fetch a new prekey from the backend
|
|
41
41
|
*/
|
|
42
42
|
getRemoteFingerprint(userId: QualifiedId, clientId: string, prekey?: PreKey): Promise<string>;
|
|
43
|
-
createConversation(
|
|
43
|
+
createConversation(conversationData: NewConversation): Promise<Conversation>;
|
|
44
44
|
/**
|
|
45
45
|
* Tries to add all the given users to the given conversation.
|
|
46
46
|
* If some users are not reachable, it will try to add the remaining users and list them in the `failedToAdd` property of the response.
|
|
47
47
|
*/
|
|
48
48
|
addUsersToConversation({ conversationId, qualifiedUsers }: AddUsersToProteusConversationParams): Promise<{
|
|
49
49
|
event?: ConversationMemberJoinEvent;
|
|
50
|
-
failedToAdd?:
|
|
50
|
+
failedToAdd?: {
|
|
51
|
+
reason: AddUsersFailureReasons;
|
|
52
|
+
users: QualifiedId[];
|
|
53
|
+
};
|
|
51
54
|
}>;
|
|
52
55
|
sendMessage({ userIds, conversationId, nativePush, targetMode, payload, onClientMismatch, }: SendProteusMessageParams): Promise<SendResult>;
|
|
53
56
|
private decrypt;
|
|
@@ -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,EACL,YAAY,
|
|
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,EACL,YAAY,EAGZ,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,+BAA+B,CAAC;AAC/E,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,oBAAoB,EACpB,wBAAwB,EACzB,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EAAC,sBAAsB,EAA2C,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAGlH,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAC,kBAAkB,EAAqB,MAAM,iBAAiB,CAAC;AAWvE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,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;AAEF,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;IA2B1D,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,gBAAgB,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC;IAiCzF;;;OAGG;IACU,sBAAsB,CAAC,EAAC,cAAc,EAAE,cAAc,EAAC,EAAE,mCAAmC,GAAG,OAAO,CAAC;QAClH,KAAK,CAAC,EAAE,2BAA2B,CAAC;QACpC,WAAW,CAAC,EAAE;YAAC,MAAM,EAAE,sBAAsB,CAAC;YAAC,KAAK,EAAE,WAAW,EAAE,CAAA;SAAC,CAAC;KACtE,CAAC;IAqCW,WAAW,CAAC,EACvB,OAAO,EACP,cAAc,EACd,UAAU,EACV,UAAU,EACV,OAAO,EACP,gBAAgB,GACjB,EAAE,wBAAwB,GAAG,OAAO,CAAC,UAAU,CAAC;YA6CnC,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"}
|
|
@@ -32,6 +32,7 @@ const sessionIdMigrator_1 = require("./sessionIdMigrator");
|
|
|
32
32
|
const userDomainFilters_1 = require("./userDomainFilters");
|
|
33
33
|
const conversation_2 = require("../../../conversation");
|
|
34
34
|
const MessageService_1 = require("../../../conversation/message/MessageService");
|
|
35
|
+
const errors_1 = require("../../../errors");
|
|
35
36
|
const EventHandler_1 = require("../EventHandler");
|
|
36
37
|
const getGenericMessageParams_1 = require("../Utility/getGenericMessageParams");
|
|
37
38
|
const isClearFromMismatch_1 = require("../Utility/isClearFromMismatch");
|
|
@@ -106,32 +107,25 @@ class ProteusService {
|
|
|
106
107
|
const sessionId = await (0, SessionHandler_1.initSession)({ userId, clientId, initialPrekey: prekey }, { cryptoClient: this.cryptoClient, apiClient: this.apiClient });
|
|
107
108
|
return this.cryptoClient.getRemoteFingerprint(sessionId);
|
|
108
109
|
}
|
|
109
|
-
async createConversation(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
payload = {
|
|
114
|
-
name: conversationData,
|
|
115
|
-
receipt_mode: null,
|
|
116
|
-
users: ids !== null && ids !== void 0 ? ids : [],
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
payload = conversationData;
|
|
110
|
+
async createConversation(conversationData) {
|
|
111
|
+
var _a;
|
|
112
|
+
try {
|
|
113
|
+
return await this.apiClient.api.conversation.postConversation(conversationData);
|
|
121
114
|
}
|
|
122
|
-
|
|
123
|
-
var _a;
|
|
115
|
+
catch (error) {
|
|
124
116
|
if ((0, conversation_1.isFederatedBackendsError)(error)) {
|
|
125
117
|
switch (error.label) {
|
|
118
|
+
case conversation_1.FederatedBackendsErrorLabel.NON_FEDERATING_BACKENDS: {
|
|
119
|
+
// In case we are trying to create a conversation with users from 2 backends that are not connected, we should stop the procedure and throw an error
|
|
120
|
+
throw new errors_1.NonFederatingBackendsError(error.backends);
|
|
121
|
+
}
|
|
126
122
|
case conversation_1.FederatedBackendsErrorLabel.UNREACHABLE_BACKENDS: {
|
|
127
123
|
const { backends } = error;
|
|
128
|
-
const { excludedUsers: unreachableUsers, includedUsers: availableUsers } = (0, userDomainFilters_1.filterUsersFromDomains)((_a =
|
|
129
|
-
|
|
124
|
+
const { excludedUsers: unreachableUsers, includedUsers: availableUsers } = (0, userDomainFilters_1.filterUsersFromDomains)((_a = conversationData.qualified_users) !== null && _a !== void 0 ? _a : [], backends);
|
|
125
|
+
conversationData = Object.assign(Object.assign({}, conversationData), { qualified_users: availableUsers });
|
|
130
126
|
// If conversation creation returns an error because a backend is offline,
|
|
131
127
|
// we try creating the conversation again with users from available backends
|
|
132
|
-
const response = await this.apiClient.api.conversation.postConversation(
|
|
133
|
-
throw error;
|
|
134
|
-
});
|
|
128
|
+
const response = await this.apiClient.api.conversation.postConversation(conversationData);
|
|
135
129
|
// on a succesfull conversation creation with the available users,
|
|
136
130
|
// we append the users from an unreachable backend to the response
|
|
137
131
|
response.failed_to_add = unreachableUsers;
|
|
@@ -140,7 +134,7 @@ class ProteusService {
|
|
|
140
134
|
}
|
|
141
135
|
}
|
|
142
136
|
throw error;
|
|
143
|
-
}
|
|
137
|
+
}
|
|
144
138
|
}
|
|
145
139
|
/**
|
|
146
140
|
* Tries to add all the given users to the given conversation.
|
|
@@ -151,19 +145,26 @@ class ProteusService {
|
|
|
151
145
|
return { event: await this.apiClient.api.conversation.postMembers(conversationId, qualifiedUsers) };
|
|
152
146
|
}
|
|
153
147
|
catch (error) {
|
|
148
|
+
const failureReasonsMap = {
|
|
149
|
+
[conversation_1.FederatedBackendsErrorLabel.NON_FEDERATING_BACKENDS]: conversation_2.AddUsersFailureReasons.NON_FEDERATING_BACKENDS,
|
|
150
|
+
[conversation_1.FederatedBackendsErrorLabel.UNREACHABLE_BACKENDS]: conversation_2.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
|
|
151
|
+
};
|
|
154
152
|
if ((0, conversation_1.isFederatedBackendsError)(error)) {
|
|
155
153
|
switch (error.label) {
|
|
154
|
+
case conversation_1.FederatedBackendsErrorLabel.NON_FEDERATING_BACKENDS:
|
|
156
155
|
case conversation_1.FederatedBackendsErrorLabel.UNREACHABLE_BACKENDS: {
|
|
157
156
|
const { backends } = error;
|
|
158
157
|
const { excludedUsers: unreachableUsers, includedUsers: availableUsers } = (0, userDomainFilters_1.filterUsersFromDomains)(qualifiedUsers, backends);
|
|
159
158
|
if (availableUsers.length === 0) {
|
|
160
|
-
return { failedToAdd: unreachableUsers };
|
|
159
|
+
return { failedToAdd: { reason: failureReasonsMap[error.label], users: unreachableUsers } };
|
|
161
160
|
}
|
|
162
|
-
// In case the request to add users failed with a `UNREACHABLE_BACKENDS`
|
|
161
|
+
// In case the request to add users failed with a `UNREACHABLE_BACKENDS` or `NOT_CONNECTED_BACKENDS` errors, we try again with the users from available backends
|
|
163
162
|
const response = await this.apiClient.api.conversation.postMembers(conversationId, availableUsers);
|
|
164
163
|
return {
|
|
165
164
|
event: response,
|
|
166
|
-
failedToAdd: unreachableUsers
|
|
165
|
+
failedToAdd: unreachableUsers.length > 0
|
|
166
|
+
? { reason: failureReasonsMap[error.label], users: unreachableUsers }
|
|
167
|
+
: undefined,
|
|
167
168
|
};
|
|
168
169
|
}
|
|
169
170
|
}
|
|
@@ -51,6 +51,7 @@ const SessionHandler_1 = require("../Utility/SessionHandler");
|
|
|
51
51
|
const notification_1 = require("../../../notification");
|
|
52
52
|
const event_1 = require("@wireapp/api-client/lib/event");
|
|
53
53
|
const protocol_messaging_1 = require("@wireapp/protocol-messaging");
|
|
54
|
+
const errors_1 = require("../../../errors");
|
|
54
55
|
jest.mock('./CryptoClient/CoreCryptoWrapper/PrekeysTracker', () => {
|
|
55
56
|
return {
|
|
56
57
|
PrekeyTracker: jest.fn().mockImplementation(() => {
|
|
@@ -487,7 +488,8 @@ describe('ProteusService', () => {
|
|
|
487
488
|
const conversationId = { id: 'conv1', domain: 'domain1' };
|
|
488
489
|
const userDomain1 = { id: 'user-1-1', domain: 'domain1' };
|
|
489
490
|
const user2Domain1 = { id: 'user-2-1', domain: 'domain1' };
|
|
490
|
-
const userDomain2 = { id: 'user-
|
|
491
|
+
const userDomain2 = { id: 'user-1-2', domain: 'domain2' };
|
|
492
|
+
const userDomain3 = { id: 'user-1-3', domain: 'domain3' };
|
|
491
493
|
it('adds all requested users to an existing conversation', async () => {
|
|
492
494
|
const [proteusService, { apiClient }] = await (0, ProteusService_mocks_1.buildProteusService)();
|
|
493
495
|
jest.spyOn(apiClient.api.conversation, 'postMembers').mockResolvedValueOnce(baseResponse.event);
|
|
@@ -498,6 +500,7 @@ describe('ProteusService', () => {
|
|
|
498
500
|
expect(event).toEqual(baseResponse);
|
|
499
501
|
});
|
|
500
502
|
it('partially add users if some backends are unreachable', async () => {
|
|
503
|
+
var _a, _b;
|
|
501
504
|
const [proteusService, { apiClient }] = await (0, ProteusService_mocks_1.buildProteusService)();
|
|
502
505
|
const postMembersSpy = jest
|
|
503
506
|
.spyOn(apiClient.api.conversation, 'postMembers')
|
|
@@ -510,7 +513,28 @@ describe('ProteusService', () => {
|
|
|
510
513
|
expect(postMembersSpy).toHaveBeenCalledTimes(2);
|
|
511
514
|
expect(postMembersSpy).toHaveBeenCalledWith(conversationId, expect.arrayContaining([userDomain1, user2Domain1, userDomain2]));
|
|
512
515
|
expect(postMembersSpy).toHaveBeenCalledWith(conversationId, expect.arrayContaining([userDomain2]));
|
|
513
|
-
expect(result.failedToAdd).
|
|
516
|
+
expect((_a = result.failedToAdd) === null || _a === void 0 ? void 0 : _a.reason).toBe(conversation_2.AddUsersFailureReasons.UNREACHABLE_BACKENDS);
|
|
517
|
+
expect((_b = result.failedToAdd) === null || _b === void 0 ? void 0 : _b.users).toEqual([userDomain1, user2Domain1]);
|
|
518
|
+
});
|
|
519
|
+
it('partially add users if some users are part of not-connected backends', async () => {
|
|
520
|
+
var _a, _b;
|
|
521
|
+
const [proteusService, { apiClient }] = await (0, ProteusService_mocks_1.buildProteusService)();
|
|
522
|
+
const postMembersSpy = jest
|
|
523
|
+
.spyOn(apiClient.api.conversation, 'postMembers')
|
|
524
|
+
.mockRejectedValueOnce(new conversation_1.FederatedBackendsError(conversation_1.FederatedBackendsErrorLabel.NON_FEDERATING_BACKENDS, [
|
|
525
|
+
userDomain2.domain,
|
|
526
|
+
userDomain3.domain,
|
|
527
|
+
]))
|
|
528
|
+
.mockResolvedValueOnce(baseResponse.event);
|
|
529
|
+
const result = await proteusService.addUsersToConversation({
|
|
530
|
+
conversationId,
|
|
531
|
+
qualifiedUsers: [userDomain1, user2Domain1, userDomain2, userDomain3],
|
|
532
|
+
});
|
|
533
|
+
expect(postMembersSpy).toHaveBeenCalledTimes(2);
|
|
534
|
+
expect(postMembersSpy).toHaveBeenCalledWith(conversationId, expect.arrayContaining([userDomain1, user2Domain1, userDomain2]));
|
|
535
|
+
expect(postMembersSpy).toHaveBeenCalledWith(conversationId, expect.arrayContaining([userDomain1, user2Domain1]));
|
|
536
|
+
expect((_a = result.failedToAdd) === null || _a === void 0 ? void 0 : _a.reason).toBe(conversation_2.AddUsersFailureReasons.NON_FEDERATING_BACKENDS);
|
|
537
|
+
expect((_b = result.failedToAdd) === null || _b === void 0 ? void 0 : _b.users).toEqual([userDomain2, userDomain3]);
|
|
514
538
|
});
|
|
515
539
|
});
|
|
516
540
|
describe('createConversation', () => {
|
|
@@ -545,10 +569,8 @@ describe('ProteusService', () => {
|
|
|
545
569
|
const [proteusService, { apiClient }] = await (0, ProteusService_mocks_1.buildProteusService)();
|
|
546
570
|
jest.spyOn(apiClient.api.conversation, 'postConversation').mockResolvedValueOnce(Object.assign({}, newConversation));
|
|
547
571
|
const result = await proteusService.createConversation({
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
qualified_users: [userDomain1, user2Domain1, userDomain2],
|
|
551
|
-
},
|
|
572
|
+
receipt_mode: null,
|
|
573
|
+
qualified_users: [userDomain1, user2Domain1, userDomain2],
|
|
552
574
|
});
|
|
553
575
|
expect(result).toEqual(newConversation);
|
|
554
576
|
});
|
|
@@ -559,10 +581,8 @@ describe('ProteusService', () => {
|
|
|
559
581
|
.mockRejectedValueOnce(new conversation_1.FederatedBackendsError(conversation_1.FederatedBackendsErrorLabel.UNREACHABLE_BACKENDS, [userDomain1.domain]))
|
|
560
582
|
.mockResolvedValueOnce(newConversation);
|
|
561
583
|
const result = await proteusService.createConversation({
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
qualified_users: [userDomain1, user2Domain1, userDomain2],
|
|
565
|
-
},
|
|
584
|
+
receipt_mode: null,
|
|
585
|
+
qualified_users: [userDomain1, user2Domain1, userDomain2],
|
|
566
586
|
});
|
|
567
587
|
expect(postConversationSpy).toHaveBeenCalledTimes(2);
|
|
568
588
|
expect(postConversationSpy).toHaveBeenCalledWith(expect.objectContaining({ qualified_users: [userDomain1, user2Domain1, userDomain2] }));
|
|
@@ -579,15 +599,26 @@ describe('ProteusService', () => {
|
|
|
579
599
|
]))
|
|
580
600
|
.mockResolvedValueOnce({});
|
|
581
601
|
const result = await proteusService.createConversation({
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
qualified_users: [userDomain1, user2Domain1, userDomain2],
|
|
585
|
-
},
|
|
602
|
+
receipt_mode: null,
|
|
603
|
+
qualified_users: [userDomain1, user2Domain1, userDomain2],
|
|
586
604
|
});
|
|
587
605
|
expect(postConversationSpy).toHaveBeenCalledTimes(2);
|
|
588
606
|
expect(postConversationSpy).toHaveBeenCalledWith(expect.objectContaining({ qualified_users: [userDomain1, user2Domain1, userDomain2] }));
|
|
589
607
|
expect(postConversationSpy).toHaveBeenCalledWith(expect.objectContaining({ qualified_users: [] }));
|
|
590
608
|
expect(result.failed_to_add).toEqual([userDomain1, user2Domain1, userDomain2]);
|
|
591
609
|
});
|
|
610
|
+
it('fails to create a conversation if there are users from non-connected backends', async () => {
|
|
611
|
+
const [proteusService, { apiClient }] = await (0, ProteusService_mocks_1.buildProteusService)();
|
|
612
|
+
jest
|
|
613
|
+
.spyOn(apiClient.api.conversation, 'postConversation')
|
|
614
|
+
.mockRejectedValueOnce(new conversation_1.FederatedBackendsError(conversation_1.FederatedBackendsErrorLabel.NON_FEDERATING_BACKENDS, [
|
|
615
|
+
userDomain1.domain,
|
|
616
|
+
userDomain2.domain,
|
|
617
|
+
]));
|
|
618
|
+
await expect(() => proteusService.createConversation({
|
|
619
|
+
receipt_mode: null,
|
|
620
|
+
qualified_users: [userDomain1, user2Domain1, userDomain2],
|
|
621
|
+
})).rejects.toThrow(errors_1.NonFederatingBackendsError);
|
|
622
|
+
});
|
|
592
623
|
});
|
|
593
624
|
});
|
|
@@ -102,22 +102,14 @@ describe('createConversation', () => {
|
|
|
102
102
|
it('when a new conversation object is given', async () => {
|
|
103
103
|
const proteusService = await prepareProteusService();
|
|
104
104
|
const conversationData = createConversationResult;
|
|
105
|
-
const returnData = await proteusService.createConversation(
|
|
105
|
+
const returnData = await proteusService.createConversation(conversationData);
|
|
106
106
|
expect(returnData).toStrictEqual(createConversationResult);
|
|
107
107
|
});
|
|
108
108
|
it('create a new conversation with no name', async () => {
|
|
109
109
|
const proteusService = await prepareProteusService();
|
|
110
|
-
const otherUserIds = ['user1', 'user2'];
|
|
111
110
|
const conversationData = { users: ['user1', 'user2'], receipt_mode: null };
|
|
112
|
-
const returnData = await proteusService.createConversation(
|
|
111
|
+
const returnData = await proteusService.createConversation(conversationData);
|
|
113
112
|
expect(returnData).toStrictEqual(conversationData);
|
|
114
113
|
});
|
|
115
|
-
it('when a conversation string and userIds are given', async () => {
|
|
116
|
-
const proteusService = await prepareProteusService();
|
|
117
|
-
const otherUserIds = ['user1', 'user2'];
|
|
118
|
-
const conversationData = 'test';
|
|
119
|
-
const returnData = await proteusService.createConversation({ conversationData, otherUserIds });
|
|
120
|
-
expect(returnData).toStrictEqual(createConversationResult);
|
|
121
|
-
});
|
|
122
114
|
});
|
|
123
115
|
});
|
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": "^25.
|
|
14
|
+
"@wireapp/api-client": "^25.2.0",
|
|
15
15
|
"@wireapp/commons": "^5.1.0",
|
|
16
16
|
"@wireapp/core-crypto": "1.0.0-rc.6",
|
|
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": "41.
|
|
64
|
-
"gitHead": "
|
|
63
|
+
"version": "41.2.0",
|
|
64
|
+
"gitHead": "139c43189700e34d69f734596cfd6e3f12732ff3"
|
|
65
65
|
}
|