@wireapp/core 17.20.1 → 17.21.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.
Files changed (25) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/package.json +3 -3
  3. package/src/main/conversation/ConversationService.d.ts +43 -23
  4. package/src/main/conversation/ConversationService.js +106 -112
  5. package/src/main/conversation/ConversationService.js.map +1 -1
  6. package/src/main/conversation/ConversationService.ts +130 -388
  7. package/src/main/conversation/message/MessageService.d.ts +11 -2
  8. package/src/main/conversation/message/MessageService.js +46 -19
  9. package/src/main/conversation/message/MessageService.js.map +1 -1
  10. package/src/main/conversation/message/MessageService.test.node.d.ts +1 -0
  11. package/src/main/conversation/message/MessageService.test.node.js +80 -0
  12. package/src/main/conversation/message/MessageService.test.node.js.map +1 -0
  13. package/src/main/conversation/message/MessageService.test.node.ts +95 -0
  14. package/src/main/conversation/message/MessageService.ts +48 -28
  15. package/src/main/cryptography/CryptographyService.d.ts +3 -3
  16. package/src/main/cryptography/CryptographyService.js +14 -11
  17. package/src/main/cryptography/CryptographyService.js.map +1 -1
  18. package/src/main/cryptography/CryptographyService.ts +23 -16
  19. package/src/main/util/TypePredicateUtil.js +1 -1
  20. package/src/main/util/TypePredicateUtil.js.map +1 -1
  21. package/src/main/util/TypePredicateUtil.test.node.d.ts +1 -0
  22. package/src/main/util/TypePredicateUtil.test.node.js +42 -0
  23. package/src/main/util/TypePredicateUtil.test.node.js.map +1 -0
  24. package/src/main/util/TypePredicateUtil.test.node.ts +44 -0
  25. package/src/main/util/TypePredicateUtil.ts +1 -1
@@ -20,7 +20,13 @@
20
20
  import type {APIClient} from '@wireapp/api-client';
21
21
  import type {PreKey as SerializedPreKey} from '@wireapp/api-client/src/auth/';
22
22
  import type {RegisteredClient} from '@wireapp/api-client/src/client/';
23
- import type {OTRClientMap, OTRRecipients, QualifiedOTRRecipients} from '@wireapp/api-client/src/conversation/';
23
+ import type {
24
+ OTRClientMap,
25
+ OTRRecipients,
26
+ QualifiedOTRRecipients,
27
+ QualifiedUserClients,
28
+ UserClients,
29
+ } from '@wireapp/api-client/src/conversation/';
24
30
  import type {ConversationOtrMessageAddEvent} from '@wireapp/api-client/src/event';
25
31
  import type {QualifiedUserPreKeyBundleMap, UserPreKeyBundleMap} from '@wireapp/api-client/src/user/';
26
32
  import {Cryptobox} from '@wireapp/cryptobox';
@@ -32,6 +38,7 @@ import logdown from 'logdown';
32
38
 
33
39
  import {GenericMessageType, PayloadBundle, PayloadBundleSource} from '../conversation';
34
40
  import type {SessionPayloadBundle} from '../cryptography/';
41
+ import {isUserClients} from '../util';
35
42
  import {CryptographyDatabaseRepository} from './CryptographyDatabaseRepository';
36
43
  import {GenericMessageMapper} from './GenericMessageMapper';
37
44
 
@@ -118,7 +125,7 @@ export class CryptographyService {
118
125
 
119
126
  public async encryptQualified(
120
127
  plainText: Uint8Array,
121
- preKeyBundles: QualifiedUserPreKeyBundleMap,
128
+ preKeyBundles: QualifiedUserPreKeyBundleMap | QualifiedUserClients,
122
129
  ): Promise<QualifiedOTRRecipients> {
123
130
  const qualifiedOTRRecipients: QualifiedOTRRecipients = {};
124
131
 
@@ -131,17 +138,15 @@ export class CryptographyService {
131
138
 
132
139
  public async encrypt(
133
140
  plainText: Uint8Array,
134
- preKeyBundles: UserPreKeyBundleMap,
141
+ users: UserPreKeyBundleMap | UserClients,
135
142
  domain?: string,
136
143
  ): Promise<OTRRecipients<Uint8Array>> {
137
- const recipients: OTRRecipients<Uint8Array> = {};
138
144
  const bundles: Promise<SessionPayloadBundle>[] = [];
139
145
 
140
- for (const userId in preKeyBundles) {
141
- recipients[userId] = {};
142
-
143
- for (const clientId in preKeyBundles[userId]) {
144
- const {key: base64PreKey} = preKeyBundles[userId][clientId];
146
+ for (const userId in users) {
147
+ const clientIds = isUserClients(users) ? users[userId] : Object.keys(users[userId]);
148
+ for (const clientId of clientIds) {
149
+ const base64PreKey = isUserClients(users) ? undefined : users[userId][clientId].key;
145
150
  const sessionId = CryptographyService.constructSessionId(userId, clientId, domain || null);
146
151
  bundles.push(this.encryptPayloadForSession(sessionId, plainText, base64PreKey));
147
152
  }
@@ -149,27 +154,29 @@ export class CryptographyService {
149
154
 
150
155
  const payloads = await Promise.all(bundles);
151
156
 
152
- payloads.forEach(payload => {
157
+ return payloads.reduce((recipients, payload) => {
153
158
  const {encryptedPayload, sessionId} = payload;
154
159
  const {userId, clientId} = CryptographyService.dismantleSessionId(sessionId);
160
+ recipients[userId] ||= {};
155
161
  recipients[userId][clientId] = encryptedPayload;
156
- });
157
-
158
- return recipients;
162
+ return recipients;
163
+ }, {} as OTRRecipients<Uint8Array>);
159
164
  }
160
165
 
161
166
  private async encryptPayloadForSession(
162
167
  sessionId: string,
163
168
  plainText: Uint8Array,
164
- base64EncodedPreKey: string,
169
+ base64EncodedPreKey?: string,
165
170
  ): Promise<SessionPayloadBundle> {
166
171
  this.logger.log(`Encrypting payload for session ID "${sessionId}"`);
167
172
 
168
173
  let encryptedPayload: Uint8Array;
169
174
 
170
175
  try {
171
- const decodedPreKeyBundle = Decoder.fromBase64(base64EncodedPreKey).asBytes;
172
- const payloadAsArrayBuffer = await this.cryptobox.encrypt(sessionId, plainText, decodedPreKeyBundle.buffer);
176
+ const decodedPreKeyBundle = base64EncodedPreKey
177
+ ? Decoder.fromBase64(base64EncodedPreKey).asBytes.buffer
178
+ : undefined;
179
+ const payloadAsArrayBuffer = await this.cryptobox.encrypt(sessionId, plainText, decodedPreKeyBundle);
173
180
  encryptedPayload = new Uint8Array(payloadAsArrayBuffer);
174
181
  } catch (error) {
175
182
  this.logger.error(`Could not encrypt payload: ${(error as Error).message}`);
@@ -35,7 +35,7 @@ function isQualifiedUserClients(obj) {
35
35
  const firstClientIdArray = Object.values(firstUserClientObject)[0];
36
36
  if (Array.isArray(firstClientIdArray)) {
37
37
  const firstClientId = firstClientIdArray[0];
38
- return typeof firstClientId === 'string';
38
+ return typeof firstClientId === 'string' || typeof firstClientId === 'undefined';
39
39
  }
40
40
  }
41
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TypePredicateUtil.js","sourceRoot":"","sources":["TypePredicateUtil.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAKH,SAAgB,aAAa,CAAC,GAAQ;IACpC,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;AAC1D,CAAC;AAFD,sCAEC;AAED,SAAgB,kBAAkB,CAAC,GAAQ;IACzC,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC;AAClG,CAAC;AAFD,gDAEC;AAED,SAAgB,sBAAsB,CAAC,GAAQ;;IAC7C,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC3B,MAAM,qBAAqB,GAAG,MAAA,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,0CAAG,CAAC,CAAC,CAAC;QACtD,IAAI,OAAO,qBAAqB,KAAK,QAAQ,EAAE;YAC7C,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,qBAA+B,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7E,IAAI,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE;gBACrC,MAAM,aAAa,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;gBAC5C,OAAO,OAAO,aAAa,KAAK,QAAQ,CAAC;aAC1C;SACF;KACF;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAZD,wDAYC;AAED,SAAgB,aAAa,CAAC,GAAQ;;IACpC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC3B,MAAM,oBAAoB,GAAG,MAAA,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,0CAAG,CAAC,CAAC,CAAC;QACrD,IAAI,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE;YACvC,MAAM,aAAa,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC;YAC9C,OAAO,OAAO,aAAa,KAAK,QAAQ,CAAC;SAC1C;KACF;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AATD,sCASC"}
1
+ {"version":3,"file":"TypePredicateUtil.js","sourceRoot":"","sources":["TypePredicateUtil.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAKH,SAAgB,aAAa,CAAC,GAAQ;IACpC,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;AAC1D,CAAC;AAFD,sCAEC;AAED,SAAgB,kBAAkB,CAAC,GAAQ;IACzC,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC;AAClG,CAAC;AAFD,gDAEC;AAED,SAAgB,sBAAsB,CAAC,GAAQ;;IAC7C,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC3B,MAAM,qBAAqB,GAAG,MAAA,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,0CAAG,CAAC,CAAC,CAAC;QACtD,IAAI,OAAO,qBAAqB,KAAK,QAAQ,EAAE;YAC7C,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,qBAA+B,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7E,IAAI,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE;gBACrC,MAAM,aAAa,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;gBAC5C,OAAO,OAAO,aAAa,KAAK,QAAQ,IAAI,OAAO,aAAa,KAAK,WAAW,CAAC;aAClF;SACF;KACF;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAZD,wDAYC;AAED,SAAgB,aAAa,CAAC,GAAQ;;IACpC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC3B,MAAM,oBAAoB,GAAG,MAAA,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,0CAAG,CAAC,CAAC,CAAC;QACrD,IAAI,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE;YACvC,MAAM,aAAa,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC;YAC9C,OAAO,OAAO,aAAa,KAAK,QAAQ,CAAC;SAC1C;KACF;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AATD,sCASC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ /*
3
+ * Wire
4
+ * Copyright (C) 2021 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 TypePredicateUtil_1 = require("./TypePredicateUtil");
22
+ describe('TypePredicatUtil', () => {
23
+ describe('isQualifiedUserClients', () => {
24
+ it('detects QualifiedUserClients', () => {
25
+ const validUserClients = [
26
+ { domain1: { user1: ['client1'] } },
27
+ { domain1: { user1: [] } }, // When a user has no clients
28
+ ];
29
+ validUserClients.forEach(payload => expect((0, TypePredicateUtil_1.isQualifiedUserClients)(payload)).toBeTrue());
30
+ });
31
+ it('rejects non QualifiedUserClients', () => {
32
+ const invalidUserClients = [
33
+ { domain1: { user1: '' } },
34
+ { domain1: { user1: {} } },
35
+ { domain1: [] },
36
+ { domain1: { user1: [{}] } },
37
+ ];
38
+ invalidUserClients.forEach(payload => expect((0, TypePredicateUtil_1.isQualifiedUserClients)(payload)).toBeFalse());
39
+ });
40
+ });
41
+ });
42
+ //# sourceMappingURL=TypePredicateUtil.test.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypePredicateUtil.test.node.js","sourceRoot":"","sources":["TypePredicateUtil.test.node.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;AAEH,2DAA2D;AAE3D,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,gBAAgB,GAAG;gBACvB,EAAC,OAAO,EAAE,EAAC,KAAK,EAAE,CAAC,SAAS,CAAC,EAAC,EAAC;gBAC/B,EAAC,OAAO,EAAE,EAAC,KAAK,EAAE,EAAE,EAAC,EAAC,EAAE,6BAA6B;aACtD,CAAC;YAEF,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,IAAA,0CAAsB,EAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC1F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,kBAAkB,GAAG;gBACzB,EAAC,OAAO,EAAE,EAAC,KAAK,EAAE,EAAE,EAAC,EAAC;gBACtB,EAAC,OAAO,EAAE,EAAC,KAAK,EAAE,EAAE,EAAC,EAAC;gBACtB,EAAC,OAAO,EAAE,EAAE,EAAC;gBACb,EAAC,OAAO,EAAE,EAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAC,EAAC;aACzB,CAAC;YAEF,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,IAAA,0CAAsB,EAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Wire
3
+ * Copyright (C) 2021 Wire Swiss GmbH
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program. If not, see http://www.gnu.org/licenses/.
17
+ *
18
+ */
19
+
20
+ import {isQualifiedUserClients} from './TypePredicateUtil';
21
+
22
+ describe('TypePredicatUtil', () => {
23
+ describe('isQualifiedUserClients', () => {
24
+ it('detects QualifiedUserClients', () => {
25
+ const validUserClients = [
26
+ {domain1: {user1: ['client1']}},
27
+ {domain1: {user1: []}}, // When a user has no clients
28
+ ];
29
+
30
+ validUserClients.forEach(payload => expect(isQualifiedUserClients(payload)).toBeTrue());
31
+ });
32
+
33
+ it('rejects non QualifiedUserClients', () => {
34
+ const invalidUserClients = [
35
+ {domain1: {user1: ''}},
36
+ {domain1: {user1: {}}},
37
+ {domain1: []},
38
+ {domain1: {user1: [{}]}},
39
+ ];
40
+
41
+ invalidUserClients.forEach(payload => expect(isQualifiedUserClients(payload)).toBeFalse());
42
+ });
43
+ });
44
+ });
@@ -35,7 +35,7 @@ export function isQualifiedUserClients(obj: any): obj is QualifiedUserClients {
35
35
  const firstClientIdArray = Object.values(firstUserClientObject as object)[0];
36
36
  if (Array.isArray(firstClientIdArray)) {
37
37
  const firstClientId = firstClientIdArray[0];
38
- return typeof firstClientId === 'string';
38
+ return typeof firstClientId === 'string' || typeof firstClientId === 'undefined';
39
39
  }
40
40
  }
41
41
  }