@wireapp/core 40.5.2-1 → 40.5.3-beta.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/LICENSE +674 -0
- package/lib/Account.d.ts +9 -7
- package/lib/Account.d.ts.map +1 -1
- package/lib/Account.js +32 -35
- package/lib/CoreError.js +1 -1
- package/lib/broadcast/BroadcastService.d.ts +2 -11
- package/lib/broadcast/BroadcastService.d.ts.map +1 -1
- package/lib/broadcast/BroadcastService.js +5 -39
- package/lib/client/ClientDatabaseRepository.d.ts +5 -5
- package/lib/client/ClientDatabaseRepository.d.ts.map +1 -1
- package/lib/client/ClientDatabaseRepository.js +10 -17
- package/lib/client/ClientService.d.ts +5 -1
- package/lib/client/ClientService.d.ts.map +1 -1
- package/lib/client/ClientService.js +11 -9
- package/lib/connection/ConnectionService.d.ts +2 -2
- package/lib/connection/ConnectionService.d.ts.map +1 -1
- package/lib/connection/ConnectionService.js +2 -2
- package/lib/conversation/AssetTransferState.js +1 -1
- package/lib/conversation/ConversationService/ConversationService.d.ts +12 -5
- package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
- package/lib/conversation/ConversationService/ConversationService.js +26 -11
- package/lib/conversation/ConversationService/ConversationService.test.js +1 -1
- package/lib/conversation/ConversationService/ConversationService.types.d.ts +12 -11
- package/lib/conversation/ConversationService/ConversationService.types.d.ts.map +1 -1
- package/lib/conversation/ConversationService/ConversationService.types.js +1 -1
- package/lib/conversation/ConversationService/Utility/getConversationQualifiedMembers.d.ts +1 -1
- package/lib/conversation/ConversationService/Utility/getConversationQualifiedMembers.d.ts.map +1 -1
- package/lib/conversation/GenericMessageType.js +1 -1
- package/lib/conversation/ReactionType.d.ts +1 -4
- package/lib/conversation/ReactionType.d.ts.map +1 -1
- package/lib/conversation/ReactionType.js +0 -6
- package/lib/conversation/message/Message.types.js +1 -1
- package/lib/conversation/message/MessageBuilder.d.ts +1 -1
- package/lib/conversation/message/MessageBuilder.d.ts.map +1 -1
- package/lib/conversation/message/MessageBuilder.js +2 -2
- package/lib/conversation/message/MessageService.d.ts +6 -31
- package/lib/conversation/message/MessageService.d.ts.map +1 -1
- package/lib/conversation/message/MessageService.js +19 -162
- package/lib/conversation/message/MessageService.test.js +151 -141
- package/lib/conversation/message/PayloadBundle.js +1 -1
- 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/mls/EventHandler/EventHandler.d.ts +1 -1
- package/lib/messagingProtocols/mls/EventHandler/EventHandler.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.js +7 -2
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.js +2 -0
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.test.js +3 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +20 -8
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.js +81 -40
- package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +9 -0
- package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.d.ts +1 -1
- package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.js +5 -5
- package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.test.js +3 -3
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.d.ts +13 -0
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.js +67 -0
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.test.d.ts +2 -0
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.test.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.test.js +72 -0
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts +10 -5
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.js +33 -11
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/PrekeysTracker/PrekeysTracker.d.ts +2 -3
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/PrekeysTracker/PrekeysTracker.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/PrekeysTracker/PrekeysTracker.js +8 -9
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/PrekeysTracker/PrekeysTracker.store.d.ts +4 -9
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/PrekeysTracker/PrekeysTracker.store.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/PrekeysTracker/PrekeysTracker.store.js +10 -24
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/PrekeysTracker/PrekeysTracker.test.js +2 -10
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.d.ts +1 -2
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.js +3 -3
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts +2 -2
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoboxWrapper.d.ts +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoboxWrapper.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoboxWrapper.js +2 -2
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts +14 -7
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.js +31 -35
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.js +2 -3
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.test.js +109 -89
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts +6 -9
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/Utility/Recipients.d.ts +4 -10
- package/lib/messagingProtocols/proteus/Utility/Recipients.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/Utility/Recipients.js +16 -16
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.d.ts +15 -10
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.js +80 -92
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.test.js +70 -54
- package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts +5 -14
- package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.js +3 -35
- package/lib/messagingProtocols/proteus/Utility/isClearFromMismatch.d.ts +2 -2
- package/lib/messagingProtocols/proteus/Utility/isClearFromMismatch.d.ts.map +1 -1
- package/lib/notification/NotificationDatabaseRepository.js +1 -1
- package/lib/notification/Notifications.types.js +1 -1
- package/lib/user/UserService.d.ts +6 -17
- package/lib/user/UserService.d.ts.map +1 -1
- package/lib/user/UserService.js +2 -47
- package/lib/util/TaskScheduler/TaskScheduler.d.ts +4 -1
- package/lib/util/TaskScheduler/TaskScheduler.d.ts.map +1 -1
- package/lib/util/TaskScheduler/TaskScheduler.js +24 -3
- package/lib/util/TaskScheduler/TaskScheduler.store.d.ts +7 -0
- package/lib/util/TaskScheduler/TaskScheduler.store.d.ts.map +1 -0
- package/lib/util/TaskScheduler/TaskScheduler.store.js +34 -0
- package/lib/util/TypePredicateUtil.d.ts +0 -1
- package/lib/util/TypePredicateUtil.d.ts.map +1 -1
- package/lib/util/TypePredicateUtil.js +1 -2
- package/package.json +7 -7
- package/lib/messagingProtocols/mls/MLSService/stores/keyMaterialUpdatesStore/index.d.ts +0 -2
- package/lib/messagingProtocols/mls/MLSService/stores/keyMaterialUpdatesStore/index.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/stores/keyMaterialUpdatesStore/index.js +0 -35
- package/lib/messagingProtocols/mls/MLSService/stores/keyMaterialUpdatesStore/keyMaterialUpdatesStore.d.ts +0 -11
- package/lib/messagingProtocols/mls/MLSService/stores/keyMaterialUpdatesStore/keyMaterialUpdatesStore.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/stores/keyMaterialUpdatesStore/keyMaterialUpdatesStore.js +0 -50
- package/lib/messagingProtocols/mls/MLSService/stores/keyMaterialUpdatesStore/keyMaterialUpdatesStore.test.d.ts +0 -2
- package/lib/messagingProtocols/mls/MLSService/stores/keyMaterialUpdatesStore/keyMaterialUpdatesStore.test.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/stores/keyMaterialUpdatesStore/keyMaterialUpdatesStore.test.js +0 -39
- package/lib/messagingProtocols/mls/MLSService/subconversationGroupIdMapper.d.ts +0 -4
- package/lib/messagingProtocols/mls/MLSService/subconversationGroupIdMapper.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/subconversationGroupIdMapper.js +0 -35
- package/lib/messagingProtocols/mls/MLSService/subconversationGroupIdMapper.test.d.ts +0 -2
- package/lib/messagingProtocols/mls/MLSService/subconversationGroupIdMapper.test.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/subconversationGroupIdMapper.test.js +0 -35
- 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,11 +1,11 @@
|
|
|
1
|
-
import { PostMlsMessageResponse } from '@wireapp/api-client/lib/conversation';
|
|
1
|
+
import { PostMlsMessageResponse, SUBCONVERSATION_ID } from '@wireapp/api-client/lib/conversation';
|
|
2
2
|
import { Subconversation } from '@wireapp/api-client/lib/conversation/Subconversation';
|
|
3
3
|
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
4
4
|
import logdown from 'logdown';
|
|
5
5
|
import { APIClient } from '@wireapp/api-client';
|
|
6
|
-
import { AddProposalArgs, ConversationId, CoreCrypto, DecryptedMessage,
|
|
6
|
+
import { AddProposalArgs, ConversationId, CoreCrypto, DecryptedMessage, ExternalAddProposalArgs, ExternalProposalType, Invitee, ProposalArgs, ProposalType, RemoveProposalArgs } from '@wireapp/core-crypto';
|
|
7
7
|
import { MLSServiceConfig } from './MLSService.types';
|
|
8
|
-
import {
|
|
8
|
+
import { KeyPackageClaimUser } from '../../../conversation';
|
|
9
9
|
import { TypedEventEmitter } from '../../../util/TypedEventEmitter';
|
|
10
10
|
import { EventHandlerResult } from '../../common.types';
|
|
11
11
|
import { EventHandlerParams } from '../EventHandler';
|
|
@@ -30,19 +30,26 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
30
30
|
groupIdFromConversationId?: MLSCallbacks['groupIdFromConversationId'];
|
|
31
31
|
private readonly textEncoder;
|
|
32
32
|
private readonly textDecoder;
|
|
33
|
+
private readonly defaultCiphersuite;
|
|
33
34
|
constructor(apiClient: APIClient, coreCryptoClient: CoreCrypto, { keyingMaterialUpdateThreshold, nbKeyPackages, }: Partial<MLSServiceConfig>);
|
|
34
35
|
initClient(userId: QualifiedId, clientId: string): Promise<void>;
|
|
35
36
|
createClient(userId: QualifiedId, clientId: string): Promise<void>;
|
|
36
37
|
private uploadCommitBundle;
|
|
37
|
-
addUsersToExistingConversation(groupId: Uint8Array, invitee: Invitee[]): Promise<PostMlsMessageResponse | null
|
|
38
|
+
addUsersToExistingConversation(groupId: Uint8Array, invitee: Invitee[]): Promise<PostMlsMessageResponse | null> | null;
|
|
38
39
|
configureMLSCallbacks({ groupIdFromConversationId, ...coreCryptoCallbacks }: MLSCallbacks): void;
|
|
39
|
-
getKeyPackagesPayload(qualifiedUsers:
|
|
40
|
+
getKeyPackagesPayload(qualifiedUsers: KeyPackageClaimUser[]): Promise<Invitee[]>;
|
|
40
41
|
getEpoch(groupId: string | Uint8Array): Promise<number>;
|
|
41
42
|
newProposal(proposalType: ProposalType, args: ProposalArgs | AddProposalArgs | RemoveProposalArgs): Promise<import("@wireapp/core-crypto").ProposalBundle>;
|
|
42
43
|
joinByExternalCommit(getGroupInfo: () => Promise<Uint8Array>): Promise<PostMlsMessageResponse | null>;
|
|
43
44
|
getConferenceSubconversation(conversationId: QualifiedId): Promise<Subconversation>;
|
|
44
45
|
private deleteConferenceSubconversation;
|
|
46
|
+
/**
|
|
47
|
+
* Will leave conference subconversation if it's known by client and established.
|
|
48
|
+
*
|
|
49
|
+
* @param conversationId Id of the parent conversation which subconversation we want to leave
|
|
50
|
+
*/
|
|
45
51
|
leaveConferenceSubconversation(conversationId: QualifiedId): Promise<void>;
|
|
52
|
+
leaveStaleConferenceSubconversations(): Promise<void>;
|
|
46
53
|
/**
|
|
47
54
|
* Will join or register an mls subconversation for conference calls.
|
|
48
55
|
* Will return the secret key derived from the subconversation
|
|
@@ -54,7 +61,7 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
54
61
|
epoch: number;
|
|
55
62
|
}>;
|
|
56
63
|
exportSecretKey(groupId: string, keyLength: number): Promise<string>;
|
|
57
|
-
newExternalProposal(externalProposalType: ExternalProposalType, args:
|
|
64
|
+
newExternalProposal(externalProposalType: ExternalProposalType, args: ExternalAddProposalArgs): Promise<Uint8Array>;
|
|
58
65
|
processWelcomeMessage(welcomeMessage: Uint8Array): Promise<ConversationId>;
|
|
59
66
|
decryptMessage(conversationId: ConversationId, payload: Uint8Array): Promise<DecryptedMessage>;
|
|
60
67
|
encryptMessage(conversationId: ConversationId, message: Uint8Array): Promise<Uint8Array>;
|
|
@@ -102,6 +109,11 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
102
109
|
* @param groupId The group that should have its key material updated
|
|
103
110
|
*/
|
|
104
111
|
resetKeyMaterialRenewal(groupId: string): void;
|
|
112
|
+
/**
|
|
113
|
+
* Will cancel the renewal of the key material for a given groupId
|
|
114
|
+
* @param groupId The group that should stop having its key material updated
|
|
115
|
+
*/
|
|
116
|
+
cancelKeyMaterialRenewal(groupId: string): void;
|
|
105
117
|
/**
|
|
106
118
|
* Will schedule a task to update the key material of the conversation according to the threshold given as config
|
|
107
119
|
* @param groupId
|
|
@@ -111,7 +123,7 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
111
123
|
* Get all keying material last update dates and schedule tasks for renewal
|
|
112
124
|
* Function must only be called once, after application start
|
|
113
125
|
*/
|
|
114
|
-
|
|
126
|
+
schedulePeriodicKeyMaterialRenewals(groupIds: string[]): void;
|
|
115
127
|
/**
|
|
116
128
|
* Get date of last key packages count query and schedule a task to sync it with backend
|
|
117
129
|
* Function must only be called once, after application start
|
|
@@ -134,7 +146,7 @@ export declare class MLSService extends TypedEventEmitter<Events> {
|
|
|
134
146
|
*
|
|
135
147
|
* @param conversationQualifiedId
|
|
136
148
|
*/
|
|
137
|
-
getGroupIdFromConversationId(conversationQualifiedId: QualifiedId, subconversationId?:
|
|
149
|
+
getGroupIdFromConversationId(conversationQualifiedId: QualifiedId, subconversationId?: SUBCONVERSATION_ID): Promise<string | undefined>;
|
|
138
150
|
/**
|
|
139
151
|
* If there are pending proposals, we need to either process them,
|
|
140
152
|
* or save them in the database for later processing
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,10 +39,9 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
39
39
|
const bazinga64_1 = require("bazinga64");
|
|
40
40
|
const logdown_1 = __importDefault(require("logdown"));
|
|
41
41
|
const commons_1 = require("@wireapp/commons");
|
|
42
|
-
const
|
|
43
|
-
const keyMaterialUpdatesStore_1 = require("./stores/keyMaterialUpdatesStore");
|
|
42
|
+
const core_crypto_1 = require("@wireapp/core-crypto");
|
|
44
43
|
const pendingProposalsStore_1 = require("./stores/pendingProposalsStore");
|
|
45
|
-
const
|
|
44
|
+
const subconversationGroupIdStore_1 = require("./stores/subconversationGroupIdStore/subconversationGroupIdStore");
|
|
46
45
|
const messageSender_1 = require("../../../conversation/message/messageSender");
|
|
47
46
|
const fullyQualifiedClientIdUtils_1 = require("../../../util/fullyQualifiedClientIdUtils");
|
|
48
47
|
const RecurringTaskScheduler_1 = require("../../../util/RecurringTaskScheduler");
|
|
@@ -67,6 +66,7 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
67
66
|
this.logger = (0, logdown_1.default)('@wireapp/core/MLSService');
|
|
68
67
|
this.textEncoder = new TextEncoder();
|
|
69
68
|
this.textDecoder = new TextDecoder();
|
|
69
|
+
this.defaultCiphersuite = core_crypto_1.Ciphersuite.MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519;
|
|
70
70
|
this.config = {
|
|
71
71
|
keyingMaterialUpdateThreshold,
|
|
72
72
|
nbKeyPackages,
|
|
@@ -74,20 +74,21 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
74
74
|
}
|
|
75
75
|
async initClient(userId, clientId) {
|
|
76
76
|
const qualifiedClientId = (0, fullyQualifiedClientIdUtils_1.constructFullyQualifiedClientId)(userId.id, clientId, userId.domain);
|
|
77
|
-
await this.coreCryptoClient.mlsInit(this.textEncoder.encode(qualifiedClientId));
|
|
77
|
+
await this.coreCryptoClient.mlsInit(this.textEncoder.encode(qualifiedClientId), [this.defaultCiphersuite]);
|
|
78
78
|
}
|
|
79
79
|
async createClient(userId, clientId) {
|
|
80
80
|
await this.initClient(userId, clientId);
|
|
81
81
|
// If the device is new, we need to upload keypackages and public key to the backend
|
|
82
|
-
const publicKey = await this.coreCryptoClient.clientPublicKey();
|
|
83
|
-
const keyPackages = await this.coreCryptoClient.clientKeypackages(this.config.nbKeyPackages);
|
|
82
|
+
const publicKey = await this.coreCryptoClient.clientPublicKey(this.defaultCiphersuite);
|
|
83
|
+
const keyPackages = await this.coreCryptoClient.clientKeypackages(this.defaultCiphersuite, this.config.nbKeyPackages);
|
|
84
84
|
await this.uploadMLSPublicKeys(publicKey, clientId);
|
|
85
85
|
await this.uploadMLSKeyPackages(keyPackages, clientId);
|
|
86
86
|
}
|
|
87
87
|
async uploadCommitBundle(groupId, commitBundle, { regenerateCommitBundle, isExternalCommit } = {}) {
|
|
88
|
-
const
|
|
88
|
+
const { commit, groupInfo, welcome } = commitBundle;
|
|
89
|
+
const bundlePayload = new Uint8Array([...commit, ...groupInfo.payload, ...(welcome || [])]);
|
|
89
90
|
try {
|
|
90
|
-
const response = await this.apiClient.api.conversation.postMlsCommitBundle(bundlePayload
|
|
91
|
+
const response = await this.apiClient.api.conversation.postMlsCommitBundle(bundlePayload);
|
|
91
92
|
if (isExternalCommit) {
|
|
92
93
|
await this.coreCryptoClient.mergePendingGroupFromExternalCommit(groupId);
|
|
93
94
|
}
|
|
@@ -119,16 +120,18 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
119
120
|
return null;
|
|
120
121
|
}
|
|
121
122
|
addUsersToExistingConversation(groupId, invitee) {
|
|
123
|
+
if (invitee.length < 1) {
|
|
124
|
+
// providing an empty invitee list to addClientsToConversation method would make core-crypto throw an error
|
|
125
|
+
// we want to skip adding clinets in this case
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
122
128
|
return this.processCommitAction(groupId, () => this.coreCryptoClient.addClientsToConversation(groupId, invitee));
|
|
123
129
|
}
|
|
124
130
|
configureMLSCallbacks(_a) {
|
|
125
131
|
var { groupIdFromConversationId } = _a, coreCryptoCallbacks = __rest(_a, ["groupIdFromConversationId"]);
|
|
126
|
-
void this.coreCryptoClient.registerCallbacks(Object.assign(Object.assign({}, coreCryptoCallbacks), { clientIsExistingGroupUser: (_groupId,
|
|
127
|
-
|
|
128
|
-
return Promise.resolve(
|
|
129
|
-
const { user: otherUser } = (0, fullyQualifiedClientIdUtils_1.parseFullQualifiedClientId)(this.textDecoder.decode(client));
|
|
130
|
-
return otherUser.toLowerCase() === user.toLowerCase();
|
|
131
|
-
}));
|
|
132
|
+
void this.coreCryptoClient.registerCallbacks(Object.assign(Object.assign({}, coreCryptoCallbacks), { clientIsExistingGroupUser: (_groupId, _client, _otherClients) => {
|
|
133
|
+
// All authorization/membership rules are enforced on backend
|
|
134
|
+
return Promise.resolve(true);
|
|
132
135
|
} }));
|
|
133
136
|
this.groupIdFromConversationId = groupIdFromConversationId;
|
|
134
137
|
}
|
|
@@ -138,9 +141,7 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
138
141
|
* we want to add to the new MLS conversations,
|
|
139
142
|
* includes self user too.
|
|
140
143
|
*/
|
|
141
|
-
const keyPackages = await Promise.all(
|
|
142
|
-
...qualifiedUsers.map(({ id, domain, skipOwn }) => this.apiClient.api.client.claimMLSKeyPackages(id, domain, skipOwn)),
|
|
143
|
-
]);
|
|
144
|
+
const keyPackages = await Promise.all(qualifiedUsers.map(({ id, domain, skipOwnClientId }) => this.apiClient.api.client.claimMLSKeyPackages(id, domain, skipOwnClientId)));
|
|
144
145
|
const coreCryptoKeyPackagesPayload = keyPackages.reduce((previousValue, currentValue) => {
|
|
145
146
|
// skip users that have not uploaded their MLS key packages
|
|
146
147
|
if (currentValue.key_packages.length > 0) {
|
|
@@ -166,14 +167,20 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
166
167
|
async joinByExternalCommit(getGroupInfo) {
|
|
167
168
|
const generateCommit = async () => {
|
|
168
169
|
const groupInfo = await getGroupInfo();
|
|
169
|
-
const _a = await this.coreCryptoClient.joinByExternalCommit(groupInfo), { conversationId } = _a, commitBundle = __rest(_a, ["conversationId"]);
|
|
170
|
+
const _a = await this.coreCryptoClient.joinByExternalCommit(groupInfo, core_crypto_1.CredentialType.Basic), { conversationId } = _a, commitBundle = __rest(_a, ["conversationId"]);
|
|
170
171
|
return { groupId: conversationId, commitBundle };
|
|
171
172
|
};
|
|
172
173
|
const { commitBundle, groupId } = await generateCommit();
|
|
173
|
-
|
|
174
|
+
const mlsResponse = await this.uploadCommitBundle(groupId, commitBundle, {
|
|
174
175
|
isExternalCommit: true,
|
|
175
176
|
regenerateCommitBundle: async () => (await generateCommit()).commitBundle,
|
|
176
177
|
});
|
|
178
|
+
if (mlsResponse) {
|
|
179
|
+
//after we've successfully joined via external commit, we schedule periodic key material renewal
|
|
180
|
+
const groupIdStr = bazinga64_1.Encoder.toBase64(groupId).asString;
|
|
181
|
+
this.scheduleKeyMaterialRenewal(groupIdStr);
|
|
182
|
+
}
|
|
183
|
+
return mlsResponse;
|
|
177
184
|
}
|
|
178
185
|
async getConferenceSubconversation(conversationId) {
|
|
179
186
|
return this.apiClient.api.conversation.getSubconversation(conversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
@@ -181,14 +188,36 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
181
188
|
async deleteConferenceSubconversation(conversationId, data) {
|
|
182
189
|
return this.apiClient.api.conversation.deleteSubconversation(conversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE, data);
|
|
183
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Will leave conference subconversation if it's known by client and established.
|
|
193
|
+
*
|
|
194
|
+
* @param conversationId Id of the parent conversation which subconversation we want to leave
|
|
195
|
+
*/
|
|
184
196
|
async leaveConferenceSubconversation(conversationId) {
|
|
185
|
-
const subconversationGroupId =
|
|
197
|
+
const subconversationGroupId = subconversationGroupIdStore_1.subconversationGroupIdStore.getGroupId(conversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
198
|
+
if (!subconversationGroupId) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
186
201
|
const isSubconversationEstablished = await this.conversationExists(subconversationGroupId);
|
|
187
202
|
if (!isSubconversationEstablished) {
|
|
188
|
-
|
|
203
|
+
// if the subconversation was known by a client but is not established anymore, we can remove it from the store
|
|
204
|
+
return subconversationGroupIdStore_1.subconversationGroupIdStore.removeGroupId(conversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
await this.apiClient.api.conversation.deleteSubconversationSelf(conversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
this.logger.error(`Failed to leave conference subconversation:`, error);
|
|
211
|
+
}
|
|
212
|
+
await this.wipeConversation(subconversationGroupId);
|
|
213
|
+
// once we've left the subconversation, we can remove it from the store
|
|
214
|
+
subconversationGroupIdStore_1.subconversationGroupIdStore.removeGroupId(conversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
215
|
+
}
|
|
216
|
+
async leaveStaleConferenceSubconversations() {
|
|
217
|
+
const conversationIds = subconversationGroupIdStore_1.subconversationGroupIdStore.getAllGroupIdsBySubconversationId(conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
218
|
+
for (const { parentConversationId } of conversationIds) {
|
|
219
|
+
await this.leaveConferenceSubconversation(parentConversationId);
|
|
189
220
|
}
|
|
190
|
-
await this.apiClient.api.conversation.deleteSubconversationSelf(conversationId, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
191
|
-
return this.wipeConversation(subconversationGroupId);
|
|
192
221
|
}
|
|
193
222
|
/**
|
|
194
223
|
* Will join or register an mls subconversation for conference calls.
|
|
@@ -218,7 +247,7 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
218
247
|
}
|
|
219
248
|
const epoch = Number(await this.getEpoch(subconversation.group_id));
|
|
220
249
|
// We store the mapping between the subconversation and the parent conversation
|
|
221
|
-
|
|
250
|
+
subconversationGroupIdStore_1.subconversationGroupIdStore.storeGroupId(conversationId, subconversation.subconv_id, subconversation.group_id);
|
|
222
251
|
return { groupId: subconversation.group_id, epoch };
|
|
223
252
|
}
|
|
224
253
|
async exportSecretKey(groupId, keyLength) {
|
|
@@ -270,16 +299,16 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
270
299
|
const mlsKeyBytes = Object.values(mlsKeys).map((key) => bazinga64_1.Decoder.fromBase64(key).asBytes);
|
|
271
300
|
const configuration = {
|
|
272
301
|
externalSenders: mlsKeyBytes,
|
|
273
|
-
ciphersuite:
|
|
302
|
+
ciphersuite: this.defaultCiphersuite,
|
|
274
303
|
};
|
|
275
|
-
await this.coreCryptoClient.createConversation(groupIdBytes, configuration);
|
|
304
|
+
await this.coreCryptoClient.createConversation(groupIdBytes, core_crypto_1.CredentialType.Basic, configuration);
|
|
276
305
|
const keyPackages = await this.getKeyPackagesPayload(users.map(user => {
|
|
277
306
|
if (user.id === (creator === null || creator === void 0 ? void 0 : creator.user.id)) {
|
|
278
307
|
/**
|
|
279
308
|
* we should skip fetching key packages for current self client,
|
|
280
309
|
* it's already added by the backend on the group creation time
|
|
281
310
|
*/
|
|
282
|
-
return Object.assign(Object.assign({}, creator.user), {
|
|
311
|
+
return Object.assign(Object.assign({}, creator.user), { skipOwnClientId: creator.client });
|
|
283
312
|
}
|
|
284
313
|
return user;
|
|
285
314
|
}));
|
|
@@ -287,7 +316,7 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
287
316
|
? await this.addUsersToExistingConversation(groupIdBytes, keyPackages)
|
|
288
317
|
: // If there are no clients to add, just update the keying material
|
|
289
318
|
await this.processCommitAction(groupIdBytes, () => this.coreCryptoClient.updateKeyingMaterial(groupIdBytes));
|
|
290
|
-
// We schedule a key material renewal
|
|
319
|
+
// We schedule a periodic key material renewal
|
|
291
320
|
this.scheduleKeyMaterialRenewal(groupId);
|
|
292
321
|
return response;
|
|
293
322
|
}
|
|
@@ -309,10 +338,10 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
309
338
|
return this.coreCryptoClient.conversationExists(groupIdBytes);
|
|
310
339
|
}
|
|
311
340
|
async clientValidKeypackagesCount() {
|
|
312
|
-
return this.coreCryptoClient.clientValidKeypackagesCount();
|
|
341
|
+
return this.coreCryptoClient.clientValidKeypackagesCount(this.defaultCiphersuite);
|
|
313
342
|
}
|
|
314
343
|
async clientKeypackages(amountRequested) {
|
|
315
|
-
return this.coreCryptoClient.clientKeypackages(amountRequested);
|
|
344
|
+
return this.coreCryptoClient.clientKeypackages(this.defaultCiphersuite, amountRequested);
|
|
316
345
|
}
|
|
317
346
|
/**
|
|
318
347
|
* Renew key material for a given groupId
|
|
@@ -323,7 +352,7 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
323
352
|
try {
|
|
324
353
|
const groupConversationExists = await this.conversationExists(groupId);
|
|
325
354
|
if (!groupConversationExists) {
|
|
326
|
-
|
|
355
|
+
this.cancelKeyMaterialRenewal(groupId);
|
|
327
356
|
return;
|
|
328
357
|
}
|
|
329
358
|
const groupIdDecodedFromBase64 = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
@@ -341,9 +370,16 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
341
370
|
* @param groupId The group that should have its key material updated
|
|
342
371
|
*/
|
|
343
372
|
resetKeyMaterialRenewal(groupId) {
|
|
344
|
-
|
|
373
|
+
this.cancelKeyMaterialRenewal(groupId);
|
|
345
374
|
this.scheduleKeyMaterialRenewal(groupId);
|
|
346
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Will cancel the renewal of the key material for a given groupId
|
|
378
|
+
* @param groupId The group that should stop having its key material updated
|
|
379
|
+
*/
|
|
380
|
+
cancelKeyMaterialRenewal(groupId) {
|
|
381
|
+
return (0, RecurringTaskScheduler_1.cancelRecurringTask)(this.createKeyMaterialUpdateTaskSchedulerId(groupId));
|
|
382
|
+
}
|
|
347
383
|
/**
|
|
348
384
|
* Will schedule a task to update the key material of the conversation according to the threshold given as config
|
|
349
385
|
* @param groupId
|
|
@@ -360,10 +396,9 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
360
396
|
* Get all keying material last update dates and schedule tasks for renewal
|
|
361
397
|
* Function must only be called once, after application start
|
|
362
398
|
*/
|
|
363
|
-
|
|
399
|
+
schedulePeriodicKeyMaterialRenewals(groupIds) {
|
|
364
400
|
try {
|
|
365
|
-
|
|
366
|
-
keyMaterialUpdateDates.forEach(({ groupId }) => this.scheduleKeyMaterialRenewal(groupId));
|
|
401
|
+
groupIds.forEach(groupId => this.scheduleKeyMaterialRenewal(groupId));
|
|
367
402
|
}
|
|
368
403
|
catch (error) {
|
|
369
404
|
this.logger.error('Could not get last key material update dates', error);
|
|
@@ -409,11 +444,21 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
409
444
|
return this.apiClient.api.client.uploadMLSKeyPackages(clientId, keypackages.map(keypackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keypackage))));
|
|
410
445
|
}
|
|
411
446
|
async wipeConversation(groupId) {
|
|
447
|
+
const isMLSConversationEstablished = await this.conversationExists(groupId);
|
|
448
|
+
if (!isMLSConversationEstablished) {
|
|
449
|
+
//if the mls group does not exist, we don't need to wipe it
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
this.cancelKeyMaterialRenewal(groupId);
|
|
412
453
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
413
454
|
return this.coreCryptoClient.wipeConversation(groupIdBytes);
|
|
414
455
|
}
|
|
415
456
|
async handleEvent(params) {
|
|
416
457
|
return (0, EventHandler_1.handleBackendEvent)(Object.assign(Object.assign({}, params), { mlsService: this }), async (groupId) => {
|
|
458
|
+
const conversationExists = await this.conversationExists(groupId);
|
|
459
|
+
if (!conversationExists) {
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
417
462
|
const newEpoch = await this.getEpoch(groupId);
|
|
418
463
|
this.emit('newEpoch', { groupId, epoch: newEpoch });
|
|
419
464
|
});
|
|
@@ -426,13 +471,9 @@ class MLSService extends TypedEventEmitter_1.TypedEventEmitter {
|
|
|
426
471
|
*/
|
|
427
472
|
async getGroupIdFromConversationId(conversationQualifiedId, subconversationId) {
|
|
428
473
|
var _a;
|
|
429
|
-
const { id: conversationId, domain: conversationDomain } = conversationQualifiedId;
|
|
430
474
|
const groupId = subconversationId
|
|
431
|
-
?
|
|
475
|
+
? subconversationGroupIdStore_1.subconversationGroupIdStore.getGroupId(conversationQualifiedId, subconversationId)
|
|
432
476
|
: await ((_a = this.groupIdFromConversationId) === null || _a === void 0 ? void 0 : _a.call(this, conversationQualifiedId));
|
|
433
|
-
if (!groupId) {
|
|
434
|
-
throw new Error(`Could not find a group_id for conversation ${conversationId}@${conversationDomain}`);
|
|
435
|
-
}
|
|
436
477
|
return groupId;
|
|
437
478
|
}
|
|
438
479
|
/**
|
|
@@ -29,6 +29,8 @@ describe('MLSService', () => {
|
|
|
29
29
|
const apiClient = new api_client_1.APIClient();
|
|
30
30
|
const mockCoreCrypto = {
|
|
31
31
|
createConversation: jest.fn(),
|
|
32
|
+
conversationExists: jest.fn(),
|
|
33
|
+
wipeConversation: jest.fn(),
|
|
32
34
|
};
|
|
33
35
|
describe('registerConversation', () => {
|
|
34
36
|
let mlsService;
|
|
@@ -40,6 +42,7 @@ describe('MLSService', () => {
|
|
|
40
42
|
jest.spyOn(apiClient.api.client, 'claimMLSKeyPackages').mockResolvedValue({ key_packages: [] });
|
|
41
43
|
jest.spyOn(mlsService, 'scheduleKeyMaterialRenewal').mockImplementation();
|
|
42
44
|
jest.spyOn(mlsService, 'processCommitAction').mockImplementation();
|
|
45
|
+
jest.spyOn(mlsService, 'cancelKeyMaterialRenewal').mockImplementation();
|
|
43
46
|
});
|
|
44
47
|
it('creates a new mls conversation and avoid adding the selfUser', async () => {
|
|
45
48
|
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
@@ -56,5 +59,11 @@ describe('MLSService', () => {
|
|
|
56
59
|
await mlsService.registerConversation(groupId, [createUserId(), createUserId()]);
|
|
57
60
|
expect(mlsService.scheduleKeyMaterialRenewal).toHaveBeenCalledWith(groupId);
|
|
58
61
|
});
|
|
62
|
+
it('cancels key material timers after group is wiped', async () => {
|
|
63
|
+
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm4OQFc=';
|
|
64
|
+
jest.spyOn(mockCoreCrypto, 'conversationExists').mockResolvedValueOnce(true);
|
|
65
|
+
await mlsService.wipeConversation(groupId);
|
|
66
|
+
expect(mlsService.cancelKeyMaterialRenewal).toHaveBeenCalledWith(groupId);
|
|
67
|
+
});
|
|
59
68
|
});
|
|
60
69
|
});
|
|
@@ -4,5 +4,5 @@ import { CommitBundle } from '@wireapp/core-crypto';
|
|
|
4
4
|
* @param commitBundle a commit bundle generated by coreCrypto
|
|
5
5
|
* @returns
|
|
6
6
|
*/
|
|
7
|
-
export declare function toProtobufCommitBundle({ commit, welcome,
|
|
7
|
+
export declare function toProtobufCommitBundle({ commit, welcome, groupInfo }: CommitBundle): Uint8Array;
|
|
8
8
|
//# sourceMappingURL=commitBundleUtil.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commitBundleUtil.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/commitBundleUtil.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAC,YAAY,
|
|
1
|
+
{"version":3,"file":"commitBundleUtil.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/commitBundleUtil.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAC,YAAY,EAA2C,MAAM,sBAAsB,CAAC;AAY5F;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,EAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAC,EAAE,YAAY,GAAG,UAAU,CAW7F"}
|
|
@@ -27,20 +27,20 @@ const ratchetTreeMapping = {
|
|
|
27
27
|
[core_crypto_1.RatchetTreeType.Delta]: mls_1.mls.RatchetTreeType.DELTA,
|
|
28
28
|
};
|
|
29
29
|
const groupInfoType = {
|
|
30
|
-
[core_crypto_1.
|
|
31
|
-
[core_crypto_1.
|
|
30
|
+
[core_crypto_1.GroupInfoEncryptionType.Plaintext]: mls_1.mls.GroupInfoType.PUBLIC_GROUP_STATE,
|
|
31
|
+
[core_crypto_1.GroupInfoEncryptionType.JweEncrypted]: mls_1.mls.GroupInfoType.GROUP_INFO_JWE,
|
|
32
32
|
};
|
|
33
33
|
/**
|
|
34
34
|
* Will convert a coreCrypto commit bundle into a Uint8Array representing a protobuf object
|
|
35
35
|
* @param commitBundle a commit bundle generated by coreCrypto
|
|
36
36
|
* @returns
|
|
37
37
|
*/
|
|
38
|
-
function toProtobufCommitBundle({ commit, welcome,
|
|
39
|
-
const { ratchetTreeType, encryptionType } =
|
|
38
|
+
function toProtobufCommitBundle({ commit, welcome, groupInfo }) {
|
|
39
|
+
const { ratchetTreeType, encryptionType } = groupInfo;
|
|
40
40
|
return mls_1.mls.CommitBundle.encode({
|
|
41
41
|
groupInfoBundle: {
|
|
42
42
|
ratchetTreeType: ratchetTreeMapping[ratchetTreeType],
|
|
43
|
-
groupInfo:
|
|
43
|
+
groupInfo: groupInfo.payload,
|
|
44
44
|
groupInfoType: groupInfoType[encryptionType],
|
|
45
45
|
},
|
|
46
46
|
commit,
|
|
@@ -27,17 +27,17 @@ describe('toProtobufCommitBundle', () => {
|
|
|
27
27
|
const payload = {
|
|
28
28
|
commit: Uint8Array.from([0]),
|
|
29
29
|
welcome: Uint8Array.from([1]),
|
|
30
|
-
|
|
30
|
+
groupInfo: {
|
|
31
31
|
ratchetTreeType: core_crypto_1.RatchetTreeType.Full,
|
|
32
32
|
payload: Uint8Array.from([2]),
|
|
33
|
-
encryptionType: core_crypto_1.
|
|
33
|
+
encryptionType: core_crypto_1.GroupInfoEncryptionType.Plaintext,
|
|
34
34
|
},
|
|
35
35
|
};
|
|
36
36
|
const result = (0, commitBundleUtil_1.toProtobufCommitBundle)(payload);
|
|
37
37
|
const { commit, welcome, groupInfoBundle } = mls_1.mls.CommitBundle.decode(result);
|
|
38
38
|
expect(bazinga64_1.Encoder.toBase64(commit)).toEqual(bazinga64_1.Encoder.toBase64(payload.commit));
|
|
39
39
|
expect(bazinga64_1.Encoder.toBase64(welcome)).toEqual(bazinga64_1.Encoder.toBase64(payload.welcome));
|
|
40
|
-
expect(bazinga64_1.Encoder.toBase64(groupInfoBundle.groupInfo)).toEqual(bazinga64_1.Encoder.toBase64(payload.
|
|
40
|
+
expect(bazinga64_1.Encoder.toBase64(groupInfoBundle.groupInfo)).toEqual(bazinga64_1.Encoder.toBase64(payload.groupInfo.payload));
|
|
41
41
|
expect(groupInfoBundle.ratchetTreeType).toEqual(mls_1.mls.RatchetTreeType.FULL);
|
|
42
42
|
expect(groupInfoBundle.groupInfoType).toEqual(mls_1.mls.GroupInfoType.PUBLIC_GROUP_STATE);
|
|
43
43
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SUBCONVERSATION_ID } from '@wireapp/api-client/lib/conversation';
|
|
2
|
+
import { QualifiedId } from '@wireapp/api-client/lib/user';
|
|
3
|
+
export declare const subconversationGroupIdStore: {
|
|
4
|
+
storeGroupId: (parentConversationId: QualifiedId, subconversationId: SUBCONVERSATION_ID, subconversationGroupId: string) => void;
|
|
5
|
+
getGroupId: (parentConversationId: QualifiedId, subconversationId: SUBCONVERSATION_ID) => string | undefined;
|
|
6
|
+
removeGroupId: (parentConversationId: QualifiedId, subconversationId: SUBCONVERSATION_ID) => void;
|
|
7
|
+
getAllGroupIdsBySubconversationId: (subconversationIdQuery: SUBCONVERSATION_ID) => {
|
|
8
|
+
subconversationGroupId: string;
|
|
9
|
+
parentConversationId: QualifiedId;
|
|
10
|
+
subconversationId: SUBCONVERSATION_ID;
|
|
11
|
+
}[];
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=subconversationGroupIdStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subconversationGroupIdStore.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAgEzD,eAAO,MAAM,2BAA2B;yCA3BhB,WAAW,qBACd,kBAAkB,0BACb,MAAM;uCAMU,WAAW,qBAAqB,kBAAkB;0CAc/C,WAAW,qBAAqB,kBAAkB;gEAT5B,kBAAkB;;8BArC3D,WAAW;2BAAqB,kBAAkB;;CAwD3E,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
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.subconversationGroupIdStore = void 0;
|
|
22
|
+
const storageKey = 'subconversationGroupIdStore';
|
|
23
|
+
const generateSubconversationStoreKey = (parentConversationId, subconversationId) => {
|
|
24
|
+
return `${parentConversationId.id}@${parentConversationId.domain}:${subconversationId}`;
|
|
25
|
+
};
|
|
26
|
+
const parseSubconversationStoreKey = (subconversationStoreKey) => {
|
|
27
|
+
const [parentConversationId, subconversationId] = subconversationStoreKey.split(':');
|
|
28
|
+
const [id, domain] = parentConversationId.split('@');
|
|
29
|
+
return { parentConversationId: { domain, id }, subconversationId };
|
|
30
|
+
};
|
|
31
|
+
const getCurrentMap = () => {
|
|
32
|
+
const storedEntry = localStorage.getItem(storageKey);
|
|
33
|
+
return storedEntry ? new Map(JSON.parse(storedEntry)) : new Map();
|
|
34
|
+
};
|
|
35
|
+
const addItemToMap = (subconversationId, subgroupId) => {
|
|
36
|
+
const currentMap = getCurrentMap();
|
|
37
|
+
currentMap.set(subconversationId, subgroupId);
|
|
38
|
+
localStorage.setItem(storageKey, JSON.stringify(Array.from(currentMap.entries())));
|
|
39
|
+
};
|
|
40
|
+
const removeItemFromMap = (subconversationId) => {
|
|
41
|
+
const currentMap = getCurrentMap();
|
|
42
|
+
currentMap.delete(subconversationId);
|
|
43
|
+
localStorage.setItem(storageKey, JSON.stringify(Array.from(currentMap.entries())));
|
|
44
|
+
};
|
|
45
|
+
const storeGroupId = (parentConversationId, subconversationId, subconversationGroupId) => {
|
|
46
|
+
const subconversationStoreKey = generateSubconversationStoreKey(parentConversationId, subconversationId);
|
|
47
|
+
addItemToMap(subconversationStoreKey, subconversationGroupId);
|
|
48
|
+
};
|
|
49
|
+
const getGroupId = (parentConversationId, subconversationId) => {
|
|
50
|
+
const subconversationStoreKey = generateSubconversationStoreKey(parentConversationId, subconversationId);
|
|
51
|
+
return getCurrentMap().get(subconversationStoreKey);
|
|
52
|
+
};
|
|
53
|
+
const getAllGroupIdsBySubconversationId = (subconversationIdQuery) => {
|
|
54
|
+
return Array.from(getCurrentMap().entries())
|
|
55
|
+
.map(([subconversationId, subconversationGroupId]) => (Object.assign(Object.assign({}, parseSubconversationStoreKey(subconversationId)), { subconversationGroupId })))
|
|
56
|
+
.filter(({ subconversationId }) => subconversationId === subconversationIdQuery);
|
|
57
|
+
};
|
|
58
|
+
const removeGroupId = (parentConversationId, subconversationId) => {
|
|
59
|
+
const subconversationStoreKey = generateSubconversationStoreKey(parentConversationId, subconversationId);
|
|
60
|
+
return removeItemFromMap(subconversationStoreKey);
|
|
61
|
+
};
|
|
62
|
+
exports.subconversationGroupIdStore = {
|
|
63
|
+
storeGroupId,
|
|
64
|
+
getGroupId,
|
|
65
|
+
removeGroupId,
|
|
66
|
+
getAllGroupIdsBySubconversationId,
|
|
67
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subconversationGroupIdStore.test.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/MLSService/stores/subconversationGroupIdStore/subconversationGroupIdStore.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Wire
|
|
4
|
+
* Copyright (C) 2018 Wire Swiss GmbH
|
|
5
|
+
*
|
|
6
|
+
* This program is free software: you can redistribute it and/or modify
|
|
7
|
+
* it under the terms of the GNU General Public License as published by
|
|
8
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
* (at your option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
* GNU General Public License for more details.
|
|
15
|
+
*
|
|
16
|
+
* You should have received a copy of the GNU General Public License
|
|
17
|
+
* along with this program. If not, see http://www.gnu.org/licenses/.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const conversation_1 = require("@wireapp/api-client/lib/conversation");
|
|
22
|
+
const subconversationGroupIdStore_1 = require("./subconversationGroupIdStore");
|
|
23
|
+
describe('subconversationGroupIdMapper', () => {
|
|
24
|
+
it('returns empty groupId if conversation is not known', () => {
|
|
25
|
+
const groupId = subconversationGroupIdStore_1.subconversationGroupIdStore.getGroupId({ domain: 'example.com', id: '123' }, conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
26
|
+
expect(groupId).toBeUndefined();
|
|
27
|
+
});
|
|
28
|
+
it('returns the stored groupId', () => {
|
|
29
|
+
const conversationId = { domain: 'example.com', id: '123' };
|
|
30
|
+
const subconversation = conversation_1.SUBCONVERSATION_ID.CONFERENCE;
|
|
31
|
+
const groupId = 'groupID';
|
|
32
|
+
subconversationGroupIdStore_1.subconversationGroupIdStore.storeGroupId(conversationId, subconversation, groupId);
|
|
33
|
+
const result = subconversationGroupIdStore_1.subconversationGroupIdStore.getGroupId(conversationId, subconversation);
|
|
34
|
+
expect(result).toBe(groupId);
|
|
35
|
+
});
|
|
36
|
+
it('removes groupId from the store', () => {
|
|
37
|
+
const conversationId = { domain: 'example.com', id: '123' };
|
|
38
|
+
const subconversation = conversation_1.SUBCONVERSATION_ID.CONFERENCE;
|
|
39
|
+
const groupId = 'groupID';
|
|
40
|
+
subconversationGroupIdStore_1.subconversationGroupIdStore.storeGroupId(conversationId, subconversation, groupId);
|
|
41
|
+
expect(subconversationGroupIdStore_1.subconversationGroupIdStore.getGroupId(conversationId, subconversation)).toEqual(groupId);
|
|
42
|
+
subconversationGroupIdStore_1.subconversationGroupIdStore.removeGroupId(conversationId, subconversation);
|
|
43
|
+
expect(subconversationGroupIdStore_1.subconversationGroupIdStore.getGroupId(conversationId, subconversation)).toBeUndefined();
|
|
44
|
+
});
|
|
45
|
+
it('retrieves all entries from the store by subconversation id', () => {
|
|
46
|
+
const conversationId = { domain: 'example.com', id: '123' };
|
|
47
|
+
const subconversation = conversation_1.SUBCONVERSATION_ID.CONFERENCE;
|
|
48
|
+
const groupId = 'groupID';
|
|
49
|
+
const conversationId2 = { domain: 'example2.com', id: '1234' };
|
|
50
|
+
const subconversation2 = conversation_1.SUBCONVERSATION_ID.CONFERENCE;
|
|
51
|
+
const groupId2 = 'groupID2';
|
|
52
|
+
const conversationId3 = { domain: 'example3.com', id: '12345' };
|
|
53
|
+
const subconversation3 = 'none';
|
|
54
|
+
const groupId3 = 'groupID3';
|
|
55
|
+
subconversationGroupIdStore_1.subconversationGroupIdStore.storeGroupId(conversationId, subconversation, groupId);
|
|
56
|
+
subconversationGroupIdStore_1.subconversationGroupIdStore.storeGroupId(conversationId2, subconversation2, groupId2);
|
|
57
|
+
subconversationGroupIdStore_1.subconversationGroupIdStore.storeGroupId(conversationId3, subconversation3, groupId3);
|
|
58
|
+
const result = subconversationGroupIdStore_1.subconversationGroupIdStore.getAllGroupIdsBySubconversationId(conversation_1.SUBCONVERSATION_ID.CONFERENCE);
|
|
59
|
+
expect(result).toEqual([
|
|
60
|
+
{
|
|
61
|
+
parentConversationId: conversationId,
|
|
62
|
+
subconversationId: subconversation,
|
|
63
|
+
subconversationGroupId: groupId,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
parentConversationId: conversationId2,
|
|
67
|
+
subconversationId: subconversation2,
|
|
68
|
+
subconversationGroupId: groupId2,
|
|
69
|
+
},
|
|
70
|
+
]);
|
|
71
|
+
});
|
|
72
|
+
});
|