@wireapp/core 26.0.0 → 27.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,41 @@
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
+ ## [27.0.1](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/compare/@wireapp/core@27.0.0...@wireapp/core@27.0.1) (2022-05-18)
7
+
8
+ **Note:** Version bump only for package @wireapp/core
9
+
10
+
11
+
12
+
13
+
14
+ # [27.0.0](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/compare/@wireapp/core@26.1.0...@wireapp/core@27.0.0) (2022-05-17)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * Avoid silently creating client when initializing core ([#4264](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/issues/4264)) ([65a843a](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/commit/65a843a2052dad2543e6cf046aca55ce85cc7c5e))
20
+
21
+
22
+ ### BREAKING CHANGES
23
+
24
+ * if you were relying on account.init() to also create a new client, this behavior now change and will throw an error instead. If you also want to create a device (if it doesn't exist already), you should use the account.login() or account.initClient() methods instead
25
+
26
+
27
+
28
+
29
+
30
+ # [26.1.0](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/compare/@wireapp/core@26.0.0...@wireapp/core@26.1.0) (2022-05-16)
31
+
32
+
33
+ ### Features
34
+
35
+ * Allow consumer to set number of prekeys generated ([#4263](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/issues/4263)) ([648ecda](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/commit/648ecdad260488e1d07965a84a28c346d6f015c3))
36
+
37
+
38
+
39
+
40
+
6
41
  # [26.0.0](https://github.com/wireapp/wire-web-packages/tree/main/packages/core/compare/@wireapp/core@25.3.1...@wireapp/core@26.0.0) (2022-05-16)
7
42
 
8
43
 
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "dependencies": {
6
6
  "@types/long": "4.0.1",
7
7
  "@types/node": "~14",
8
- "@wireapp/api-client": "19.2.0",
8
+ "@wireapp/api-client": "19.2.1",
9
9
  "@wireapp/cryptobox": "12.8.0",
10
10
  "bazinga64": "5.10.0",
11
11
  "hash.js": "1.1.7",
@@ -69,6 +69,6 @@
69
69
  "test:project": "yarn dist && yarn test",
70
70
  "test:node": "nyc jasmine --config=jasmine.json"
71
71
  },
72
- "version": "26.0.0",
73
- "gitHead": "730379c5b3701879632789ca73c1a9d55a9505ad"
72
+ "version": "27.0.1",
73
+ "gitHead": "d5755913d74a8718c19df31f5d6e0a22c8e2273c"
74
74
  }
@@ -53,11 +53,26 @@ export interface Account {
53
53
  on(event: TOPIC.ERROR, listener: (payload: CoreError) => void): this;
54
54
  }
55
55
  export declare type CreateStoreFn = (storeName: string, context: Context) => undefined | Promise<CRUDEngine | undefined>;
56
+ interface AccountOptions {
57
+ /** Used to store info in the database (will create a inMemory engine if returns undefined) */
58
+ createStore?: CreateStoreFn;
59
+ /** Number of prekeys to generate when creating a new device (defaults to 2)
60
+ * Prekeys are Diffie-Hellmann public keys which allow offline initiation of a secure Proteus session between two devices.
61
+ * Having a high value will:
62
+ * - make creating a new device consuming more CPU resources
63
+ * - make it less likely that all prekeys get consumed while the device is offline and the last resort prekey will not be used to create new session
64
+ * Having a low value will:
65
+ * - make creating a new device fast
66
+ * - make it likely that all prekeys get consumed while the device is offline and the last resort prekey will be used to create new session
67
+ */
68
+ nbPrekeys?: number;
69
+ }
56
70
  export declare class Account extends EventEmitter {
57
71
  private readonly apiClient;
58
72
  private readonly logger;
59
73
  private readonly createStore;
60
74
  private storeEngine?;
75
+ private readonly nbPrekeys;
61
76
  static readonly TOPIC: typeof TOPIC;
62
77
  service?: {
63
78
  account: AccountService;
@@ -77,22 +92,51 @@ export declare class Account extends EventEmitter {
77
92
  backendFeatures: BackendFeatures;
78
93
  /**
79
94
  * @param apiClient The apiClient instance to use in the core (will create a new new one if undefined)
80
- * @param storeEngineProvider Used to store info in the database (will create a inMemory engine if returns undefined)
95
+ * @param storeEngineProvider
81
96
  */
82
- constructor(apiClient?: APIClient, { createStore }?: {
83
- createStore?: CreateStoreFn;
84
- });
97
+ constructor(apiClient?: APIClient, { createStore, nbPrekeys }?: AccountOptions);
85
98
  private persistCookie;
86
99
  get clientId(): string;
87
100
  get userId(): string;
101
+ /**
102
+ * Will register a new user to the backend
103
+ *
104
+ * @param registration The user's data
105
+ * @param clientType Type of client to create (temporary or permanent)
106
+ */
88
107
  register(registration: RegisterData, clientType: ClientType): Promise<Context>;
108
+ /**
109
+ * Will init the core with an aleady existing client (both on backend and local)
110
+ * Will fail if local client cannot be found
111
+ *
112
+ * @param clientType The type of client the user is using (temporary or permanent)
113
+ * @param cookie The cookie to identify the user against backend (will use the browser's one if not given)
114
+ */
89
115
  init(clientType: ClientType, cookie?: Cookie, initClient?: boolean): Promise<Context>;
90
- initServices(context: Context): Promise<void>;
116
+ /**
117
+ * Will log the user in with the given credential.
118
+ * Will also create the local client and store it in DB
119
+ *
120
+ * @param loginData The credentials of the user
121
+ * @param initClient Should the call also create the local client
122
+ * @param clientInfo Info about the client to create (name, type...)
123
+ */
91
124
  login(loginData: LoginData, initClient?: boolean, clientInfo?: ClientInfo): Promise<Context>;
125
+ /**
126
+ * Will try to get the load the local client from local DB.
127
+ * If clientInfo are provided, will also create the client on backend and DB
128
+ * If clientInfo are not provideo, the method will fail if local client cannot be found
129
+ *
130
+ * @param loginData User's credentials
131
+ * @param clientInfo Will allow creating the client if the local client cannot be found (else will fail if local client is not found)
132
+ * @param entropyData Additional entropy data
133
+ * @returns The local existing client or newly created client
134
+ */
92
135
  initClient(loginData: LoginData, clientInfo?: ClientInfo, entropyData?: Uint8Array): Promise<{
93
136
  isNewClient: boolean;
94
137
  localClient: RegisteredClient;
95
138
  }>;
139
+ initServices(context: Context): Promise<void>;
96
140
  loadAndValidateLocalClient(): Promise<RegisteredClient>;
97
141
  private registerClient;
98
142
  private resetContext;
@@ -67,12 +67,17 @@ var TOPIC;
67
67
  (function (TOPIC) {
68
68
  TOPIC["ERROR"] = "Account.TOPIC.ERROR";
69
69
  })(TOPIC || (TOPIC = {}));
70
+ const coreDefaultClient = {
71
+ classification: client_1.ClientClassification.DESKTOP,
72
+ cookieLabel: 'default',
73
+ model: '@wireapp/core',
74
+ };
70
75
  class Account extends events_1.EventEmitter {
71
76
  /**
72
77
  * @param apiClient The apiClient instance to use in the core (will create a new new one if undefined)
73
- * @param storeEngineProvider Used to store info in the database (will create a inMemory engine if returns undefined)
78
+ * @param storeEngineProvider
74
79
  */
75
- constructor(apiClient = new api_client_1.APIClient(), { createStore = () => undefined } = {}) {
80
+ constructor(apiClient = new api_client_1.APIClient(), { createStore = () => undefined, nbPrekeys = 2 } = {}) {
76
81
  super();
77
82
  this.handlePayload = async (payload) => {
78
83
  switch (payload.type) {
@@ -90,6 +95,7 @@ class Account extends events_1.EventEmitter {
90
95
  };
91
96
  this.apiClient = apiClient;
92
97
  this.backendFeatures = this.apiClient.backendFeatures;
98
+ this.nbPrekeys = nbPrekeys;
93
99
  this.createStore = createStore;
94
100
  apiClient.on(api_client_1.APIClient.TOPIC.COOKIE_REFRESH, async (cookie) => {
95
101
  if (cookie && this.storeEngine) {
@@ -116,11 +122,24 @@ class Account extends events_1.EventEmitter {
116
122
  get userId() {
117
123
  return this.apiClient.validatedUserId;
118
124
  }
125
+ /**
126
+ * Will register a new user to the backend
127
+ *
128
+ * @param registration The user's data
129
+ * @param clientType Type of client to create (temporary or permanent)
130
+ */
119
131
  async register(registration, clientType) {
120
132
  const context = await this.apiClient.register(registration, clientType);
121
133
  await this.initServices(context);
122
134
  return context;
123
135
  }
136
+ /**
137
+ * Will init the core with an aleady existing client (both on backend and local)
138
+ * Will fail if local client cannot be found
139
+ *
140
+ * @param clientType The type of client the user is using (temporary or permanent)
141
+ * @param cookie The cookie to identify the user against backend (will use the browser's one if not given)
142
+ */
124
143
  async init(clientType, cookie, initClient = true) {
125
144
  const context = await this.apiClient.init(clientType, cookie);
126
145
  await this.initServices(context);
@@ -129,44 +148,15 @@ class Account extends events_1.EventEmitter {
129
148
  }
130
149
  return context;
131
150
  }
132
- async initServices(context) {
133
- this.storeEngine = await this.initEngine(context);
134
- const accountService = new account_1.AccountService(this.apiClient);
135
- const assetService = new conversation_1.AssetService(this.apiClient);
136
- const cryptographyService = new cryptography_1.CryptographyService(this.apiClient, this.storeEngine, {
137
- // We want to encrypt with fully qualified session ids, only if the backend is federated with other backends
138
- useQualifiedIds: this.backendFeatures.isFederated,
139
- });
140
- const clientService = new client_2.ClientService(this.apiClient, this.storeEngine, cryptographyService);
141
- const connectionService = new connection_1.ConnectionService(this.apiClient);
142
- const giphyService = new giphy_1.GiphyService(this.apiClient);
143
- const linkPreviewService = new linkPreview_1.LinkPreviewService(assetService);
144
- const conversationService = new conversation_1.ConversationService(this.apiClient, cryptographyService, {
145
- // We can use qualified ids to send messages as long as the backend supports federated endpoints
146
- useQualifiedIds: this.backendFeatures.federationEndpoints,
147
- });
148
- const notificationService = new notification_1.NotificationService(this.apiClient, cryptographyService, this.storeEngine);
149
- const selfService = new self_1.SelfService(this.apiClient);
150
- const teamService = new team_1.TeamService(this.apiClient);
151
- const broadcastService = new broadcast_1.BroadcastService(this.apiClient, cryptographyService);
152
- const userService = new user_1.UserService(this.apiClient, broadcastService, conversationService, connectionService);
153
- this.service = {
154
- account: accountService,
155
- asset: assetService,
156
- broadcast: broadcastService,
157
- client: clientService,
158
- connection: connectionService,
159
- conversation: conversationService,
160
- cryptography: cryptographyService,
161
- giphy: giphyService,
162
- linkPreview: linkPreviewService,
163
- notification: notificationService,
164
- self: selfService,
165
- team: teamService,
166
- user: userService,
167
- };
168
- }
169
- async login(loginData, initClient = true, clientInfo) {
151
+ /**
152
+ * Will log the user in with the given credential.
153
+ * Will also create the local client and store it in DB
154
+ *
155
+ * @param loginData The credentials of the user
156
+ * @param initClient Should the call also create the local client
157
+ * @param clientInfo Info about the client to create (name, type...)
158
+ */
159
+ async login(loginData, initClient = true, clientInfo = coreDefaultClient) {
170
160
  this.resetContext();
171
161
  auth_2.LoginSanitizer.removeNonPrintableCharacters(loginData);
172
162
  const context = await this.apiClient.login(loginData);
@@ -176,6 +166,16 @@ class Account extends events_1.EventEmitter {
176
166
  }
177
167
  return context;
178
168
  }
169
+ /**
170
+ * Will try to get the load the local client from local DB.
171
+ * If clientInfo are provided, will also create the client on backend and DB
172
+ * If clientInfo are not provideo, the method will fail if local client cannot be found
173
+ *
174
+ * @param loginData User's credentials
175
+ * @param clientInfo Will allow creating the client if the local client cannot be found (else will fail if local client is not found)
176
+ * @param entropyData Additional entropy data
177
+ * @returns The local existing client or newly created client
178
+ */
179
179
  async initClient(loginData, clientInfo, entropyData) {
180
180
  var _a, _b;
181
181
  if (!this.service) {
@@ -186,6 +186,10 @@ class Account extends events_1.EventEmitter {
186
186
  return { isNewClient: false, localClient };
187
187
  }
188
188
  catch (error) {
189
+ if (!clientInfo) {
190
+ // If no client info provided, the client should not be created
191
+ throw error;
192
+ }
189
193
  // There was no client so we need to "create" and "register" a client
190
194
  const notFoundInDatabase = error instanceof cryptobox.error.CryptoboxError ||
191
195
  error.constructor.name === 'CryptoboxError' ||
@@ -216,6 +220,44 @@ class Account extends events_1.EventEmitter {
216
220
  throw error;
217
221
  }
218
222
  }
223
+ async initServices(context) {
224
+ this.storeEngine = await this.initEngine(context);
225
+ const accountService = new account_1.AccountService(this.apiClient);
226
+ const assetService = new conversation_1.AssetService(this.apiClient);
227
+ const cryptographyService = new cryptography_1.CryptographyService(this.apiClient, this.storeEngine, {
228
+ // We want to encrypt with fully qualified session ids, only if the backend is federated with other backends
229
+ useQualifiedIds: this.backendFeatures.isFederated,
230
+ nbPrekeys: this.nbPrekeys,
231
+ });
232
+ const clientService = new client_2.ClientService(this.apiClient, this.storeEngine, cryptographyService);
233
+ const connectionService = new connection_1.ConnectionService(this.apiClient);
234
+ const giphyService = new giphy_1.GiphyService(this.apiClient);
235
+ const linkPreviewService = new linkPreview_1.LinkPreviewService(assetService);
236
+ const conversationService = new conversation_1.ConversationService(this.apiClient, cryptographyService, {
237
+ // We can use qualified ids to send messages as long as the backend supports federated endpoints
238
+ useQualifiedIds: this.backendFeatures.federationEndpoints,
239
+ });
240
+ const notificationService = new notification_1.NotificationService(this.apiClient, cryptographyService, this.storeEngine);
241
+ const selfService = new self_1.SelfService(this.apiClient);
242
+ const teamService = new team_1.TeamService(this.apiClient);
243
+ const broadcastService = new broadcast_1.BroadcastService(this.apiClient, cryptographyService);
244
+ const userService = new user_1.UserService(this.apiClient, broadcastService, conversationService, connectionService);
245
+ this.service = {
246
+ account: accountService,
247
+ asset: assetService,
248
+ broadcast: broadcastService,
249
+ client: clientService,
250
+ connection: connectionService,
251
+ conversation: conversationService,
252
+ cryptography: cryptographyService,
253
+ giphy: giphyService,
254
+ linkPreview: linkPreviewService,
255
+ notification: notificationService,
256
+ self: selfService,
257
+ team: teamService,
258
+ user: userService,
259
+ };
260
+ }
219
261
  async loadAndValidateLocalClient() {
220
262
  await this.service.cryptography.initCryptobox();
221
263
  const loadedClient = await this.service.client.getLocalClient();
@@ -223,7 +265,7 @@ class Account extends events_1.EventEmitter {
223
265
  this.apiClient.context.clientId = loadedClient.id;
224
266
  return loadedClient;
225
267
  }
226
- async registerClient(loginData, clientInfo, entropyData) {
268
+ async registerClient(loginData, clientInfo = coreDefaultClient, entropyData) {
227
269
  if (!this.service) {
228
270
  throw new Error('Services are not set.');
229
271
  }
@@ -36,5 +36,5 @@ export declare class ClientService {
36
36
  getLocalClient(): Promise<MetaClient>;
37
37
  createLocalClient(client: RegisteredClient, domain?: string): Promise<MetaClient>;
38
38
  synchronizeClients(): Promise<MetaClient[]>;
39
- register(loginData: LoginData, clientInfo?: ClientInfo, entropyData?: Uint8Array): Promise<RegisteredClient>;
39
+ register(loginData: LoginData, clientInfo: ClientInfo, entropyData?: Uint8Array): Promise<RegisteredClient>;
40
40
  }
@@ -71,11 +71,7 @@ class ClientService {
71
71
  return this.database.createClientList(this.apiClient.context.userId, filteredClients, (_a = this.apiClient.context) === null || _a === void 0 ? void 0 : _a.domain);
72
72
  }
73
73
  // TODO: Split functionality into "create" and "register" client
74
- async register(loginData, clientInfo = {
75
- classification: client_1.ClientClassification.DESKTOP,
76
- cookieLabel: 'default',
77
- model: '@wireapp/core',
78
- }, entropyData) {
74
+ async register(loginData, clientInfo, entropyData) {
79
75
  if (!this.apiClient.context) {
80
76
  throw new Error('Context is not set.');
81
77
  }
@@ -20,8 +20,9 @@ export declare class CryptographyService {
20
20
  private readonly logger;
21
21
  cryptobox: Cryptobox;
22
22
  private readonly database;
23
- constructor(apiClient: APIClient, storeEngine: CRUDEngine, config?: {
24
- useQualifiedIds?: boolean;
23
+ constructor(apiClient: APIClient, storeEngine: CRUDEngine, config: {
24
+ useQualifiedIds: boolean;
25
+ nbPrekeys: number;
25
26
  });
26
27
  constructSessionId(userId: string | QualifiedId, clientId: string, domain?: string): string;
27
28
  static convertArrayRecipientsToBase64(recipients: OTRRecipients<Uint8Array>): OTRRecipients<string>;
@@ -32,11 +32,11 @@ const util_1 = require("../util");
32
32
  const CryptographyDatabaseRepository_1 = require("./CryptographyDatabaseRepository");
33
33
  const GenericMessageMapper_1 = require("./GenericMessageMapper");
34
34
  class CryptographyService {
35
- constructor(apiClient, storeEngine, config = {}) {
35
+ constructor(apiClient, storeEngine, config) {
36
36
  this.apiClient = apiClient;
37
37
  this.storeEngine = storeEngine;
38
38
  this.config = config;
39
- this.cryptobox = new cryptobox_1.Cryptobox(this.storeEngine);
39
+ this.cryptobox = new cryptobox_1.Cryptobox(this.storeEngine, config.nbPrekeys);
40
40
  this.database = new CryptographyDatabaseRepository_1.CryptographyDatabaseRepository(this.storeEngine);
41
41
  this.logger = (0, logdown_1.default)('@wireapp/core/cryptography/CryptographyService', {
42
42
  logger: console,