@wireapp/core 42.9.0 → 42.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Account.js +1 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +3 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.js +5 -8
- package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +103 -30
- package/lib/storage/CoreDB.d.ts +7 -0
- package/lib/storage/CoreDB.d.ts.map +1 -1
- package/lib/storage/CoreDB.js +4 -1
- package/lib/util/LowPrecisionTaskScheduler/LowPrecisionTaskScheduler.js +2 -2
- package/lib/util/RecurringTaskScheduler/RecurringTaskScheduler.d.ts.map +1 -1
- package/lib/util/RecurringTaskScheduler/RecurringTaskScheduler.js +6 -5
- package/lib/util/RecurringTaskScheduler/RecurringTaskScheduler.test.js +14 -0
- package/package.json +2 -2
- package/lib/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/index.d.ts +0 -2
- package/lib/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/index.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/index.js +0 -35
- package/lib/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/pendingProposalsStore.d.ts +0 -10
- package/lib/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/pendingProposalsStore.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/pendingProposalsStore.js +0 -50
- package/lib/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/pendingProposalsStore.test.d.ts +0 -2
- package/lib/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/pendingProposalsStore.test.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/pendingProposalsStore.test.js +0 -42
package/lib/Account.js
CHANGED
|
@@ -260,7 +260,7 @@ class Account extends commons_1.TypedEventEmitter {
|
|
|
260
260
|
const cryptoClientDef = await this.buildCryptoClient(context, this.storeEngine, enableMLS);
|
|
261
261
|
const [clientType, cryptoClient] = cryptoClientDef;
|
|
262
262
|
const mlsService = clientType === CryptoClient_1.CryptoClientType.CORE_CRYPTO && enableMLS
|
|
263
|
-
? new mls_1.MLSService(this.apiClient, cryptoClient.getNativeClient(), Object.assign({}, (_b = this.cryptoProtocolConfig) === null || _b === void 0 ? void 0 : _b.mls))
|
|
263
|
+
? new mls_1.MLSService(this.apiClient, cryptoClient.getNativeClient(), this.db, Object.assign({}, (_b = this.cryptoProtocolConfig) === null || _b === void 0 ? void 0 : _b.mls))
|
|
264
264
|
: undefined;
|
|
265
265
|
const proteusService = new proteus_1.ProteusService(this.apiClient, cryptoClient, {
|
|
266
266
|
onNewClient: payload => this.emit(EVENTS.NEW_SESSION, payload),
|
|
@@ -9,6 +9,7 @@ import { TypedEventEmitter } from '@wireapp/commons';
|
|
|
9
9
|
import { AddProposalArgs, ConversationId, CoreCrypto, DecryptedMessage, ExternalAddProposalArgs, ExternalProposalType, Invitee, ProposalArgs, ProposalType, RemoveProposalArgs } from '@wireapp/core-crypto';
|
|
10
10
|
import { MLSServiceConfig } from './MLSService.types';
|
|
11
11
|
import { KeyPackageClaimUser } from '../../../conversation';
|
|
12
|
+
import { CoreDatabase } from '../../../storage/CoreDB';
|
|
12
13
|
import { CommitPendingProposalsParams, HandlePendingProposalsParams, MLSCallbacks } from '../types';
|
|
13
14
|
export declare const optionalToUint8Array: (array: Uint8Array | []) => Uint8Array;
|
|
14
15
|
interface LocalMLSServiceConfig extends MLSServiceConfig {
|
|
@@ -31,12 +32,13 @@ type Events = {
|
|
|
31
32
|
export declare class MLSService extends TypedEventEmitter<Events> {
|
|
32
33
|
private readonly apiClient;
|
|
33
34
|
private readonly coreCryptoClient;
|
|
35
|
+
private readonly coreDatabase;
|
|
34
36
|
logger: logdown.Logger;
|
|
35
37
|
config: LocalMLSServiceConfig;
|
|
36
38
|
groupIdFromConversationId?: MLSCallbacks['groupIdFromConversationId'];
|
|
37
39
|
private readonly textEncoder;
|
|
38
40
|
private readonly textDecoder;
|
|
39
|
-
constructor(apiClient: APIClient, coreCryptoClient: CoreCrypto, { keyingMaterialUpdateThreshold, nbKeyPackages, defaultCiphersuite, defaultCredentialType, }: Partial<MLSServiceConfig>);
|
|
41
|
+
constructor(apiClient: APIClient, coreCryptoClient: CoreCrypto, coreDatabase: CoreDatabase, { keyingMaterialUpdateThreshold, nbKeyPackages, defaultCiphersuite, defaultCredentialType, }: Partial<MLSServiceConfig>);
|
|
40
42
|
initClient(userId: QualifiedId, client: RegisteredClient): Promise<void>;
|
|
41
43
|
private readonly uploadCommitBundle;
|
|
42
44
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAqB,gBAAgB,EAAC,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAC,sBAAsB,EAAE,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AAChG,OAAO,EAAC,eAAe,EAAC,MAAM,sDAAsD,CAAC;AACrF,OAAO,EAAC,8BAA8B,EAAE,2BAA2B,EAAC,MAAM,+BAA+B,CAAC;AAE1G,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAGzD,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAW,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EACL,eAAe,EAIf,cAAc,EACd,UAAU,EAEV,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAC,gBAAgB,EAAsB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,7 +41,6 @@ const logdown_1 = __importDefault(require("logdown"));
|
|
|
41
41
|
const commons_1 = require("@wireapp/commons");
|
|
42
42
|
const core_crypto_1 = require("@wireapp/core-crypto");
|
|
43
43
|
const CoreCryptoMLSError_1 = require("./CoreCryptoMLSError");
|
|
44
|
-
const pendingProposalsStore_1 = require("./stores/pendingProposalsStore");
|
|
45
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");
|
|
@@ -62,10 +61,11 @@ const defaultConfig = {
|
|
|
62
61
|
defaultCredentialType: core_crypto_1.CredentialType.Basic,
|
|
63
62
|
};
|
|
64
63
|
class MLSService extends commons_1.TypedEventEmitter {
|
|
65
|
-
constructor(apiClient, coreCryptoClient, { keyingMaterialUpdateThreshold = defaultConfig.keyingMaterialUpdateThreshold, nbKeyPackages = defaultConfig.nbKeyPackages, defaultCiphersuite = defaultConfig.defaultCiphersuite, defaultCredentialType = defaultConfig.defaultCredentialType, }) {
|
|
64
|
+
constructor(apiClient, coreCryptoClient, coreDatabase, { keyingMaterialUpdateThreshold = defaultConfig.keyingMaterialUpdateThreshold, nbKeyPackages = defaultConfig.nbKeyPackages, defaultCiphersuite = defaultConfig.defaultCiphersuite, defaultCredentialType = defaultConfig.defaultCredentialType, }) {
|
|
66
65
|
super();
|
|
67
66
|
this.apiClient = apiClient;
|
|
68
67
|
this.coreCryptoClient = coreCryptoClient;
|
|
68
|
+
this.coreDatabase = coreDatabase;
|
|
69
69
|
this.logger = (0, logdown_1.default)('@wireapp/core/MLSService');
|
|
70
70
|
this.textEncoder = new TextEncoder();
|
|
71
71
|
this.textDecoder = new TextDecoder();
|
|
@@ -556,10 +556,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
556
556
|
if (delayInMs > 0) {
|
|
557
557
|
const eventDate = new Date(eventTime);
|
|
558
558
|
const firingDate = eventDate.setTime(eventDate.getTime() + delayInMs);
|
|
559
|
-
|
|
560
|
-
groupId,
|
|
561
|
-
firingDate,
|
|
562
|
-
});
|
|
559
|
+
await this.coreDatabase.put('pendingProposals', { groupId, firingDate }, groupId);
|
|
563
560
|
TaskScheduler_1.TaskScheduler.addTask({
|
|
564
561
|
task: () => this.commitPendingProposals({ groupId }),
|
|
565
562
|
firingDate,
|
|
@@ -581,7 +578,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
581
578
|
await this.commitProposals(bazinga64_1.Decoder.fromBase64(groupId).asBytes);
|
|
582
579
|
if (!skipDelete) {
|
|
583
580
|
TaskScheduler_1.TaskScheduler.cancelTask(groupId);
|
|
584
|
-
|
|
581
|
+
await this.coreDatabase.delete('pendingProposals', groupId);
|
|
585
582
|
}
|
|
586
583
|
}
|
|
587
584
|
catch (error) {
|
|
@@ -595,7 +592,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
595
592
|
*/
|
|
596
593
|
async checkExistingPendingProposals() {
|
|
597
594
|
try {
|
|
598
|
-
const pendingProposals =
|
|
595
|
+
const pendingProposals = await this.coreDatabase.getAll('pendingProposals');
|
|
599
596
|
if (pendingProposals.length > 0) {
|
|
600
597
|
pendingProposals.forEach(({ groupId, firingDate }) => TaskScheduler_1.TaskScheduler.addTask({
|
|
601
598
|
task: () => this.commitPendingProposals({ groupId }),
|
|
@@ -23,11 +23,12 @@ const event_1 = require("@wireapp/api-client/lib/event");
|
|
|
23
23
|
const crypto_1 = require("crypto");
|
|
24
24
|
const api_client_1 = require("@wireapp/api-client");
|
|
25
25
|
const MLSService_1 = require("./MLSService");
|
|
26
|
+
const CoreDB_1 = require("../../../storage/CoreDB");
|
|
26
27
|
jest.createMockFromModule('@wireapp/api-client');
|
|
27
28
|
function createUserId() {
|
|
28
29
|
return { id: (0, crypto_1.randomUUID)(), domain: '' };
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
+
const createMLSService = async () => {
|
|
31
32
|
const apiClient = new api_client_1.APIClient();
|
|
32
33
|
const mockCoreCrypto = {
|
|
33
34
|
createConversation: jest.fn(),
|
|
@@ -38,11 +39,24 @@ describe('MLSService', () => {
|
|
|
38
39
|
mlsInit: jest.fn(),
|
|
39
40
|
clientPublicKey: jest.fn(),
|
|
40
41
|
processWelcomeMessage: jest.fn(),
|
|
42
|
+
decryptMessage: jest.fn(),
|
|
43
|
+
conversationEpoch: jest.fn(),
|
|
44
|
+
commitPendingProposals: jest.fn(),
|
|
41
45
|
};
|
|
46
|
+
const mockedDb = await (0, CoreDB_1.openDB)('core-test-db');
|
|
47
|
+
const mlsService = new MLSService_1.MLSService(apiClient, mockCoreCrypto, mockedDb, {});
|
|
48
|
+
return [mlsService, { apiClient, coreCrypto: mockCoreCrypto }];
|
|
49
|
+
};
|
|
50
|
+
describe('MLSService', () => {
|
|
42
51
|
describe('registerConversation', () => {
|
|
43
52
|
let mlsService;
|
|
44
|
-
|
|
45
|
-
|
|
53
|
+
let apiClient;
|
|
54
|
+
let coreCrypto;
|
|
55
|
+
beforeEach(async () => {
|
|
56
|
+
const [mockedMLSService, { apiClient: mockApiClient, coreCrypto: mockCoreCrypto }] = await createMLSService();
|
|
57
|
+
mlsService = mockedMLSService;
|
|
58
|
+
apiClient = mockApiClient;
|
|
59
|
+
coreCrypto = mockCoreCrypto;
|
|
46
60
|
jest
|
|
47
61
|
.spyOn(apiClient.api.client, 'getPublicKeys')
|
|
48
62
|
.mockResolvedValue({ removal: { algo: 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=' } });
|
|
@@ -73,21 +87,21 @@ describe('MLSService', () => {
|
|
|
73
87
|
});
|
|
74
88
|
it('cancels key material timers after group is wiped', async () => {
|
|
75
89
|
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm4OQFc=';
|
|
76
|
-
jest.spyOn(
|
|
90
|
+
jest.spyOn(coreCrypto, 'conversationExists').mockResolvedValueOnce(true);
|
|
77
91
|
await mlsService.wipeConversation(groupId);
|
|
78
92
|
expect(mlsService.cancelKeyMaterialRenewal).toHaveBeenCalledWith(groupId);
|
|
79
93
|
});
|
|
80
94
|
});
|
|
81
95
|
describe('isConversationEstablished', () => {
|
|
82
96
|
it('returns false if conversation does not exist locally', async () => {
|
|
83
|
-
const mlsService =
|
|
97
|
+
const [mlsService] = await createMLSService();
|
|
84
98
|
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
85
99
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(false);
|
|
86
100
|
const isEstablshed = await mlsService.isConversationEstablished(groupId);
|
|
87
101
|
expect(isEstablshed).toBe(false);
|
|
88
102
|
});
|
|
89
103
|
it('returns false if epoch number is 0', async () => {
|
|
90
|
-
const mlsService =
|
|
104
|
+
const [mlsService] = await createMLSService();
|
|
91
105
|
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
92
106
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
|
|
93
107
|
jest.spyOn(mlsService, 'getEpoch').mockResolvedValueOnce(0);
|
|
@@ -95,7 +109,7 @@ describe('MLSService', () => {
|
|
|
95
109
|
expect(isEstablshed).toBe(false);
|
|
96
110
|
});
|
|
97
111
|
it.each([1, 2, 100])('returns false if epoch number is 1 or more', async (epoch) => {
|
|
98
|
-
const mlsService =
|
|
112
|
+
const [mlsService] = await createMLSService();
|
|
99
113
|
const groupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
100
114
|
jest.spyOn(mlsService, 'conversationExists').mockResolvedValueOnce(true);
|
|
101
115
|
jest.spyOn(mlsService, 'getEpoch').mockResolvedValueOnce(epoch);
|
|
@@ -105,62 +119,121 @@ describe('MLSService', () => {
|
|
|
105
119
|
});
|
|
106
120
|
describe('initClient', () => {
|
|
107
121
|
it('uploads public key only if it was not yet defined on client entity', async () => {
|
|
108
|
-
const mlsService
|
|
122
|
+
const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
|
|
109
123
|
const mockUserId = { id: 'user-1', domain: 'local.zinfra.io' };
|
|
110
124
|
const mockClientId = 'client-1';
|
|
111
125
|
const mockClient = { mls_public_keys: {}, id: mockClientId };
|
|
112
126
|
apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
|
|
113
127
|
const mockedClientPublicKey = new Uint8Array();
|
|
114
|
-
jest.spyOn(
|
|
128
|
+
jest.spyOn(coreCrypto, 'clientPublicKey').mockResolvedValueOnce(mockedClientPublicKey);
|
|
115
129
|
jest.spyOn(apiClient.api.client, 'putClient').mockResolvedValueOnce(undefined);
|
|
116
130
|
jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(mlsService.config.nbKeyPackages);
|
|
117
131
|
await mlsService.initClient(mockUserId, mockClient);
|
|
118
|
-
expect(
|
|
132
|
+
expect(coreCrypto.mlsInit).toHaveBeenCalled();
|
|
119
133
|
expect(apiClient.api.client.putClient).toHaveBeenCalledWith(mockClientId, expect.anything());
|
|
120
134
|
});
|
|
121
135
|
it('uploads key packages if there are not enough keys on backend', async () => {
|
|
122
|
-
const mlsService
|
|
136
|
+
const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
|
|
123
137
|
const mockUserId = { id: 'user-1', domain: 'local.zinfra.io' };
|
|
124
138
|
const mockClientId = 'client-1';
|
|
125
139
|
const mockClient = { mls_public_keys: { ed25519: 'key' }, id: mockClientId };
|
|
126
140
|
apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
|
|
127
141
|
const mockedClientKeyPackages = [new Uint8Array()];
|
|
128
|
-
jest.spyOn(
|
|
142
|
+
jest.spyOn(coreCrypto, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
|
|
129
143
|
jest
|
|
130
144
|
.spyOn(apiClient.api.client, 'getMLSKeyPackageCount')
|
|
131
145
|
.mockResolvedValueOnce(mlsService.config.minRequiredNumberOfAvailableKeyPackages - 1);
|
|
132
146
|
jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages').mockResolvedValueOnce(undefined);
|
|
133
147
|
await mlsService.initClient(mockUserId, mockClient);
|
|
134
|
-
expect(
|
|
148
|
+
expect(coreCrypto.mlsInit).toHaveBeenCalled();
|
|
135
149
|
expect(apiClient.api.client.uploadMLSKeyPackages).toHaveBeenCalledWith(mockClientId, expect.anything());
|
|
136
150
|
});
|
|
137
151
|
it('does not upload public key or key packages if both are already uploaded', async () => {
|
|
138
|
-
const mlsService
|
|
152
|
+
const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
|
|
139
153
|
const mockUserId = { id: 'user-1', domain: 'local.zinfra.io' };
|
|
140
154
|
const mockClientId = 'client-1';
|
|
141
155
|
const mockClient = { mls_public_keys: { ed25519: 'key' }, id: mockClientId };
|
|
142
156
|
apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
|
|
143
157
|
jest.spyOn(apiClient.api.client, 'getClient').mockResolvedValueOnce(mockClient);
|
|
144
158
|
jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(mlsService.config.nbKeyPackages);
|
|
159
|
+
jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages');
|
|
160
|
+
jest.spyOn(apiClient.api.client, 'putClient');
|
|
145
161
|
await mlsService.initClient(mockUserId, mockClient);
|
|
146
|
-
expect(
|
|
162
|
+
expect(coreCrypto.mlsInit).toHaveBeenCalled();
|
|
147
163
|
expect(apiClient.api.client.uploadMLSKeyPackages).not.toHaveBeenCalled();
|
|
148
164
|
expect(apiClient.api.client.putClient).not.toHaveBeenCalled();
|
|
149
165
|
});
|
|
150
166
|
});
|
|
167
|
+
describe('handleMLSMessageAddEvent', () => {
|
|
168
|
+
it('decrypts a message and emits new epoch event if epoch has changed', async () => {
|
|
169
|
+
const [mlsService, { coreCrypto: mockCoreCrypto }] = await createMLSService();
|
|
170
|
+
const mockGroupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
171
|
+
const mockedNewEpoch = 3;
|
|
172
|
+
jest.spyOn(mlsService, 'getGroupIdFromConversationId').mockResolvedValueOnce(mockGroupId);
|
|
173
|
+
const mockedDecryptoedMessage = {
|
|
174
|
+
hasEpochChanged: true,
|
|
175
|
+
isActive: false,
|
|
176
|
+
proposals: [],
|
|
177
|
+
};
|
|
178
|
+
jest.spyOn(mockCoreCrypto, 'decryptMessage').mockResolvedValueOnce(mockedDecryptoedMessage);
|
|
179
|
+
jest.spyOn(mockCoreCrypto, 'conversationEpoch').mockResolvedValueOnce(mockedNewEpoch);
|
|
180
|
+
jest.spyOn(mlsService, 'emit').mockImplementation(jest.fn());
|
|
181
|
+
const mockedMLSWelcomeEvent = {
|
|
182
|
+
type: event_1.CONVERSATION_EVENT.MLS_MESSAGE_ADD,
|
|
183
|
+
senderClientId: '',
|
|
184
|
+
conversation: '',
|
|
185
|
+
data: '',
|
|
186
|
+
from: '',
|
|
187
|
+
time: '',
|
|
188
|
+
};
|
|
189
|
+
await mlsService.handleMLSMessageAddEvent(mockedMLSWelcomeEvent);
|
|
190
|
+
expect(mockCoreCrypto.decryptMessage).toHaveBeenCalled();
|
|
191
|
+
expect(mlsService.emit).toHaveBeenCalledWith('newEpoch', { epoch: mockedNewEpoch, groupId: mockGroupId });
|
|
192
|
+
});
|
|
193
|
+
it('handles pending propoals with a delay after decrypting a message', async () => {
|
|
194
|
+
const [mlsService, { coreCrypto: mockCoreCrypto }] = await createMLSService();
|
|
195
|
+
jest.useFakeTimers();
|
|
196
|
+
const mockGroupId = 'mXOagqRIX/RFd7QyXJA8/Ed8X+hvQgLXIiwYHm3OQFc=';
|
|
197
|
+
const mockedNewEpoch = 3;
|
|
198
|
+
const commitDelay = 1000;
|
|
199
|
+
jest.spyOn(mlsService, 'getGroupIdFromConversationId').mockResolvedValueOnce(mockGroupId);
|
|
200
|
+
const mockedDecryptoedMessage = {
|
|
201
|
+
hasEpochChanged: true,
|
|
202
|
+
isActive: false,
|
|
203
|
+
proposals: [],
|
|
204
|
+
commitDelay,
|
|
205
|
+
};
|
|
206
|
+
jest.spyOn(mockCoreCrypto, 'decryptMessage').mockResolvedValueOnce(mockedDecryptoedMessage);
|
|
207
|
+
jest.spyOn(mockCoreCrypto, 'conversationEpoch').mockResolvedValueOnce(mockedNewEpoch);
|
|
208
|
+
jest.spyOn(mlsService, 'commitPendingProposals');
|
|
209
|
+
const mockedMLSWelcomeEvent = {
|
|
210
|
+
type: event_1.CONVERSATION_EVENT.MLS_MESSAGE_ADD,
|
|
211
|
+
senderClientId: '',
|
|
212
|
+
conversation: '',
|
|
213
|
+
data: '',
|
|
214
|
+
from: '',
|
|
215
|
+
time: new Date().toISOString(),
|
|
216
|
+
};
|
|
217
|
+
await mlsService.handleMLSMessageAddEvent(mockedMLSWelcomeEvent);
|
|
218
|
+
expect(mockCoreCrypto.commitPendingProposals).not.toHaveBeenCalled();
|
|
219
|
+
jest.advanceTimersByTime(commitDelay);
|
|
220
|
+
expect(mockCoreCrypto.decryptMessage).toHaveBeenCalled();
|
|
221
|
+
expect(mockCoreCrypto.commitPendingProposals).toHaveBeenCalled();
|
|
222
|
+
});
|
|
223
|
+
});
|
|
151
224
|
describe('handleMLSWelcomeMessageEvent', () => {
|
|
152
225
|
it("before processing welcome it verifies that there's enough key packages locally", async () => {
|
|
153
|
-
const mlsService
|
|
226
|
+
const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
|
|
154
227
|
const mockClientId = 'client-1';
|
|
155
228
|
const mockClient = { mls_public_keys: { ed25519: 'key' }, id: mockClientId };
|
|
156
229
|
apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
|
|
157
230
|
const mockedClientKeyPackages = [new Uint8Array()];
|
|
158
|
-
jest.spyOn(
|
|
231
|
+
jest.spyOn(coreCrypto, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
|
|
159
232
|
const numberOfKeysBelowThreshold = mlsService.config.minRequiredNumberOfAvailableKeyPackages - 1;
|
|
160
233
|
jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(numberOfKeysBelowThreshold);
|
|
161
|
-
jest.spyOn(
|
|
234
|
+
jest.spyOn(coreCrypto, 'clientValidKeypackagesCount').mockResolvedValueOnce(numberOfKeysBelowThreshold);
|
|
162
235
|
jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages').mockResolvedValueOnce(undefined);
|
|
163
|
-
jest.spyOn(
|
|
236
|
+
jest.spyOn(coreCrypto, 'processWelcomeMessage').mockResolvedValueOnce(new Uint8Array());
|
|
164
237
|
jest.spyOn(mlsService, 'scheduleKeyMaterialRenewal').mockImplementation(jest.fn());
|
|
165
238
|
const mockedMLSWelcomeEvent = {
|
|
166
239
|
type: event_1.CONVERSATION_EVENT.MLS_WELCOME_MESSAGE,
|
|
@@ -170,21 +243,21 @@ describe('MLSService', () => {
|
|
|
170
243
|
time: '',
|
|
171
244
|
};
|
|
172
245
|
await mlsService.handleMLSWelcomeMessageEvent(mockedMLSWelcomeEvent, mockClient.id);
|
|
173
|
-
expect(
|
|
246
|
+
expect(coreCrypto.processWelcomeMessage).toHaveBeenCalled();
|
|
174
247
|
expect(apiClient.api.client.uploadMLSKeyPackages).toHaveBeenCalledWith(mockClientId, expect.anything());
|
|
175
248
|
});
|
|
176
249
|
it('before processing welcome it does not generate new keys if there is enough key packages locally', async () => {
|
|
177
|
-
const mlsService
|
|
250
|
+
const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
|
|
178
251
|
const mockClientId = 'client-1';
|
|
179
252
|
const mockClient = { mls_public_keys: { ed25519: 'key' }, id: mockClientId };
|
|
180
253
|
apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
|
|
181
254
|
const mockedClientKeyPackages = [new Uint8Array()];
|
|
182
|
-
jest.spyOn(
|
|
255
|
+
jest.spyOn(coreCrypto, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
|
|
183
256
|
const numberOfKeysAboveThreshold = mlsService.config.minRequiredNumberOfAvailableKeyPackages + 1;
|
|
184
|
-
jest.spyOn(
|
|
257
|
+
jest.spyOn(coreCrypto, 'clientValidKeypackagesCount').mockResolvedValueOnce(numberOfKeysAboveThreshold);
|
|
185
258
|
jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(numberOfKeysAboveThreshold);
|
|
186
259
|
jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages').mockResolvedValueOnce(undefined);
|
|
187
|
-
jest.spyOn(
|
|
260
|
+
jest.spyOn(coreCrypto, 'processWelcomeMessage').mockResolvedValueOnce(new Uint8Array());
|
|
188
261
|
jest.spyOn(mlsService, 'scheduleKeyMaterialRenewal').mockImplementation(jest.fn());
|
|
189
262
|
const mockedMLSWelcomeEvent = {
|
|
190
263
|
type: event_1.CONVERSATION_EVENT.MLS_WELCOME_MESSAGE,
|
|
@@ -194,22 +267,22 @@ describe('MLSService', () => {
|
|
|
194
267
|
time: '',
|
|
195
268
|
};
|
|
196
269
|
await mlsService.handleMLSWelcomeMessageEvent(mockedMLSWelcomeEvent, mockClient.id);
|
|
197
|
-
expect(
|
|
270
|
+
expect(coreCrypto.processWelcomeMessage).toHaveBeenCalled();
|
|
198
271
|
expect(apiClient.api.client.uploadMLSKeyPackages).not.toHaveBeenCalled();
|
|
199
272
|
});
|
|
200
273
|
it('before processing welcome it does not generate new keys if there is enough key packages uploaded to backend', async () => {
|
|
201
|
-
const mlsService
|
|
274
|
+
const [mlsService, { apiClient, coreCrypto }] = await createMLSService();
|
|
202
275
|
const mockClientId = 'client-1';
|
|
203
276
|
const mockClient = { mls_public_keys: { ed25519: 'key' }, id: mockClientId };
|
|
204
277
|
apiClient.context = { clientType: client_1.ClientType.PERMANENT, clientId: mockClientId, userId: '' };
|
|
205
278
|
const mockedClientKeyPackages = [new Uint8Array()];
|
|
206
|
-
jest.spyOn(
|
|
279
|
+
jest.spyOn(coreCrypto, 'clientKeypackages').mockResolvedValueOnce(mockedClientKeyPackages);
|
|
207
280
|
const numberOfKeysBelowThreshold = mlsService.config.minRequiredNumberOfAvailableKeyPackages - 1;
|
|
208
281
|
const numberOfKeysAboveThreshold = mlsService.config.minRequiredNumberOfAvailableKeyPackages + 1;
|
|
209
|
-
jest.spyOn(
|
|
282
|
+
jest.spyOn(coreCrypto, 'clientValidKeypackagesCount').mockResolvedValueOnce(numberOfKeysBelowThreshold);
|
|
210
283
|
jest.spyOn(apiClient.api.client, 'getMLSKeyPackageCount').mockResolvedValueOnce(numberOfKeysAboveThreshold);
|
|
211
284
|
jest.spyOn(apiClient.api.client, 'uploadMLSKeyPackages').mockResolvedValueOnce(undefined);
|
|
212
|
-
jest.spyOn(
|
|
285
|
+
jest.spyOn(coreCrypto, 'processWelcomeMessage').mockResolvedValueOnce(new Uint8Array());
|
|
213
286
|
jest.spyOn(mlsService, 'scheduleKeyMaterialRenewal').mockImplementation(jest.fn());
|
|
214
287
|
const mockedMLSWelcomeEvent = {
|
|
215
288
|
type: event_1.CONVERSATION_EVENT.MLS_WELCOME_MESSAGE,
|
|
@@ -219,7 +292,7 @@ describe('MLSService', () => {
|
|
|
219
292
|
time: '',
|
|
220
293
|
};
|
|
221
294
|
await mlsService.handleMLSWelcomeMessageEvent(mockedMLSWelcomeEvent, mockClient.id);
|
|
222
|
-
expect(
|
|
295
|
+
expect(coreCrypto.processWelcomeMessage).toHaveBeenCalled();
|
|
223
296
|
expect(apiClient.api.client.uploadMLSKeyPackages).not.toHaveBeenCalled();
|
|
224
297
|
});
|
|
225
298
|
});
|
package/lib/storage/CoreDB.d.ts
CHANGED
|
@@ -7,6 +7,13 @@ interface CoreDBSchema extends DBSchema {
|
|
|
7
7
|
highestId: number;
|
|
8
8
|
};
|
|
9
9
|
};
|
|
10
|
+
pendingProposals: {
|
|
11
|
+
key: string;
|
|
12
|
+
value: {
|
|
13
|
+
groupId: string;
|
|
14
|
+
firingDate: number;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
10
17
|
}
|
|
11
18
|
export type CoreDatabase = IDBPDatabase<CoreDBSchema>;
|
|
12
19
|
export declare function openDB(dbName: string): Promise<CoreDatabase>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoreDB.d.ts","sourceRoot":"","sources":["../../src/storage/CoreDB.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,QAAQ,EAA2B,YAAY,EAAsB,MAAM,KAAK,CAAC;AAGzF,UAAU,YAAa,SAAQ,QAAQ;IACrC,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAC,CAAC;KAC/C,CAAC;CACH;AAED,MAAM,MAAM,YAAY,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;AAEtD,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"CoreDB.d.ts","sourceRoot":"","sources":["../../src/storage/CoreDB.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,QAAQ,EAA2B,YAAY,EAAsB,MAAM,KAAK,CAAC;AAGzF,UAAU,YAAa,SAAQ,QAAQ;IACrC,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAC,CAAC;KAC/C,CAAC;IACF,gBAAgB,EAAE;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAC,CAAC;KAC9C,CAAC;CACH;AAED,MAAM,MAAM,YAAY,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;AAEtD,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAalE;AAED,wBAAsB,QAAQ,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D"}
|
package/lib/storage/CoreDB.js
CHANGED
|
@@ -20,13 +20,16 @@
|
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
exports.deleteDB = exports.openDB = void 0;
|
|
22
22
|
const idb_1 = require("idb");
|
|
23
|
-
const VERSION =
|
|
23
|
+
const VERSION = 2;
|
|
24
24
|
async function openDB(dbName) {
|
|
25
25
|
const db = await (0, idb_1.openDB)(dbName, VERSION, {
|
|
26
26
|
upgrade: (db, oldVersion) => {
|
|
27
27
|
switch (oldVersion) {
|
|
28
28
|
case 0:
|
|
29
29
|
db.createObjectStore('prekeys');
|
|
30
|
+
case 1:
|
|
31
|
+
db.deleteObjectStore('prekeys');
|
|
32
|
+
db.createObjectStore('pendingProposals');
|
|
30
33
|
}
|
|
31
34
|
},
|
|
32
35
|
});
|
|
@@ -39,11 +39,11 @@ const addTask = ({ key, firingDate, task, intervalDelay }) => {
|
|
|
39
39
|
const tasks = (_a = intervals[intervalDelay]) === null || _a === void 0 ? void 0 : _a.tasks;
|
|
40
40
|
if ((tasks === null || tasks === void 0 ? void 0 : tasks.length) !== 0) {
|
|
41
41
|
for (const taskData of tasks) {
|
|
42
|
-
if (nowTime >= firingDate) {
|
|
42
|
+
if (nowTime >= taskData.firingDate) {
|
|
43
43
|
const { task, key } = taskData;
|
|
44
44
|
logger.info(`Executing task with key "${key}"`);
|
|
45
|
-
task();
|
|
46
45
|
cancelTask({ intervalDelay, key });
|
|
46
|
+
task();
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecurringTaskScheduler.d.ts","sourceRoot":"","sources":["../../../src/util/RecurringTaskScheduler/RecurringTaskScheduler.ts"],"names":[],"mappings":"AA0BA,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,qBAAqB,CAAC,EAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAC,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"RecurringTaskScheduler.d.ts","sourceRoot":"","sources":["../../../src/util/RecurringTaskScheduler/RecurringTaskScheduler.ts"],"names":[],"mappings":"AA0BA,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,qBAAqB,CAAC,EAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAC,EAAE,UAAU,QAqBnE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,QAIlD"}
|
|
@@ -24,13 +24,13 @@ const RecurringTaskScheduler_store_1 = require("./RecurringTaskScheduler.store")
|
|
|
24
24
|
const LowPrecisionTaskScheduler_1 = require("../LowPrecisionTaskScheduler");
|
|
25
25
|
const TaskScheduler_1 = require("../TaskScheduler");
|
|
26
26
|
function registerRecurringTask({ every, task, key }) {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const firingDate = (0, RecurringTaskScheduler_store_1.loadState)(key) || Date.now() + every;
|
|
28
|
+
(0, RecurringTaskScheduler_store_1.saveState)(key, firingDate);
|
|
29
29
|
const taskConfig = {
|
|
30
|
-
firingDate
|
|
30
|
+
firingDate,
|
|
31
31
|
key,
|
|
32
|
-
task() {
|
|
33
|
-
(0, RecurringTaskScheduler_store_1.
|
|
32
|
+
task: () => {
|
|
33
|
+
(0, RecurringTaskScheduler_store_1.deleteState)(key);
|
|
34
34
|
task();
|
|
35
35
|
registerRecurringTask({ every, task, key });
|
|
36
36
|
},
|
|
@@ -46,6 +46,7 @@ function registerRecurringTask({ every, task, key }) {
|
|
|
46
46
|
}
|
|
47
47
|
exports.registerRecurringTask = registerRecurringTask;
|
|
48
48
|
function cancelRecurringTask(taskKey) {
|
|
49
|
+
(0, RecurringTaskScheduler_store_1.deleteState)(taskKey);
|
|
49
50
|
TaskScheduler_1.TaskScheduler.cancelTask(taskKey);
|
|
50
51
|
LowPrecisionTaskScheduler_1.LowPrecisionTaskScheduler.cancelTask({ intervalDelay: commons_1.TimeUtil.TimeInMillis.MINUTE, key: taskKey });
|
|
51
52
|
}
|
|
@@ -36,6 +36,20 @@ describe('RecurringTaskScheduler', () => {
|
|
|
36
36
|
jest.advanceTimersByTime(commons_1.TimeUtil.TimeInMillis.MINUTE + 1);
|
|
37
37
|
expect(task).toHaveBeenCalledTimes(2);
|
|
38
38
|
});
|
|
39
|
+
it('resumes a task after re-registering a recurring task', () => {
|
|
40
|
+
const task = jest.fn();
|
|
41
|
+
// it should fire in a minute
|
|
42
|
+
(0, RecurringTaskScheduler_1.registerRecurringTask)({ every: commons_1.TimeUtil.TimeInMillis.MINUTE, task, key: 'test-task2' });
|
|
43
|
+
jest.advanceTimersByTime(commons_1.TimeUtil.TimeInMillis.MINUTE / 2);
|
|
44
|
+
// re-register the task
|
|
45
|
+
(0, RecurringTaskScheduler_1.registerRecurringTask)({ every: commons_1.TimeUtil.TimeInMillis.MINUTE, task, key: 'test-task2' });
|
|
46
|
+
// only 30s have passed, so the task should not have fired yet
|
|
47
|
+
expect(task).toHaveBeenCalledTimes(0);
|
|
48
|
+
// advance the timer by another 30s (so we have 1 minute in total)
|
|
49
|
+
jest.advanceTimersByTime(commons_1.TimeUtil.TimeInMillis.MINUTE / 2);
|
|
50
|
+
// the task should have fired once after a minute from the beginning even if we re-registered it
|
|
51
|
+
expect(task).toHaveBeenCalledTimes(1);
|
|
52
|
+
});
|
|
39
53
|
it('cancel a task before it is run', () => {
|
|
40
54
|
const task = jest.fn();
|
|
41
55
|
const testKey = 'test-task-1';
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/index.ts"],"names":[],"mappings":"AAmBA,cAAc,yBAAyB,CAAC"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Wire
|
|
4
|
-
* Copyright (C) 2022 Wire Swiss GmbH
|
|
5
|
-
*
|
|
6
|
-
* This program is free software: you can redistribute it and/or modify
|
|
7
|
-
* it under the terms of the GNU General Public License as published by
|
|
8
|
-
* the Free Software Foundation, either version 3 of the License, or
|
|
9
|
-
* (at your option) any later version.
|
|
10
|
-
*
|
|
11
|
-
* This program is distributed in the hope that it will be useful,
|
|
12
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
-
* GNU General Public License for more details.
|
|
15
|
-
*
|
|
16
|
-
* You should have received a copy of the GNU General Public License
|
|
17
|
-
* along with this program. If not, see http://www.gnu.org/licenses/.
|
|
18
|
-
*
|
|
19
|
-
*/
|
|
20
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
|
-
if (k2 === undefined) k2 = k;
|
|
22
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
23
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
24
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
25
|
-
}
|
|
26
|
-
Object.defineProperty(o, k2, desc);
|
|
27
|
-
}) : (function(o, m, k, k2) {
|
|
28
|
-
if (k2 === undefined) k2 = k;
|
|
29
|
-
o[k2] = m[k];
|
|
30
|
-
}));
|
|
31
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
32
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
33
|
-
};
|
|
34
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
__exportStar(require("./pendingProposalsStore"), exports);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { CommonMLS } from '../../../types';
|
|
2
|
-
export type PendingProposalsParams = {
|
|
3
|
-
firingDate: number;
|
|
4
|
-
} & CommonMLS;
|
|
5
|
-
export declare const pendingProposalsStore: {
|
|
6
|
-
getAllItems: () => PendingProposalsParams[];
|
|
7
|
-
storeItem: ({ groupId, firingDate }: PendingProposalsParams) => void;
|
|
8
|
-
deleteItem: ({ groupId }: CommonMLS) => void;
|
|
9
|
-
};
|
|
10
|
-
//# sourceMappingURL=pendingProposalsStore.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pendingProposalsStore.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/pendingProposalsStore.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAEzC,MAAM,MAAM,sBAAsB,GAAG;IACnC,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,SAAS,CAAC;AAmCd,eAAO,MAAM,qBAAqB;uBAnBV,sBAAsB,EAAE;yCAKN,sBAAsB;8BAMjC,SAAS;CAYvC,CAAC"}
|
package/lib/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/pendingProposalsStore.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Wire
|
|
4
|
-
* Copyright (C) 2022 Wire Swiss GmbH
|
|
5
|
-
*
|
|
6
|
-
* This program is free software: you can redistribute it and/or modify
|
|
7
|
-
* it under the terms of the GNU General Public License as published by
|
|
8
|
-
* the Free Software Foundation, either version 3 of the License, or
|
|
9
|
-
* (at your option) any later version.
|
|
10
|
-
*
|
|
11
|
-
* This program is distributed in the hope that it will be useful,
|
|
12
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
-
* GNU General Public License for more details.
|
|
15
|
-
*
|
|
16
|
-
* You should have received a copy of the GNU General Public License
|
|
17
|
-
* along with this program. If not, see http://www.gnu.org/licenses/.
|
|
18
|
-
*
|
|
19
|
-
*/
|
|
20
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.pendingProposalsStore = void 0;
|
|
22
|
-
const storageKey = 'pendingProposals';
|
|
23
|
-
const getAllItemsMap = () => {
|
|
24
|
-
const storedState = localStorage.getItem(storageKey);
|
|
25
|
-
if (!storedState) {
|
|
26
|
-
return {};
|
|
27
|
-
}
|
|
28
|
-
return JSON.parse(storedState);
|
|
29
|
-
};
|
|
30
|
-
const getAllItems = () => {
|
|
31
|
-
const storedStateMap = getAllItemsMap();
|
|
32
|
-
return Object.values(storedStateMap);
|
|
33
|
-
};
|
|
34
|
-
const storeItem = ({ groupId, firingDate }) => {
|
|
35
|
-
const storedState = getAllItemsMap();
|
|
36
|
-
const newStoredState = Object.assign(Object.assign({}, storedState), { [groupId]: { groupId, firingDate } });
|
|
37
|
-
localStorage.setItem(storageKey, JSON.stringify(newStoredState));
|
|
38
|
-
};
|
|
39
|
-
const deleteItem = ({ groupId }) => {
|
|
40
|
-
const storedState = getAllItemsMap();
|
|
41
|
-
if (storedState[groupId]) {
|
|
42
|
-
delete storedState[groupId];
|
|
43
|
-
}
|
|
44
|
-
localStorage.setItem(storageKey, JSON.stringify(storedState));
|
|
45
|
-
};
|
|
46
|
-
exports.pendingProposalsStore = {
|
|
47
|
-
getAllItems,
|
|
48
|
-
storeItem,
|
|
49
|
-
deleteItem,
|
|
50
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pendingProposalsStore.test.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/MLSService/stores/pendingProposalsStore/pendingProposalsStore.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Wire
|
|
4
|
-
* Copyright (C) 2022 Wire Swiss GmbH
|
|
5
|
-
*
|
|
6
|
-
* This program is free software: you can redistribute it and/or modify
|
|
7
|
-
* it under the terms of the GNU General Public License as published by
|
|
8
|
-
* the Free Software Foundation, either version 3 of the License, or
|
|
9
|
-
* (at your option) any later version.
|
|
10
|
-
*
|
|
11
|
-
* This program is distributed in the hope that it will be useful,
|
|
12
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
-
* GNU General Public License for more details.
|
|
15
|
-
*
|
|
16
|
-
* You should have received a copy of the GNU General Public License
|
|
17
|
-
* along with this program. If not, see http://www.gnu.org/licenses/.
|
|
18
|
-
*
|
|
19
|
-
*/
|
|
20
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
const pendingProposalsStore_1 = require("./pendingProposalsStore");
|
|
22
|
-
const mockEntries = [
|
|
23
|
-
{ groupId: 'group0', firingDate: 1 },
|
|
24
|
-
{ groupId: 'group1', firingDate: 2 },
|
|
25
|
-
];
|
|
26
|
-
describe('pendingProposalsStore', () => {
|
|
27
|
-
it('adds and retrieves items to/from dates store', () => {
|
|
28
|
-
pendingProposalsStore_1.pendingProposalsStore.storeItem(mockEntries[0]);
|
|
29
|
-
expect(pendingProposalsStore_1.pendingProposalsStore.getAllItems()).toContainEqual(mockEntries[0]);
|
|
30
|
-
pendingProposalsStore_1.pendingProposalsStore.storeItem(mockEntries[1]);
|
|
31
|
-
const stored = pendingProposalsStore_1.pendingProposalsStore.getAllItems();
|
|
32
|
-
expect(stored).toContainEqual(mockEntries[1]);
|
|
33
|
-
expect(stored).toContainEqual(mockEntries[0]);
|
|
34
|
-
expect(stored).toHaveLength(2);
|
|
35
|
-
});
|
|
36
|
-
it('removes items from dates store', () => {
|
|
37
|
-
pendingProposalsStore_1.pendingProposalsStore.storeItem(mockEntries[0]);
|
|
38
|
-
expect(pendingProposalsStore_1.pendingProposalsStore.getAllItems()).toContainEqual(mockEntries[0]);
|
|
39
|
-
pendingProposalsStore_1.pendingProposalsStore.deleteItem({ groupId: mockEntries[0].groupId });
|
|
40
|
-
expect(pendingProposalsStore_1.pendingProposalsStore.getAllItems()).not.toContainEqual(mockEntries[0]);
|
|
41
|
-
});
|
|
42
|
-
});
|