@wireapp/core 30.6.1 → 30.7.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/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [30.7.0](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/compare/@wireapp/core@30.6.1...@wireapp/core@30.7.0) (2022-09-14)
7
+
8
+
9
+ ### Features
10
+
11
+ * **core:** sync keys with backend (FS-655) ([#4384](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/issues/4384)) ([28bd0b7](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/commit/28bd0b7358bc8291a712ac267ee65aceec3d74c4))
12
+
13
+
14
+
15
+
16
+
6
17
  ## [30.6.1](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/compare/@wireapp/core@30.6.0...@wireapp/core@30.6.1) (2022-09-13)
7
18
 
8
19
  **Note:** Version bump only for package @wireapp/core
package/package.json CHANGED
@@ -77,6 +77,6 @@
77
77
  "test:node": "nyc jasmine --config=jasmine.json",
78
78
  "watch": "tsc ---watch"
79
79
  },
80
- "version": "30.6.1",
81
- "gitHead": "7f7ff444af87563ce59f0782eae6806a6c43c9d3"
80
+ "version": "30.7.0",
81
+ "gitHead": "c9020130a213747f423d2c49aea546dc5038da72"
82
82
  }
@@ -22,6 +22,7 @@ import { UserService } from './user/';
22
22
  import { AccountService } from './account/';
23
23
  import { LinkPreviewService } from './linkPreview';
24
24
  import { WEBSOCKET_STATE } from '@wireapp/api-client/src/tcp/ReconnectingWebsocket';
25
+ import { MLSService } from './mls';
25
26
  import type { MLSConfig } from './mls/types';
26
27
  export declare type ProcessedEventPayload = HandledEventPayload;
27
28
  declare enum TOPIC {
@@ -84,6 +85,7 @@ export declare class Account<T = any> extends EventEmitter {
84
85
  private coreCryptoClient?;
85
86
  static readonly TOPIC: typeof TOPIC;
86
87
  service?: {
88
+ mls: MLSService;
87
89
  account: AccountService;
88
90
  asset: AssetService;
89
91
  broadcast: BroadcastService;
@@ -138,7 +138,7 @@ class Account extends events_1.EventEmitter {
138
138
  * @param cookie The cookie to identify the user against backend (will use the browser's one if not given)
139
139
  */
140
140
  async init(clientType, cookie, initClient = true) {
141
- var _a, _b;
141
+ var _a, _b, _c;
142
142
  const context = await this.apiClient.init(clientType, cookie);
143
143
  await this.initServices(context);
144
144
  // Assumption: client gets only initialized once
@@ -148,6 +148,8 @@ class Account extends events_1.EventEmitter {
148
148
  await ((_a = this.service) === null || _a === void 0 ? void 0 : _a.notification.checkExistingPendingProposals());
149
149
  // initialize schedulers for renewing key materials
150
150
  await ((_b = this.service) === null || _b === void 0 ? void 0 : _b.notification.checkForKeyMaterialsUpdate());
151
+ // initialize scheduler for syncing key packages with backend
152
+ await ((_c = this.service) === null || _c === void 0 ? void 0 : _c.notification.checkForKeyPackagesBackendSync());
151
153
  }
152
154
  return context;
153
155
  }
@@ -247,6 +249,7 @@ class Account extends events_1.EventEmitter {
247
249
  const broadcastService = new broadcast_1.BroadcastService(this.apiClient, cryptographyService);
248
250
  const userService = new user_1.UserService(this.apiClient, broadcastService, conversationService, connectionService);
249
251
  this.service = {
252
+ mls: mlsService,
250
253
  account: accountService,
251
254
  asset: assetService,
252
255
  broadcast: broadcastService,
@@ -300,8 +303,8 @@ class Account extends events_1.EventEmitter {
300
303
  });
301
304
  if (isNewMLSDevice) {
302
305
  // If the device is new, we need to upload keypackages and public key to the backend
303
- await this.service.client.uploadMLSPublicKeys(await mlsClient.clientPublicKey(), client.id);
304
- await this.service.client.uploadMLSKeyPackages(await mlsClient.clientKeypackages(this.nbPrekeys), client.id);
306
+ await this.service.mls.uploadMLSPublicKeys(await mlsClient.clientPublicKey(), client.id);
307
+ await this.service.mls.uploadMLSKeyPackages(await mlsClient.clientKeypackages(this.nbPrekeys), client.id);
305
308
  }
306
309
  return mlsClient;
307
310
  }
@@ -37,12 +37,4 @@ export declare class ClientService {
37
37
  createLocalClient(client: RegisteredClient, domain?: string): Promise<MetaClient>;
38
38
  synchronizeClients(): Promise<MetaClient[]>;
39
39
  register(loginData: LoginData, clientInfo: ClientInfo, entropyData?: Uint8Array): Promise<RegisteredClient>;
40
- /**
41
- * Will make the given client mls capable (generate and upload key packages)
42
- *
43
- * @param mlsClient Intance of the coreCrypto that represents the mls client
44
- * @param clientId The id of the client
45
- */
46
- uploadMLSPublicKeys(publicKey: Uint8Array, clientId: string): Promise<void>;
47
- uploadMLSKeyPackages(keypackages: Uint8Array[], clientId: string): Promise<void>;
48
40
  }
@@ -21,7 +21,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.ClientService = void 0;
22
22
  const client_1 = require("@wireapp/api-client/src/client/");
23
23
  const _1 = require("./");
24
- const bazinga64_1 = require("bazinga64");
25
24
  class ClientService {
26
25
  constructor(apiClient, storeEngine, cryptographyService) {
27
26
  this.apiClient = apiClient;
@@ -99,20 +98,6 @@ class ClientService {
99
98
  await this.createLocalClient(client, this.apiClient.context.domain);
100
99
  return client;
101
100
  }
102
- /**
103
- * Will make the given client mls capable (generate and upload key packages)
104
- *
105
- * @param mlsClient Intance of the coreCrypto that represents the mls client
106
- * @param clientId The id of the client
107
- */
108
- async uploadMLSPublicKeys(publicKey, clientId) {
109
- return this.backend.putClient(clientId, {
110
- mls_public_keys: { ed25519: btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(publicKey)) },
111
- });
112
- }
113
- async uploadMLSKeyPackages(keypackages, clientId) {
114
- return this.backend.uploadMLSKeyPackages(clientId, keypackages.map(keypackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keypackage))));
115
- }
116
101
  }
117
102
  exports.ClientService = ClientService;
118
103
  //# sourceMappingURL=ClientService.js.map
@@ -23,4 +23,14 @@ export declare class MLSService {
23
23
  removeClientsFromConversation(conversationId: ConversationId, clientIds: Uint8Array[]): Promise<PostMlsMessageResponse | null>;
24
24
  commitPendingProposals(conversationId: ConversationId): Promise<CommitBundle>;
25
25
  conversationExists(conversationId: ConversationId): Promise<boolean>;
26
+ clientValidKeypackagesCount(): Promise<number>;
27
+ clientKeypackages(amountRequested: number): Promise<Uint8Array[]>;
28
+ /**
29
+ * Will make the given client mls capable (generate and upload key packages)
30
+ *
31
+ * @param mlsClient Intance of the coreCrypto that represents the mls client
32
+ * @param clientId The id of the client
33
+ */
34
+ uploadMLSPublicKeys(publicKey: Uint8Array, clientId: string): Promise<void>;
35
+ uploadMLSKeyPackages(keypackages: Uint8Array[], clientId: string): Promise<void>;
26
36
  }
@@ -126,6 +126,26 @@ class MLSService {
126
126
  async conversationExists(conversationId) {
127
127
  return this.getCoreCryptoClient().conversationExists(conversationId);
128
128
  }
129
+ async clientValidKeypackagesCount() {
130
+ return this.getCoreCryptoClient().clientValidKeypackagesCount();
131
+ }
132
+ async clientKeypackages(amountRequested) {
133
+ return this.getCoreCryptoClient().clientKeypackages(amountRequested);
134
+ }
135
+ /**
136
+ * Will make the given client mls capable (generate and upload key packages)
137
+ *
138
+ * @param mlsClient Intance of the coreCrypto that represents the mls client
139
+ * @param clientId The id of the client
140
+ */
141
+ async uploadMLSPublicKeys(publicKey, clientId) {
142
+ return this.apiClient.api.client.putClient(clientId, {
143
+ mls_public_keys: { ed25519: btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(publicKey)) },
144
+ });
145
+ }
146
+ async uploadMLSKeyPackages(keypackages, clientId) {
147
+ return this.apiClient.api.client.uploadMLSKeyPackages(clientId, keypackages.map(keypackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keypackage))));
148
+ }
129
149
  }
130
150
  exports.MLSService = MLSService;
131
151
  //# sourceMappingURL=MLSService.js.map
@@ -0,0 +1,7 @@
1
+ export interface KeyPackagesStatusStore {
2
+ lastQueryDate: number;
3
+ }
4
+ export declare const keyPackagesStatusStore: {
5
+ getState: () => KeyPackagesStatusStore;
6
+ saveState: ({ lastQueryDate }: KeyPackagesStatusStore) => void;
7
+ };
@@ -0,0 +1,42 @@
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.keyPackagesStatusStore = void 0;
22
+ const storageKey = 'keyPackagesStatus';
23
+ const getState = () => {
24
+ const storedState = localStorage.getItem(storageKey);
25
+ if (!storedState) {
26
+ return {
27
+ lastQueryDate: 0,
28
+ };
29
+ }
30
+ const parsedState = JSON.parse(storedState);
31
+ return {
32
+ lastQueryDate: Number(parsedState.lastQueryDate),
33
+ };
34
+ };
35
+ const saveState = ({ lastQueryDate }) => {
36
+ localStorage.setItem(storageKey, JSON.stringify({ lastQueryDate }));
37
+ };
38
+ exports.keyPackagesStatusStore = {
39
+ getState,
40
+ saveState,
41
+ };
42
+ //# sourceMappingURL=keyPackagesStatusStore.js.map
@@ -122,10 +122,19 @@ export declare class NotificationService extends EventEmitter {
122
122
  private scheduleTaskToRenewKeyMaterial;
123
123
  /**
124
124
  * ## MLS only ##
125
- * Get all pending proposals from the database and schedule them
125
+ * Get all keying material last update dates and schedule tasks for renewal
126
126
  * Function must only be called once, after application start
127
127
  *
128
128
  */
129
129
  checkForKeyMaterialsUpdate(): Promise<void>;
130
+ private scheduleKeyPackagesSync;
131
+ private syncKeyPackages;
132
+ /**
133
+ * ## MLS only ##
134
+ * Get date of last key packages count query and schedule a task to sync it with backend
135
+ * Function must only be called once, after application start
136
+ *
137
+ */
138
+ checkForKeyPackagesBackendSync(): Promise<void>;
130
139
  }
131
140
  export {};
@@ -68,11 +68,13 @@ const protocol_messaging_1 = require("@wireapp/protocol-messaging");
68
68
  const bazinga64_1 = require("bazinga64");
69
69
  const TaskScheduler_1 = require("../util/TaskScheduler/TaskScheduler");
70
70
  const LowPrecisionTaskScheduler_1 = require("../util/LowPrecisionTaskScheduler/LowPrecisionTaskScheduler");
71
+ const keyPackagesStatusStore_1 = require("../mls/keyPackagesStatusStore/keyPackagesStatusStore");
71
72
  var TOPIC;
72
73
  (function (TOPIC) {
73
74
  TOPIC["NOTIFICATION_ERROR"] = "NotificationService.TOPIC.NOTIFICATION_ERROR";
74
75
  })(TOPIC || (TOPIC = {}));
75
76
  const DEFAULT_KEYING_MATERIAL_UPDATE_THRESHOLD = 1000 * 60 * 60 * 24 * 30; //30 days
77
+ const INITIAL_NUMBER_OF_KEY_PACKAGES = 100;
76
78
  class NotificationService extends events_1.EventEmitter {
77
79
  constructor(apiClient, cryptographyService, mlsService, storeEngine) {
78
80
  super();
@@ -449,7 +451,7 @@ class NotificationService extends events_1.EventEmitter {
449
451
  }
450
452
  /**
451
453
  * ## MLS only ##
452
- * Get all pending proposals from the database and schedule them
454
+ * Get all keying material last update dates and schedule tasks for renewal
453
455
  * Function must only be called once, after application start
454
456
  *
455
457
  */
@@ -462,6 +464,44 @@ class NotificationService extends events_1.EventEmitter {
462
464
  this.logger.error('Could not get last key material update dates', error);
463
465
  }
464
466
  }
467
+ scheduleKeyPackagesSync(firingDate) {
468
+ TaskScheduler_1.TaskScheduler.addTask({
469
+ firingDate,
470
+ key: 'try-key-packages-backend-sync',
471
+ task: () => this.syncKeyPackages(),
472
+ });
473
+ }
474
+ async syncKeyPackages() {
475
+ const validKeyPackagesCount = await this.mlsService.clientValidKeypackagesCount();
476
+ const lastQueryDate = new Date().getTime();
477
+ await keyPackagesStatusStore_1.keyPackagesStatusStore.saveState({ lastQueryDate });
478
+ const minAllowedNumberOfKeyPackages = INITIAL_NUMBER_OF_KEY_PACKAGES / 2;
479
+ if (validKeyPackagesCount <= minAllowedNumberOfKeyPackages) {
480
+ const clientId = this.apiClient.validatedClientId;
481
+ //check numbers of keys on backend
482
+ const backendKeyPackagesCount = await this.apiClient.api.client.getMLSKeyPackageCount(clientId);
483
+ if (backendKeyPackagesCount <= minAllowedNumberOfKeyPackages) {
484
+ //upload new keys
485
+ const newKeyPackages = await this.mlsService.clientKeypackages(INITIAL_NUMBER_OF_KEY_PACKAGES);
486
+ await this.mlsService.uploadMLSKeyPackages(newKeyPackages, clientId);
487
+ }
488
+ }
489
+ //schedule new task after next 24h
490
+ const nextKeyPackagesQueryDate = lastQueryDate + commons_1.TimeUtil.TimeInMillis.DAY;
491
+ this.scheduleKeyPackagesSync(nextKeyPackagesQueryDate);
492
+ }
493
+ /**
494
+ * ## MLS only ##
495
+ * Get date of last key packages count query and schedule a task to sync it with backend
496
+ * Function must only be called once, after application start
497
+ *
498
+ */
499
+ async checkForKeyPackagesBackendSync() {
500
+ const { lastQueryDate } = keyPackagesStatusStore_1.keyPackagesStatusStore.getState();
501
+ //schedule a task lastKeyPackagesQueryDate + 24H
502
+ const nextKeyPackagesQueryDate = lastQueryDate + commons_1.TimeUtil.TimeInMillis.DAY;
503
+ this.scheduleKeyPackagesSync(nextKeyPackagesQueryDate);
504
+ }
465
505
  }
466
506
  exports.NotificationService = NotificationService;
467
507
  NotificationService.TOPIC = TOPIC;