@wireapp/core 46.29.3 → 46.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/Account.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { RegisterData, Context, Cookie, LoginData } from '@wireapp/api-client/lib/auth';
2
- import { ClientType, RegisteredClient } from '@wireapp/api-client/lib/client/';
2
+ import { ClientCapability, ClientType, RegisteredClient } from '@wireapp/api-client/lib/client/';
3
3
  import * as Events from '@wireapp/api-client/lib/event';
4
+ import { Notification } from '@wireapp/api-client/lib/notification/';
5
+ import { ConsumableNotification } from '@wireapp/api-client/lib/notification/ConsumableNotification';
4
6
  import { APIClient, BackendFeatures } from '@wireapp/api-client';
5
7
  import { TypedEventEmitter } from '@wireapp/commons';
6
8
  import { CRUDEngine } from '@wireapp/store-engine';
@@ -65,6 +67,12 @@ export declare enum EVENTS {
65
67
  type Events = {
66
68
  [EVENTS.NEW_SESSION]: NewClient;
67
69
  };
70
+ export declare const AccountLocalStorageStore: {
71
+ get: (key: string) => string | undefined;
72
+ add: (key: string, value: string) => void;
73
+ remove: (key: string) => void;
74
+ has: (key: string) => boolean;
75
+ };
68
76
  export declare class Account extends TypedEventEmitter<Events> {
69
77
  private options;
70
78
  private readonly apiClient;
@@ -75,6 +83,9 @@ export declare class Account extends TypedEventEmitter<Events> {
75
83
  private db?;
76
84
  private encryptedDb?;
77
85
  private coreCallbacks?;
86
+ private totalPendingNotifications;
87
+ private remainingNotifications;
88
+ private connectionState;
78
89
  service?: {
79
90
  mls?: MLSService;
80
91
  e2eIdentity?: E2EIServiceExternal;
@@ -157,7 +168,7 @@ export declare class Account extends TypedEventEmitter<Events> {
157
168
  registerClient(loginData: LoginData, clientInfo?: ClientInfo,
158
169
  /** will add extra manual entropy to the client's identity being created */
159
170
  entropyData?: Uint8Array): Promise<RegisteredClient>;
160
- getLocalClient(): Promise<RegisteredClient | undefined> | undefined;
171
+ getLocalClient(): Promise<import("./client/ClientService").MetaClient | undefined> | undefined;
161
172
  /**
162
173
  * Will initiate all the cryptographic material of the given registered device and setup all the background tasks.
163
174
  *
@@ -204,7 +215,7 @@ export declare class Account extends TypedEventEmitter<Events> {
204
215
  * @param callbacks callbacks that will be called to handle different events
205
216
  * @returns close a function that will disconnect from the websocket
206
217
  */
207
- listen({ onEvent, onConnectionStateChanged, onNotificationStreamProgress, onMissedNotifications, dryRun, }?: {
218
+ listen({ onEvent, onConnectionStateChanged: onConnectionStateChangedCallBack, onNotificationStreamProgress, onMissedNotifications, dryRun, }?: {
208
219
  /**
209
220
  * Called when a new event arrives from backend
210
221
  * @param payload the payload of the event. Contains the raw event received and the decrypted data (if event was encrypted)
@@ -234,7 +245,62 @@ export declare class Account extends TypedEventEmitter<Events> {
234
245
  * When set will not decrypt and not store the last notification ID. This is useful if you only want to subscribe to unencrypted backend events
235
246
  */
236
247
  dryRun?: boolean;
237
- }): () => void;
248
+ }): Promise<() => void>;
249
+ private createConnectionStateChangedHandler;
250
+ /**
251
+ * Creates the event handler that is invoked for each decrypted event from the backend.
252
+ * Responsible for handling specific event types like `MESSAGE_TIMER_UPDATE`, and then
253
+ * forwarding the event to the consumer via the `onEvent` callback.
254
+ */
255
+ private createEventHandler;
256
+ private createLegacyNotificationHandler;
257
+ private createNotificationHandler;
258
+ /**
259
+ * Returns a function to handle missed notifications — i.e., when the backend indicates
260
+ * that some notifications were lost due to age (typically >28 days).
261
+ * Also handles MLS-specific epoch mismatch recovery by triggering a conversation rejoin.
262
+ */
263
+ private createLegacyMissedNotificationsHandler;
264
+ /**
265
+ * Returns a processor function for the notification stream (legacy sync).
266
+ * It pauses message sending and MLS rejoining during stream handling to prevent race conditions,
267
+ * then resumes normal operations after sync is complete.
268
+ *
269
+ * @param handlers Various logic handlers wired to notification callbacks
270
+ */
271
+ private createLegacyNotificationStreamProcessor;
272
+ /**
273
+ * Sets up WebSocket event listeners for:
274
+ * - Incoming backend messages
275
+ * - WebSocket state changes
276
+ * On each new backend message, we pass it to the notification handler.
277
+ * On state changes, we map raw socket states to public connection states and emit them.
278
+ */
279
+ private setupWebSocketListeners;
280
+ /**
281
+ * Handles logic for reacting to a missed notification event.
282
+ *
283
+ * The backend sends a special "missed notification" signal if it detects
284
+ * that the client has missed one or more notifications. Once this signal is sent,
285
+ * the backend will **stop sending all further notifications** until the client
286
+ * acknowledges the missed state.
287
+ *
288
+ * Because our app currently lacks functionality to perform a full real-time sync
289
+ * while running, we must reload the application to re-fetch the entire state.
290
+ *
291
+ * On first detection of the missed notification:
292
+ * - We set a local storage flag (`has_missing_notification`) to mark that we've
293
+ * entered this state.
294
+ * - We reload the application so the state can be re-fetched from scratch.
295
+ *
296
+ * On the next load:
297
+ * - If the flag is already present, we acknowledge the missed notification via
298
+ * the WebSocket transport, unblocking the backend so it resumes sending updates
299
+ * then we remove the flag.
300
+ */
301
+ private reactToMissedNotification;
302
+ getClientCapabilities(): ClientCapability[];
303
+ checkIsConsumable(notification: Notification | ConsumableNotification): notification is ConsumableNotification;
238
304
  private generateDbName;
239
305
  private generateCoreDbName;
240
306
  private generateEncryptedDbName;
@@ -1 +1 @@
1
- {"version":3,"file":"Account.d.ts","sourceRoot":"","sources":["../src/Account.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Account.d.ts","sourceRoot":"","sources":["../src/Account.ts"],"names":[],"mappings":"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"}
package/lib/Account.js CHANGED
@@ -41,10 +41,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
41
41
  return result;
42
42
  };
43
43
  Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.Account = exports.EVENTS = exports.ConnectionState = void 0;
44
+ exports.Account = exports.AccountLocalStorageStore = exports.EVENTS = exports.ConnectionState = void 0;
45
45
  const auth_1 = require("@wireapp/api-client/lib/auth");
46
46
  const client_1 = require("@wireapp/api-client/lib/client/");
47
47
  const event_1 = require("@wireapp/api-client/lib/event");
48
+ const ConsumableNotification_1 = require("@wireapp/api-client/lib/notification/ConsumableNotification");
48
49
  const tcp_1 = require("@wireapp/api-client/lib/tcp/");
49
50
  const ReconnectingWebsocket_1 = require("@wireapp/api-client/lib/tcp/ReconnectingWebsocket");
50
51
  const team_1 = require("@wireapp/api-client/lib/team");
@@ -76,6 +77,7 @@ const self_1 = require("./self/");
76
77
  const CoreDB_1 = require("./storage/CoreDB");
77
78
  const team_2 = require("./team/");
78
79
  const user_1 = require("./user/");
80
+ const LocalStorageStore_1 = require("./util/LocalStorageStore");
79
81
  const RecurringTaskScheduler_1 = require("./util/RecurringTaskScheduler");
80
82
  var ConnectionState;
81
83
  (function (ConnectionState) {
@@ -101,6 +103,7 @@ var EVENTS;
101
103
  */
102
104
  EVENTS["NEW_SESSION"] = "new_session";
103
105
  })(EVENTS || (exports.EVENTS = EVENTS = {}));
106
+ exports.AccountLocalStorageStore = (0, LocalStorageStore_1.LocalStorageStore)('core_account');
104
107
  class Account extends commons_1.TypedEventEmitter {
105
108
  options;
106
109
  apiClient;
@@ -111,6 +114,9 @@ class Account extends commons_1.TypedEventEmitter {
111
114
  db;
112
115
  encryptedDb;
113
116
  coreCallbacks;
117
+ totalPendingNotifications = 0;
118
+ remainingNotifications = 0;
119
+ connectionState = ConnectionState.CLOSED;
114
120
  service;
115
121
  backendFeatures;
116
122
  recurringTaskScheduler;
@@ -419,11 +425,64 @@ class Account extends commons_1.TypedEventEmitter {
419
425
  * @param callbacks callbacks that will be called to handle different events
420
426
  * @returns close a function that will disconnect from the websocket
421
427
  */
422
- listen({ onEvent = () => { }, onConnectionStateChanged = () => { }, onNotificationStreamProgress = () => { }, onMissedNotifications = () => { }, dryRun = false, } = {}) {
428
+ async listen({ onEvent = () => { }, onConnectionStateChanged: onConnectionStateChangedCallBack = () => { }, onNotificationStreamProgress = () => { }, onMissedNotifications = () => { }, dryRun = false, } = {}) {
423
429
  if (!this.currentClient) {
424
430
  throw new Error('Client has not been initialized - please login first');
425
431
  }
426
- const handleEvent = async (payload, source) => {
432
+ const onConnectionStateChanged = this.createConnectionStateChangedHandler(onConnectionStateChangedCallBack);
433
+ const handleEvent = this.createEventHandler(onEvent);
434
+ const handleLegacyNotification = this.createLegacyNotificationHandler(handleEvent, dryRun);
435
+ const handleNotification = this.createNotificationHandler(handleEvent, onNotificationStreamProgress, onConnectionStateChanged, dryRun);
436
+ const handleMissedNotifications = this.createLegacyMissedNotificationsHandler(onMissedNotifications);
437
+ const processNotificationStream = this.createLegacyNotificationStreamProcessor({
438
+ handleLegacyNotification,
439
+ handleMissedNotifications,
440
+ onNotificationStreamProgress,
441
+ onConnectionStateChanged,
442
+ });
443
+ this.setupWebSocketListeners(handleNotification, onConnectionStateChanged);
444
+ const isClientCapableOfConsumableNotifications = this.getClientCapabilities().includes(client_1.ClientCapability.CONSUMABLE_NOTIFICATIONS);
445
+ /*
446
+ * When enabling async notifications, be aware that the backend maintains a separate queue
447
+ * for new async notifications (/events weboscket endpoint), which only starts populating *after* the client declares support
448
+ * for async notifications.
449
+ *
450
+ * Therefore, after declaring support, it's necessary to perform one final fetch from the legacy
451
+ * system to ensure no notifications are missed—since older notifications won't
452
+ * appear in the new queue.
453
+ *
454
+ * These two systems are separate, and the transition timing
455
+ * is important to avoid missing any messages during the switch.
456
+ */
457
+ if (!isClientCapableOfConsumableNotifications) {
458
+ // let the backend now client is capable of consumable notifications
459
+ await this.service?.client.putClientCapabilities(this.currentClient.id, {
460
+ capabilities: [client_1.ClientCapability.LEGAL_HOLD_IMPLICIT_CONSENT, client_1.ClientCapability.CONSUMABLE_NOTIFICATIONS],
461
+ });
462
+ // do a quick legacy sync without connecting to any websockets
463
+ await processNotificationStream();
464
+ }
465
+ this.apiClient.connect();
466
+ return () => {
467
+ this.apiClient.disconnect();
468
+ onConnectionStateChanged(ConnectionState.CLOSED);
469
+ this.apiClient.transport.ws.removeAllListeners();
470
+ };
471
+ }
472
+ createConnectionStateChangedHandler(onConnectionStateChanged) {
473
+ return (state) => {
474
+ this.connectionState = state;
475
+ onConnectionStateChanged(state);
476
+ this.logger.info(`Connection state changed to: ${state}`);
477
+ };
478
+ }
479
+ /**
480
+ * Creates the event handler that is invoked for each decrypted event from the backend.
481
+ * Responsible for handling specific event types like `MESSAGE_TIMER_UPDATE`, and then
482
+ * forwarding the event to the consumer via the `onEvent` callback.
483
+ */
484
+ createEventHandler(onEvent) {
485
+ return async (payload, source) => {
427
486
  const { event } = payload;
428
487
  switch (event?.type) {
429
488
  case event_1.CONVERSATION_EVENT.MESSAGE_TIMER_UPDATE: {
@@ -433,9 +492,12 @@ class Account extends commons_1.TypedEventEmitter {
433
492
  break;
434
493
  }
435
494
  }
436
- await onEvent(payload, source);
495
+ // Always forward the event to the consumer
496
+ onEvent(payload, source);
437
497
  };
438
- const handleNotification = async (notification, source) => {
498
+ }
499
+ createLegacyNotificationHandler(handleEvent, dryRun) {
500
+ return async (notification, source) => {
439
501
  try {
440
502
  const messages = this.service.notification.handleNotification(notification, source, dryRun);
441
503
  for await (const message of messages) {
@@ -443,58 +505,153 @@ class Account extends commons_1.TypedEventEmitter {
443
505
  }
444
506
  }
445
507
  catch (error) {
446
- this.logger.error(`Failed to handle notification ID "${notification.id}": ${error.message}`, error);
508
+ this.logger.error(`Failed to handle legacy notification "${notification.id}": ${error.message}`, error);
447
509
  }
448
510
  };
449
- this.apiClient.transport.ws.removeAllListeners(tcp_1.WebSocketClient.TOPIC.ON_MESSAGE);
450
- this.apiClient.transport.ws.on(tcp_1.WebSocketClient.TOPIC.ON_MESSAGE, notification => handleNotification(notification, notification_1.NotificationSource.WEBSOCKET));
451
- this.apiClient.transport.ws.on(tcp_1.WebSocketClient.TOPIC.ON_STATE_CHANGE, wsState => {
452
- const mapping = {
453
- [ReconnectingWebsocket_1.WEBSOCKET_STATE.CLOSED]: ConnectionState.CLOSED,
454
- [ReconnectingWebsocket_1.WEBSOCKET_STATE.CONNECTING]: ConnectionState.CONNECTING,
455
- };
456
- const connectionState = mapping[wsState];
457
- if (connectionState) {
458
- onConnectionStateChanged(connectionState);
511
+ }
512
+ createNotificationHandler(handleEvent, onNotificationStreamProgress, onConnectionStateChanged, dryRun) {
513
+ return async (notification, source) => {
514
+ try {
515
+ if (notification.type === ConsumableNotification_1.ConsumableEvent.MISSED) {
516
+ this.reactToMissedNotification();
517
+ return;
518
+ }
519
+ if (notification.type === ConsumableNotification_1.ConsumableEvent.MESSAGE_COUNT) {
520
+ const { data: { count }, } = notification;
521
+ onNotificationStreamProgress({ total: count, done: 0 });
522
+ this.totalPendingNotifications = count;
523
+ this.remainingNotifications = 0;
524
+ this.apiClient.transport.ws.acknowledgeMessageCountNotification();
525
+ (0, messageSender_1.pauseMessageSending)();
526
+ onConnectionStateChanged(ConnectionState.PROCESSING_NOTIFICATIONS);
527
+ if (count === 0) {
528
+ (0, messageSender_1.resumeMessageSending)();
529
+ onConnectionStateChanged(ConnectionState.LIVE);
530
+ }
531
+ return;
532
+ }
533
+ const event = notification.data.event;
534
+ const messages = this.service.notification.handleNotification(event, source, dryRun);
535
+ if (this.connectionState !== ConnectionState.LIVE) {
536
+ this.remainingNotifications++;
537
+ onNotificationStreamProgress({
538
+ done: this.remainingNotifications,
539
+ total: this.totalPendingNotifications,
540
+ });
541
+ }
542
+ this.apiClient.transport.ws.acknowledgeNotification(notification);
543
+ for await (const message of messages) {
544
+ await handleEvent(message, source);
545
+ }
546
+ if (this.totalPendingNotifications === this.remainingNotifications &&
547
+ this.connectionState !== ConnectionState.LIVE) {
548
+ (0, messageSender_1.resumeMessageSending)();
549
+ onConnectionStateChanged(ConnectionState.LIVE);
550
+ }
459
551
  }
460
- });
461
- const handleMissedNotifications = async (notificationId) => {
552
+ catch (error) {
553
+ this.logger.error(`Failed to handle consumable notification "${notification.type}": ${error.message}`, error);
554
+ }
555
+ };
556
+ }
557
+ /**
558
+ * Returns a function to handle missed notifications — i.e., when the backend indicates
559
+ * that some notifications were lost due to age (typically >28 days).
560
+ * Also handles MLS-specific epoch mismatch recovery by triggering a conversation rejoin.
561
+ */
562
+ createLegacyMissedNotificationsHandler(onMissedNotifications) {
563
+ return async (notificationId) => {
462
564
  if (this.hasMLSDevice) {
463
565
  (0, conversationRejoinQueue_1.queueConversationRejoin)('all-conversations', () => this.service.conversation.handleConversationsEpochMismatch());
464
566
  }
465
567
  return onMissedNotifications(notificationId);
466
568
  };
467
- const processNotificationStream = async (abortHandler) => {
468
- // Lock websocket in order to buffer any message that arrives while we handle the notification stream
469
- this.apiClient.transport.ws.lock();
569
+ }
570
+ /**
571
+ * Returns a processor function for the notification stream (legacy sync).
572
+ * It pauses message sending and MLS rejoining during stream handling to prevent race conditions,
573
+ * then resumes normal operations after sync is complete.
574
+ *
575
+ * @param handlers Various logic handlers wired to notification callbacks
576
+ */
577
+ createLegacyNotificationStreamProcessor({ handleLegacyNotification, handleMissedNotifications, onNotificationStreamProgress, onConnectionStateChanged, }) {
578
+ return async () => {
470
579
  (0, messageSender_1.pauseMessageSending)();
471
580
  // We want to avoid triggering rejoins of out-of-sync MLS conversations while we are processing the notification stream
472
581
  (0, conversationRejoinQueue_1.pauseRejoiningMLSConversations)();
473
582
  onConnectionStateChanged(ConnectionState.PROCESSING_NOTIFICATIONS);
474
583
  const results = await this.service.notification.processNotificationStream(async (notification, source, progress) => {
475
- await handleNotification(notification, source);
584
+ await handleLegacyNotification(notification, source);
476
585
  onNotificationStreamProgress(progress);
477
- }, handleMissedNotifications, abortHandler);
478
- this.logger.info('Finished processing notifications', results);
479
- if (abortHandler.signal.aborted) {
480
- this.logger.warn('Ending connection process as websocket was closed');
481
- return;
482
- }
483
- onConnectionStateChanged(ConnectionState.LIVE);
484
- // We can now unlock the websocket and let the new messages being handled and decrypted
485
- this.apiClient.transport.ws.unlock();
586
+ }, handleMissedNotifications);
587
+ this.logger.info('Finished processing notifications from the legacy endpoint', results);
486
588
  // We need to wait for the notification stream to be fully handled before releasing the message sending queue.
487
589
  // This is due to the nature of how message are encrypted, any change in mls epoch needs to happen before we start encrypting any kind of messages
488
590
  this.logger.info(`Resuming message sending. ${(0, messageSender_1.getQueueLength)()} messages to be sent`);
489
591
  (0, messageSender_1.resumeMessageSending)();
490
592
  (0, conversationRejoinQueue_1.resumeRejoiningMLSConversations)();
593
+ onConnectionStateChanged(ConnectionState.LIVE);
491
594
  };
492
- this.apiClient.connect(processNotificationStream);
493
- return () => {
494
- this.apiClient.disconnect();
495
- onConnectionStateChanged(ConnectionState.CLOSED);
496
- this.apiClient.transport.ws.removeAllListeners();
497
- };
595
+ }
596
+ /**
597
+ * Sets up WebSocket event listeners for:
598
+ * - Incoming backend messages
599
+ * - WebSocket state changes
600
+ * On each new backend message, we pass it to the notification handler.
601
+ * On state changes, we map raw socket states to public connection states and emit them.
602
+ */
603
+ setupWebSocketListeners(handleNotification, onConnectionStateChanged) {
604
+ this.apiClient.transport.ws.removeAllListeners(tcp_1.WebSocketClient.TOPIC.ON_MESSAGE);
605
+ this.apiClient.transport.ws.on(tcp_1.WebSocketClient.TOPIC.ON_MESSAGE, notification => handleNotification(notification, notification_1.NotificationSource.WEBSOCKET));
606
+ this.apiClient.transport.ws.on(tcp_1.WebSocketClient.TOPIC.ON_STATE_CHANGE, wsState => {
607
+ const mapping = {
608
+ [ReconnectingWebsocket_1.WEBSOCKET_STATE.CLOSED]: ConnectionState.CLOSED,
609
+ [ReconnectingWebsocket_1.WEBSOCKET_STATE.CONNECTING]: ConnectionState.CONNECTING,
610
+ };
611
+ const connectionState = mapping[wsState];
612
+ if (connectionState) {
613
+ onConnectionStateChanged(connectionState);
614
+ }
615
+ });
616
+ }
617
+ /**
618
+ * Handles logic for reacting to a missed notification event.
619
+ *
620
+ * The backend sends a special "missed notification" signal if it detects
621
+ * that the client has missed one or more notifications. Once this signal is sent,
622
+ * the backend will **stop sending all further notifications** until the client
623
+ * acknowledges the missed state.
624
+ *
625
+ * Because our app currently lacks functionality to perform a full real-time sync
626
+ * while running, we must reload the application to re-fetch the entire state.
627
+ *
628
+ * On first detection of the missed notification:
629
+ * - We set a local storage flag (`has_missing_notification`) to mark that we've
630
+ * entered this state.
631
+ * - We reload the application so the state can be re-fetched from scratch.
632
+ *
633
+ * On the next load:
634
+ * - If the flag is already present, we acknowledge the missed notification via
635
+ * the WebSocket transport, unblocking the backend so it resumes sending updates
636
+ * then we remove the flag.
637
+ */
638
+ reactToMissedNotification() {
639
+ const localStorageKey = 'has_missing_notification';
640
+ // First-time handling: set flag and reload to trigger full re-fetch of state.
641
+ if (!exports.AccountLocalStorageStore.has(localStorageKey)) {
642
+ exports.AccountLocalStorageStore.add(localStorageKey, 'true');
643
+ window.location.reload();
644
+ return;
645
+ }
646
+ // After reload: acknowledge the missed notification so backend resumes notifications.
647
+ this.apiClient.transport.ws.acknowledgeMissedNotification();
648
+ exports.AccountLocalStorageStore.remove(localStorageKey);
649
+ }
650
+ getClientCapabilities() {
651
+ return this.currentClient?.capabilities || [];
652
+ }
653
+ checkIsConsumable(notification) {
654
+ return 'type' in notification;
498
655
  }
499
656
  generateDbName(context) {
500
657
  const clientType = context.clientType === client_1.ClientType.NONE ? '' : `@${context.clientType}`;
@@ -44,11 +44,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
44
44
  const auth_1 = require("@wireapp/api-client/lib/auth");
45
45
  const client_1 = require("@wireapp/api-client/lib/client");
46
46
  const conversation_1 = require("@wireapp/api-client/lib/conversation");
47
- const event_1 = require("@wireapp/api-client/lib/event");
48
47
  const http_1 = require("@wireapp/api-client/lib/http");
49
48
  const notification_1 = require("@wireapp/api-client/lib/notification");
49
+ const ConsumableNotification_1 = require("@wireapp/api-client/lib/notification/ConsumableNotification");
50
50
  const self_1 = require("@wireapp/api-client/lib/self");
51
- const tcp_1 = require("@wireapp/api-client/lib/tcp");
52
51
  const ReconnectingWebsocket_1 = require("@wireapp/api-client/lib/tcp/ReconnectingWebsocket");
53
52
  const http_status_codes_1 = require("http-status-codes");
54
53
  const jest_websocket_mock_1 = require("jest-websocket-mock");
@@ -105,6 +104,8 @@ describe('Account', () => {
105
104
  token_type: 'Bearer',
106
105
  user: 'aaf9a833-ef30-4c22-86a0-9adc8a15b3b4',
107
106
  };
107
+ const BACKEND_VERSION = 8;
108
+ const websocketServerAddress = `${MOCK_BACKEND.ws}/v${BACKEND_VERSION}/events?access_token=${accessTokenData.access_token}`;
108
109
  beforeEach(() => {
109
110
  (0, nock_1.default)(MOCK_BACKEND.rest)
110
111
  .post(auth_1.AuthAPI.URL.LOGIN, body => body.email && body.password)
@@ -134,6 +135,14 @@ describe('Account', () => {
134
135
  .get(`${notification_1.NotificationAPI.URL.NOTIFICATION}/${notification_1.NotificationAPI.URL.LAST}`)
135
136
  .query({ client: CLIENT_ID })
136
137
  .reply(http_status_codes_1.StatusCodes.OK, {});
138
+ (0, nock_1.default)(MOCK_BACKEND.rest)
139
+ .get(`/api-version`)
140
+ .reply(http_status_codes_1.StatusCodes.OK, {
141
+ supported: [BACKEND_VERSION],
142
+ federation: false,
143
+ development: [BACKEND_VERSION + 1],
144
+ domain: 'zinfra.io',
145
+ });
137
146
  (0, nock_1.default)(MOCK_BACKEND.rest)
138
147
  .get(notification_1.NotificationAPI.URL.NOTIFICATION)
139
148
  .query({ client: CLIENT_ID, size: 10000 })
@@ -142,6 +151,11 @@ describe('Account', () => {
142
151
  (0, nock_1.default)(MOCK_BACKEND.rest)
143
152
  .get(client_1.ClientAPI.URL.CLIENTS)
144
153
  .reply(http_status_codes_1.StatusCodes.OK, [{ id: CLIENT_ID }]);
154
+ (0, nock_1.default)(MOCK_BACKEND.rest)
155
+ .put(/\/clients\/[\w-]+$/, {
156
+ capabilities: ['legalhold-implicit-consent', 'consumable-notifications'],
157
+ })
158
+ .reply(http_status_codes_1.StatusCodes.OK);
145
159
  (0, nock_1.default)(MOCK_BACKEND.rest)
146
160
  .get(self_1.SelfAPI.URL.SELF)
147
161
  .reply(http_status_codes_1.StatusCodes.OK, {
@@ -163,6 +177,7 @@ describe('Account', () => {
163
177
  (0, nock_1.cleanAll)();
164
178
  });
165
179
  const currentClient = {
180
+ capabilities: [],
166
181
  id: CLIENT_ID,
167
182
  cookie: '',
168
183
  time: '',
@@ -218,35 +233,9 @@ describe('Account', () => {
218
233
  }
219
234
  });
220
235
  });
221
- it('emits text messages', () => {
222
- return new Promise(async (resolve) => {
223
- const { account, apiClient } = await createAccount();
224
- await account.login({
225
- clientType: client_1.ClientType.TEMPORARY,
226
- email: 'hello@example.com',
227
- password: 'my-secret',
228
- });
229
- account['currentClient'] = currentClient;
230
- jest.spyOn(apiClient, 'connect').mockImplementation();
231
- jest.spyOn(account.service.notification, 'handleEvent').mockReturnValue({
232
- status: 'handled',
233
- payload: {
234
- event: { type: event_1.CONVERSATION_EVENT.OTR_MESSAGE_ADD },
235
- },
236
- });
237
- const kill = account.listen({
238
- onEvent: ({ event }) => {
239
- expect(event.type).toBe(event_1.CONVERSATION_EVENT.OTR_MESSAGE_ADD);
240
- resolve();
241
- },
242
- });
243
- apiClient.transport.ws.emit(tcp_1.WebSocketClient.TOPIC.ON_MESSAGE, { payload: [{}] });
244
- kill();
245
- });
246
- });
247
236
  describe('Websocket connection', () => {
248
- let server;
249
237
  let dependencies;
238
+ let server;
250
239
  const mockNotifications = (size) => {
251
240
  const notifications = Array.from(new Array(size)).map(() => ({
252
241
  id: (0, uuid_1.v4)(),
@@ -267,12 +256,12 @@ describe('Account', () => {
267
256
  return callback();
268
257
  };
269
258
  };
270
- beforeEach(() => {
271
- server = new jest_websocket_mock_1.WS(`${MOCK_BACKEND.ws}/await?access_token=${accessTokenData.access_token}`);
259
+ beforeAll(() => {
272
260
  // Forces the reconnecting websocket not to automatically reconnect (to avoid infinitely hanging tests)
273
261
  ReconnectingWebsocket_1.ReconnectingWebsocket['RECONNECTING_OPTIONS'].maxRetries = 0;
274
262
  });
275
263
  beforeEach(async () => {
264
+ server = new jest_websocket_mock_1.WS(websocketServerAddress); // isolate per test
276
265
  dependencies = await createAccount();
277
266
  const { account } = dependencies;
278
267
  await account.login({
@@ -287,46 +276,40 @@ describe('Account', () => {
287
276
  jest
288
277
  .spyOn(dependencies.account.service.notification['database'], 'getLastNotificationId')
289
278
  .mockResolvedValue('0');
279
+ await account.useAPIVersion(BACKEND_VERSION, BACKEND_VERSION);
290
280
  });
291
281
  afterEach(() => {
292
- server.close();
282
+ server.close(); // ensure server shutdown
283
+ jest_websocket_mock_1.WS.clean();
293
284
  });
294
285
  describe('listen', () => {
295
- it('warns consumer of the connection state', async () => {
296
- return new Promise(async (resolve) => {
297
- const expectedConnectionStates = [
298
- Account_1.ConnectionState.CONNECTING,
299
- Account_1.ConnectionState.PROCESSING_NOTIFICATIONS,
300
- Account_1.ConnectionState.LIVE,
301
- Account_1.ConnectionState.CLOSED,
302
- ];
303
- const disconnect = dependencies.account.listen({
304
- onConnectionStateChanged: state => {
305
- expect(state).toBe(expectedConnectionStates.splice(0, 1)[0]);
306
- switch (state) {
307
- case Account_1.ConnectionState.LIVE:
308
- // We socket is live we disconnect before ending the test
309
- disconnect();
310
- break;
311
- case Account_1.ConnectionState.CLOSED:
312
- resolve();
313
- }
314
- },
315
- });
316
- });
317
- });
318
- it('processes notification stream upon connection', async () => {
286
+ it('connects to websocket after the notification stream has been processed', async () => {
287
+ jest
288
+ .spyOn(dependencies.account, 'getClientCapabilities')
289
+ .mockReturnValue([client_1.ClientCapability.LEGAL_HOLD_IMPLICIT_CONSENT]);
319
290
  return new Promise(async (resolve) => {
320
291
  const nbNotifications = 10;
321
292
  const onNotificationStreamProgress = jest.fn();
322
- const onEvent = jest.fn();
293
+ const onEvent = jest.fn().mockImplementation(() => { });
323
294
  mockNotifications(nbNotifications);
324
- const disconnect = dependencies.account.listen({
325
- onConnectionStateChanged: callWhen(Account_1.ConnectionState.LIVE, () => {
295
+ await dependencies.account.listen({
296
+ onConnectionStateChanged: callWhen(Account_1.ConnectionState.LIVE, async () => {
326
297
  expect(onNotificationStreamProgress).toHaveBeenCalledTimes(nbNotifications);
327
298
  expect(onEvent).toHaveBeenCalledTimes(nbNotifications);
328
299
  expect(onEvent).toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.NOTIFICATION_STREAM);
329
- disconnect();
300
+ expect(onEvent).not.toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.WEBSOCKET);
301
+ onEvent.mockReset();
302
+ await server.connected;
303
+ jest
304
+ .spyOn(dependencies.account.service.notification, 'handleNotification')
305
+ .mockReturnValue([{ event: { testData: 1 } }]);
306
+ server.send(JSON.stringify({
307
+ type: ConsumableNotification_1.ConsumableEvent.EVENT,
308
+ data: { delivery_tag: 1000, event: { id: (0, uuid_1.v4)(), payload: [] } },
309
+ }));
310
+ await waitFor(() => expect(onEvent).toHaveBeenCalledTimes(1));
311
+ expect(onEvent).not.toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.NOTIFICATION_STREAM);
312
+ expect(onEvent).toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.WEBSOCKET);
330
313
  resolve();
331
314
  }),
332
315
  onEvent: onEvent,
@@ -334,24 +317,39 @@ describe('Account', () => {
334
317
  });
335
318
  });
336
319
  });
337
- it('fowards events from websocket to consumer after the notification stream has been processed', async () => {
320
+ it('warns consumer of the connection state', async () => {
321
+ await new Promise(async (resolve) => {
322
+ mockNotifications(10);
323
+ const onConnectionStateChanged = jest.fn().mockImplementation((state) => {
324
+ switch (state) {
325
+ case Account_1.ConnectionState.LIVE:
326
+ break;
327
+ case Account_1.ConnectionState.CLOSED:
328
+ // Expect all states to have been called in order
329
+ expect(onConnectionStateChanged).toHaveBeenNthCalledWith(1, Account_1.ConnectionState.PROCESSING_NOTIFICATIONS);
330
+ expect(onConnectionStateChanged).toHaveBeenNthCalledWith(2, Account_1.ConnectionState.LIVE);
331
+ resolve();
332
+ break;
333
+ }
334
+ });
335
+ const disconnect = await dependencies.account.listen({
336
+ onConnectionStateChanged,
337
+ });
338
+ await waitFor(() => expect(onConnectionStateChanged).toHaveBeenCalledWith(Account_1.ConnectionState.PROCESSING_NOTIFICATIONS));
339
+ disconnect();
340
+ });
341
+ });
342
+ it('processes notification stream upon connection', async () => {
338
343
  return new Promise(async (resolve) => {
339
344
  const nbNotifications = 10;
340
345
  const onNotificationStreamProgress = jest.fn();
341
346
  const onEvent = jest.fn();
342
347
  mockNotifications(nbNotifications);
343
- const disconnect = dependencies.account.listen({
344
- onConnectionStateChanged: callWhen(Account_1.ConnectionState.LIVE, async () => {
348
+ await dependencies.account.listen({
349
+ onConnectionStateChanged: callWhen(Account_1.ConnectionState.LIVE, () => {
345
350
  expect(onNotificationStreamProgress).toHaveBeenCalledTimes(nbNotifications);
346
351
  expect(onEvent).toHaveBeenCalledTimes(nbNotifications);
347
352
  expect(onEvent).toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.NOTIFICATION_STREAM);
348
- expect(onEvent).not.toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.WEBSOCKET);
349
- onEvent.mockReset();
350
- server.send(JSON.stringify({ id: (0, uuid_1.v4)(), payload: [{}] }));
351
- await waitFor(() => expect(onEvent).toHaveBeenCalledTimes(1));
352
- expect(onEvent).not.toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.NOTIFICATION_STREAM);
353
- expect(onEvent).toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.WEBSOCKET);
354
- disconnect();
355
353
  resolve();
356
354
  }),
357
355
  onEvent: onEvent,
@@ -359,61 +357,27 @@ describe('Account', () => {
359
357
  });
360
358
  });
361
359
  });
362
- it('locks the websocket and waits for notification stream to be processed before sending websocket events', async () => {
363
- const nbNotifications = 10;
364
- const onNotificationStreamProgress = jest.fn();
365
- const onEvent = jest.fn();
366
- mockNotifications(nbNotifications);
367
- return new Promise(async (resolve) => {
368
- const disconnect = dependencies.account.listen({
369
- onConnectionStateChanged: async (state) => {
370
- switch (state) {
371
- case Account_1.ConnectionState.PROCESSING_NOTIFICATIONS:
372
- // sending a message as soon as the notificaiton stream starts to process
373
- // This message should only be forwarded once the notification stream is fully processed
374
- server.send(JSON.stringify({ id: (0, uuid_1.v4)(), payload: [{}] }));
375
- break;
376
- case Account_1.ConnectionState.LIVE:
377
- expect(onNotificationStreamProgress).toHaveBeenCalledTimes(nbNotifications);
378
- expect(onEvent).toHaveBeenCalledTimes(nbNotifications);
379
- expect(onEvent).toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.NOTIFICATION_STREAM);
380
- expect(onEvent).not.toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.WEBSOCKET);
381
- onEvent.mockReset();
382
- await waitFor(() => expect(onEvent).toHaveBeenCalledTimes(1));
383
- expect(onEvent).not.toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.NOTIFICATION_STREAM);
384
- expect(onEvent).toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.WEBSOCKET);
385
- disconnect();
386
- resolve();
387
- }
388
- },
389
- onEvent: onEvent,
390
- onNotificationStreamProgress: onNotificationStreamProgress,
391
- });
392
- });
393
- });
394
- it('does not unlock the websocket if the connection was aborted', async () => {
360
+ it('does not stop proccessing messages if websocket connection is aborted', async () => {
361
+ jest
362
+ .spyOn(dependencies.account, 'getClientCapabilities')
363
+ .mockReturnValue([client_1.ClientCapability.LEGAL_HOLD_IMPLICIT_CONSENT]);
395
364
  const nbNotifications = 10;
396
365
  const onNotificationStreamProgress = jest
397
366
  .fn()
398
367
  .mockImplementationOnce(() => { })
399
- .mockImplementationOnce(() => server.close());
368
+ .mockImplementationOnce(() => {
369
+ // abort websocket connection after the second notification is processeed
370
+ server.close();
371
+ });
400
372
  const onEvent = jest.fn();
401
373
  mockNotifications(nbNotifications);
402
- return new Promise(async (resolve, reject) => {
403
- dependencies.account.listen({
374
+ return new Promise(async (resolve) => {
375
+ return dependencies.account.listen({
404
376
  onConnectionStateChanged: async (state) => {
405
377
  switch (state) {
406
- case Account_1.ConnectionState.PROCESSING_NOTIFICATIONS:
407
- // sending a message as soon as the notificaiton stream starts to process
408
- // This message should only be forwarded once the notification stream is fully processed
409
- server.send(JSON.stringify({ id: (0, uuid_1.v4)(), payload: [{}] }));
410
- break;
411
378
  case Account_1.ConnectionState.LIVE:
412
- reject(new Error());
413
- throw new Error('should not go to `live` state');
414
- case Account_1.ConnectionState.CLOSED:
415
- expect(onNotificationStreamProgress).toHaveBeenCalledTimes(2);
416
- expect(onEvent).toHaveBeenCalledTimes(2);
379
+ expect(onNotificationStreamProgress).toHaveBeenCalledTimes(10);
380
+ expect(onEvent).toHaveBeenCalledTimes(10);
417
381
  expect(onEvent).toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.NOTIFICATION_STREAM);
418
382
  expect(dependencies.account.service.notification.handleNotification).not.toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.WEBSOCKET);
419
383
  resolve();
@@ -424,35 +388,6 @@ describe('Account', () => {
424
388
  });
425
389
  });
426
390
  });
427
- it('cancels notification stream process if socket is disconnected', () => {
428
- const nbNotifications = 10;
429
- const onNotificationStreamProgress = jest.fn();
430
- const onEvent = jest
431
- .fn()
432
- .mockImplementationOnce(() => { })
433
- .mockImplementationOnce(() => {
434
- // on second message, we kill the websocket
435
- server.close();
436
- });
437
- mockNotifications(nbNotifications);
438
- return new Promise(resolve => {
439
- dependencies.account.listen({
440
- onConnectionStateChanged: callWhen(Account_1.ConnectionState.CLOSED, () => {
441
- try {
442
- expect(onNotificationStreamProgress).toHaveBeenCalledTimes(1);
443
- expect(onEvent).toHaveBeenCalledTimes(2);
444
- expect(onEvent).toHaveBeenCalledWith(expect.any(Object), notification_2.NotificationSource.NOTIFICATION_STREAM);
445
- }
446
- catch (error) {
447
- throw error;
448
- }
449
- resolve();
450
- }, 1),
451
- onEvent: onEvent,
452
- onNotificationStreamProgress: onNotificationStreamProgress,
453
- });
454
- });
455
- });
456
391
  });
457
392
  });
458
393
  });
@@ -1,5 +1,5 @@
1
1
  import { LoginData } from '@wireapp/api-client/lib/auth/';
2
- import { RegisteredClient } from '@wireapp/api-client/lib/client/';
2
+ import { ClientCapabilityData, RegisteredClient } from '@wireapp/api-client/lib/client/';
3
3
  import { APIClient } from '@wireapp/api-client';
4
4
  import { CRUDEngine } from '@wireapp/store-engine';
5
5
  import type { ProteusService } from '../messagingProtocols/proteus';
@@ -45,8 +45,9 @@ export declare class ClientService {
45
45
  *
46
46
  * @return the loaded client or undefined
47
47
  */
48
- loadClient(): Promise<RegisteredClient | undefined>;
48
+ loadClient(): Promise<MetaClient | undefined>;
49
49
  private createLocalClient;
50
+ putClientCapabilities(clientId: string, capabilities: ClientCapabilityData): Promise<void>;
50
51
  /**
51
52
  * Will download all the clients of the self user (excluding the current client) and will store them in the database
52
53
  * @param currentClient - the id of the current client (to be excluded from the list)
@@ -1 +1 @@
1
- {"version":3,"file":"ClientService.d.ts","sourceRoot":"","sources":["../../src/client/ClientService.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,SAAS,EAAC,MAAM,+BAA+B,CAAC;AACxD,OAAO,EAAoD,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AAKpH,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAE9C,OAAO,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAEjD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAC,cAAc,EAAC,MAAM,2DAA2D,CAAC;AAEzF,OAAO,EAAC,UAAU,EAAoD,MAAM,IAAI,CAAC;AAEjF,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE;QACJ,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,qBAAa,aAAa;IAMtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAP9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgD;gBAGpD,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,UAAU;IAMnC,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAIhD;;;;;;;OAOG;IACU,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMhF;;;OAGG;IACU,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAcpD,cAAc;IAQ5B;;;;;;;OAOG;IACU,UAAU,IAAI,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAyBhE,OAAO,CAAC,iBAAiB;IAIzB;;;OAGG;IACU,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAUhE,QAAQ,CACnB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,UAAU,EACtB,EAAC,OAAO,EAAE,UAAU,EAAC,EAAE,cAAc,GACpC,OAAO,CAAC,gBAAgB,CAAC;CA6B7B"}
1
+ {"version":3,"file":"ClientService.d.ts","sourceRoot":"","sources":["../../src/client/ClientService.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,SAAS,EAAC,MAAM,+BAA+B,CAAC;AACxD,OAAO,EAEL,oBAAoB,EAGpB,gBAAgB,EACjB,MAAM,iCAAiC,CAAC;AAKzC,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAE9C,OAAO,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAEjD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAC,cAAc,EAAC,MAAM,2DAA2D,CAAC;AAEzF,OAAO,EAAC,UAAU,EAAoD,MAAM,IAAI,CAAC;AAEjF,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE;QACJ,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,qBAAa,aAAa;IAMtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAP9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgD;gBAGpD,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,UAAU;IAMnC,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAIhD;;;;;;;OAOG;IACU,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMhF;;;OAGG;IACU,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAcpD,cAAc;IAQ5B;;;;;;;OAOG;IACU,UAAU,IAAI,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAyB1D,OAAO,CAAC,iBAAiB;IAIlB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjG;;;OAGG;IACU,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAUhE,QAAQ,CACnB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,UAAU,EACtB,EAAC,OAAO,EAAE,UAAU,EAAC,EAAE,cAAc,GACpC,OAAO,CAAC,gBAAgB,CAAC;CA6B7B"}
@@ -118,6 +118,9 @@ class ClientService {
118
118
  createLocalClient(client, domain) {
119
119
  return this.database.createLocalClient(client, domain);
120
120
  }
121
+ putClientCapabilities(clientId, capabilities) {
122
+ return this.backend.putClient(clientId, capabilities);
123
+ }
121
124
  /**
122
125
  * Will download all the clients of the self user (excluding the current client) and will store them in the database
123
126
  * @param currentClient - the id of the current client (to be excluded from the list)
@@ -137,7 +140,7 @@ class ClientService {
137
140
  }
138
141
  const newClient = {
139
142
  class: clientInfo.classification,
140
- capabilities: [client_1.ClientCapability.LEGAL_HOLD_IMPLICIT_CONSENT],
143
+ capabilities: [client_1.ClientCapability.LEGAL_HOLD_IMPLICIT_CONSENT, client_1.ClientCapability.CONSUMABLE_NOTIFICATIONS],
141
144
  cookie: clientInfo.cookieLabel,
142
145
  label: clientInfo.label,
143
146
  lastkey: lastPrekey,
@@ -1 +1 @@
1
- {"version":3,"file":"welcomeMessage.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,2BAA2B,EAAC,MAAM,+BAA+B,CAAC;AAG1E,OAAO,EAAC,mBAAmB,EAAC,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAC,UAAU,EAAmB,MAAM,qBAAqB,CAAC;AAEjE,UAAU,0BAA0B;IAClC,KAAK,EAAE,2BAA2B,CAAC;IACnC,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,eAAO,MAAM,uBAAuB,2BAGjC,0BAA0B,KAAG,OAAO,CAAC,mBAAmB,CAiB1D,CAAC"}
1
+ {"version":3,"file":"welcomeMessage.d.ts","sourceRoot":"","sources":["../../../../../../src/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,2BAA2B,EAAC,MAAM,+BAA+B,CAAC;AAG1E,OAAO,EAAC,mBAAmB,EAAC,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAC,UAAU,EAAmB,MAAM,qBAAqB,CAAC;AAEjE,UAAU,0BAA0B;IAClC,KAAK,EAAE,2BAA2B,CAAC;IACnC,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,eAAO,MAAM,uBAAuB,2BAGjC,0BAA0B,KAAG,OAAO,CAAC,mBAAmB,CAmB1D,CAAC"}
@@ -29,8 +29,10 @@ const handleMLSWelcomeMessage = async ({ mlsService, event, }) => {
29
29
  // The groupId can then be sent back to the consumer
30
30
  // After we were added to the group we need to schedule a periodic key material renewal
31
31
  await mlsService.scheduleKeyMaterialRenewal(groupIdStr);
32
+ // We also need to emit a NEW_EPOCH event to notify the rest of the system that we have joined a new group
32
33
  const newEpoch = await mlsService.getEpoch(groupIdStr);
33
34
  mlsService.emit(MLSService_1.MLSServiceEvents.NEW_EPOCH, { groupId: groupIdStr, epoch: newEpoch });
35
+ mlsService.logger.info(`Joined MLS group with id ${groupIdStr} via welcome message, new epoch: ${newEpoch}`);
34
36
  return {
35
37
  event: { ...event, data: groupIdStr },
36
38
  };
@@ -44,6 +44,11 @@ const mockParams = {
44
44
  scheduleKeyMaterialRenewal: jest.fn(),
45
45
  getEpoch: jest.fn(),
46
46
  emit: jest.fn(),
47
+ logger: {
48
+ info: jest.fn(),
49
+ warn: jest.fn(),
50
+ error: jest.fn(),
51
+ },
47
52
  },
48
53
  dryRun: false,
49
54
  };
@@ -1 +1 @@
1
- {"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MLSService.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/mls/MLSService/MLSService.ts"],"names":[],"mappings":"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"}
@@ -274,7 +274,12 @@ class MLSService extends commons_1.TypedEventEmitter {
274
274
  if (welcomeBundle.id) {
275
275
  //after we've successfully joined via external commit, we schedule periodic key material renewal
276
276
  const groupIdStr = bazinga64_1.Encoder.toBase64(welcomeBundle.id).asString;
277
+ const newEpoch = await this.getEpoch(groupIdStr);
278
+ // Schedule the next key material renewal
277
279
  await this.scheduleKeyMaterialRenewal(groupIdStr);
280
+ // Notify subscribers about the new epoch
281
+ this.emit(MLSServiceEvents.NEW_EPOCH, { groupId: groupIdStr, epoch: newEpoch });
282
+ this.logger.info(`Joined MLS group with id ${groupIdStr} via external commit, new epoch: ${newEpoch}`);
278
283
  }
279
284
  }
280
285
  async exportSecretKey(groupId, keyLength) {
@@ -3,7 +3,7 @@ import { APIClient } from '@wireapp/api-client';
3
3
  export declare class NotificationBackendRepository {
4
4
  private readonly apiClient;
5
5
  constructor(apiClient: APIClient);
6
- getAllNotifications(clientId?: string, lastNotificationId?: string, abortController?: AbortController): Promise<{
6
+ getAllNotifications(clientId?: string, lastNotificationId?: string): Promise<{
7
7
  notifications: Notification[];
8
8
  missedNotification?: string;
9
9
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationBackendRepository.d.ts","sourceRoot":"","sources":["../../src/notification/NotificationBackendRepository.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,YAAY,EAAC,MAAM,uCAAuC,CAAC;AAEnE,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAE9C,qBAAa,6BAA6B;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,SAAS;IAEpC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,kBAAkB,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,eAAe;;;;IAI3G,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAGrE"}
1
+ {"version":3,"file":"NotificationBackendRepository.d.ts","sourceRoot":"","sources":["../../src/notification/NotificationBackendRepository.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,YAAY,EAAC,MAAM,uCAAuC,CAAC;AAEnE,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAE9C,qBAAa,6BAA6B;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,SAAS;IAEpC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,kBAAkB,CAAC,EAAE,MAAM;;;;IAIxE,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAGrE"}
@@ -24,8 +24,8 @@ class NotificationBackendRepository {
24
24
  constructor(apiClient) {
25
25
  this.apiClient = apiClient;
26
26
  }
27
- async getAllNotifications(clientId, lastNotificationId, abortController) {
28
- return this.apiClient.api.notification.getAllNotifications(clientId, lastNotificationId, abortController);
27
+ async getAllNotifications(clientId, lastNotificationId) {
28
+ return this.apiClient.api.notification.getAllNotifications(clientId, lastNotificationId);
29
29
  }
30
30
  getLastNotification(clientId) {
31
31
  return this.apiClient.api.notification.getLastNotification(clientId);
@@ -55,7 +55,7 @@ export declare class NotificationService extends TypedEventEmitter<Events> {
55
55
  getNotificationEventList(): Promise<BackendEvent[]>;
56
56
  setLastEventDate(eventDate: Date): Promise<Date>;
57
57
  private setLastNotificationId;
58
- processNotificationStream(notificationHandler: NotificationHandler, onMissedNotifications: (notificationId: string) => void, abortHandler: AbortController): Promise<{
58
+ processNotificationStream(notificationHandler: NotificationHandler, onMissedNotifications: (notificationId: string) => void): Promise<{
59
59
  total: number;
60
60
  error: number;
61
61
  success: number;
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationService.d.ts","sourceRoot":"","sources":["../../src/notification/NotificationService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NotificationService.d.ts","sourceRoot":"","sources":["../../src/notification/NotificationService.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,YAAY,EAAC,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAC,YAAY,EAAC,MAAM,uCAAuC,CAAC;AAEnE,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAa,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAC,UAAU,EAA4B,MAAM,uBAAuB,CAAC;AAI5E,OAAO,EAAC,kBAAkB,EAAC,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAC,mBAAmB,EAAC,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAY,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAC,eAAe,EAAC,MAAM,2BAA2B,CAAC;AAE1D,MAAM,MAAM,mBAAmB,GAAG;IAChC,0CAA0C;IAC1C,KAAK,EAAE,YAAY,CAAC;IACpB,kEAAkE;IAClE,aAAa,CAAC,EAAE,cAAc,CAAC;IAC/B,8FAA8F;IAC9F,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAC,MAAM,EAAE,WAAW,CAAA;CAAC,GACrB;IAAC,MAAM,EAAE,SAAS,CAAA;CAAC,GACnB;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAAC,CAAC;AAE7D,aAAK,KAAK;IACR,kBAAkB,iDAAiD;CACpE;AAED,MAAM,MAAM,mBAAmB,GAAG,CAChC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,KACpC,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,KAAK,MAAM,GAAG;IACZ,CAAC,KAAK,CAAC,kBAAkB,CAAC,EAAE,iBAAiB,CAAC;CAC/C,CAAC;AAEF,qBAAa,mBAAoB,SAAQ,iBAAiB,CAAC,MAAM,CAAC;IAU9D,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IATtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6D;IACpF,gBAAuB,KAAK,eAAS;gBAGnC,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,UAAU,EACN,mBAAmB,EAAE,mBAAmB;YAQ7C,mBAAmB;IAKjC,0DAA0D;IAC7C,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM/D,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAKpC,wBAAwB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAI7C,gBAAgB,CAAC,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAsB/C,qBAAqB;IAItB,yBAAyB,CACpC,mBAAmB,EAAE,mBAAmB,EACxC,qBAAqB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,GACtD,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;IA6B3D;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAYT,kBAAkB,CAC9B,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,GAAE,OAAe,GACtB,cAAc,CAAC,mBAAmB,CAAC;IAmCtC;;;;;OAKG;YACW,WAAW;CAc1B"}
@@ -43,9 +43,9 @@ class NotificationService extends commons_1.TypedEventEmitter {
43
43
  this.backend = new NotificationBackendRepository_1.NotificationBackendRepository(this.apiClient);
44
44
  this.database = new NotificationDatabaseRepository_1.NotificationDatabaseRepository(storeEngine);
45
45
  }
46
- async getAllNotifications(since, abortController) {
46
+ async getAllNotifications(since) {
47
47
  const clientId = this.apiClient.clientId;
48
- return this.backend.getAllNotifications(clientId, since, abortController);
48
+ return this.backend.getAllNotifications(clientId, since);
49
49
  }
50
50
  /** Should only be called with a completely new client. */
51
51
  async initializeNotificationStream(clientId) {
@@ -80,9 +80,9 @@ class NotificationService extends commons_1.TypedEventEmitter {
80
80
  async setLastNotificationId(lastNotification) {
81
81
  return this.database.updateLastNotificationId(lastNotification);
82
82
  }
83
- async processNotificationStream(notificationHandler, onMissedNotifications, abortHandler) {
83
+ async processNotificationStream(notificationHandler, onMissedNotifications) {
84
84
  const lastNotificationId = await this.database.getLastNotificationId();
85
- const { notifications, missedNotification } = await this.getAllNotifications(lastNotificationId, abortHandler);
85
+ const { notifications, missedNotification } = await this.getAllNotifications(lastNotificationId);
86
86
  if (missedNotification) {
87
87
  onMissedNotifications(missedNotification);
88
88
  }
@@ -92,13 +92,6 @@ class NotificationService extends commons_1.TypedEventEmitter {
92
92
  : `No notification to process from the stream`;
93
93
  this.logger.log(logMessage);
94
94
  for (const [index, notification] of notifications.entries()) {
95
- if (abortHandler.signal.aborted) {
96
- /* Stop handling notifications if the websocket has been disconnected.
97
- * Upon reconnecting we are going to restart handling the notification stream for where we left of
98
- */
99
- this.logger.warn(`Stop processing notifications as connection to websocket was closed`);
100
- return results;
101
- }
102
95
  try {
103
96
  await notificationHandler(notification, Notifications_types_1.NotificationSource.NOTIFICATION_STREAM, {
104
97
  done: index + 1,
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "./lib/cryptography/AssetCryptography/crypto.node": "./lib/cryptography/AssetCryptography/crypto.browser.js"
12
12
  },
13
13
  "dependencies": {
14
- "@wireapp/api-client": "^27.66.0",
14
+ "@wireapp/api-client": "^27.67.0",
15
15
  "@wireapp/commons": "^5.4.2",
16
16
  "@wireapp/core-crypto": "7.0.1",
17
17
  "@wireapp/cryptobox": "12.8.0",
@@ -61,6 +61,6 @@
61
61
  "test:coverage": "jest --coverage",
62
62
  "watch": "tsc --watch"
63
63
  },
64
- "version": "46.29.3",
65
- "gitHead": "e587e16017137049033de64a688d597320bf9021"
64
+ "version": "46.30.0",
65
+ "gitHead": "09304f9cc2241bdd6200926e263adbfe97ca5d68"
66
66
  }