Skip to content

Commit 32a74bf

Browse files
authored
refactor: Use UserEntities to get clients by user (#10923)
1 parent 2cfa23e commit 32a74bf

File tree

10 files changed

+202
-113
lines changed

10 files changed

+202
-113
lines changed

src/script/client/ClientRepository.test.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*
1818
*/
1919

20-
import {ClientClassification, ClientType} from '@wireapp/api-client/src/client/';
20+
import {ClientClassification, ClientType, PublicClient, QualifiedPublicClients} from '@wireapp/api-client/src/client/';
2121
import {StatusCodes as HTTP_STATUS} from 'http-status-codes';
2222
import {Runtime} from '@wireapp/commons';
2323

@@ -47,16 +47,14 @@ describe('ClientRepository', () => {
4747

4848
testFactory.client_repository['clientState'].currentClient(client);
4949

50-
/** @type {import('@wireapp/api-client/src/client').PublicClient[]} */
51-
const allClients = [
50+
const allClients: PublicClient[] = [
5251
{class: ClientClassification.DESKTOP, id: '706f64373b1bcf79'},
5352
{class: ClientClassification.PHONE, id: '809fd276d6709474'},
5453
{class: ClientClassification.DESKTOP, id: '8e11e06549c8cf1a'},
5554
{class: ClientClassification.TABLET, id: 'c411f97b139c818b'},
5655
{class: ClientClassification.DESKTOP, id: 'cbf3ea49214702d8'},
5756
];
58-
/** @type {import('@wireapp/api-client/src/client').QualifiedPublicClients} */
59-
const userClientMap = {
57+
const userClientMap: QualifiedPublicClients = {
6058
none: {
6159
[entities.user.john_doe.id]: allClients,
6260
},
@@ -65,8 +63,11 @@ describe('ClientRepository', () => {
6563
Promise.resolve(userClientMap),
6664
);
6765

68-
const clientEntities = await testFactory.client_repository.getClientsByUserIds([entities.user.john_doe.id]);
69-
expect(clientEntities[entities.user.john_doe.id].length).toBe(allClients.length);
66+
const clientEntities = await testFactory.client_repository.getClientsByUserIds(
67+
[entities.user.john_doe.id],
68+
false,
69+
);
70+
expect(clientEntities.none[entities.user.john_doe.id].length).toBe(allClients.length);
7071
});
7172
});
7273

src/script/client/ClientRepository.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
*/
1919

2020
import ko from 'knockout';
21-
import {ClientType, PublicClient, RegisteredClient} from '@wireapp/api-client/src/client/';
22-
import {USER_EVENT, UserClientAddEvent, UserClientRemoveEvent} from '@wireapp/api-client/src/event/';
21+
import {ClientType, PublicClient, QualifiedPublicClients, RegisteredClient} from '@wireapp/api-client/src/client/';
22+
import {USER_EVENT, UserClientAddEvent, UserClientRemoveEvent} from '@wireapp/api-client/src/event';
23+
import {QualifiedId} from '@wireapp/api-client/src/user/';
2324
import {Runtime} from '@wireapp/commons';
2425
import {amplify} from 'amplify';
2526
import {WebAppEvents} from '@wireapp/webapp-events';
@@ -43,6 +44,8 @@ import {ClientError} from '../error/ClientError';
4344
import {ClientRecord} from '../storage';
4445
import {ClientState} from './ClientState';
4546

47+
export type QualifiedUserClientMap = {[domain: string]: {[userId: string]: ClientEntity[]}};
48+
4649
export class ClientRepository {
4750
private readonly logger: Logger;
4851
public selfUser: ko.Observable<User>;
@@ -342,29 +345,34 @@ export class ClientRepository {
342345
* Retrieves meta information about all the clients of a given user.
343346
* @note If you want to get very detailed information about the devices from the own user, then use `getClients()`.
344347
*
345-
* @param userId User ID to retrieve client information for
348+
* @param userIds User IDs to retrieve client information for
346349
* @param updateClients Automatically update the clients
347350
* @returns Resolves with an array of client entities
348351
*/
349-
async getClientsByUserIds(userId: string[], updateClients: false): Promise<Record<string, PublicClient[]>>;
350-
async getClientsByUserIds(userId: string[], updateClients?: boolean): Promise<Record<string, ClientEntity[]>>;
352+
async getClientsByUserIds(userIds: (QualifiedId | string)[], updateClients: true): Promise<QualifiedUserClientMap>;
353+
async getClientsByUserIds(userIds: (QualifiedId | string)[], updateClients: false): Promise<QualifiedPublicClients>;
351354
async getClientsByUserIds(
352-
userId: string[],
353-
updateClients: boolean = true,
354-
): Promise<Record<string, ClientEntity[]> | Record<string, PublicClient[]>> {
355-
const userClientsMap = await this.clientService.getClientsByUserIds(userId);
355+
userIds: (QualifiedId | string)[],
356+
updateClients: boolean,
357+
): Promise<QualifiedPublicClients | QualifiedUserClientMap> {
358+
const userClientsMap = await this.clientService.getClientsByUserIds(userIds);
356359

357360
if (updateClients) {
358-
const clientEntityMap: Record<string, ClientEntity[]> = {};
361+
const clientEntityMap: QualifiedUserClientMap = {};
359362
await Promise.all(
360-
Object.entries(userClientsMap.none).map(async ([userId, clients]) => {
361-
clientEntityMap[userId] = await this.updateClientsOfUserById(userId, clients);
362-
}),
363+
Object.entries(userClientsMap).map(([domain, userClientMap]) =>
364+
Object.entries(userClientMap).map(async ([userId, clients]) => {
365+
if (!clientEntityMap[domain]) {
366+
clientEntityMap[domain] = {};
367+
}
368+
clientEntityMap[domain][userId] = await this.updateClientsOfUserById(userId, clients);
369+
}),
370+
),
363371
);
364372
return clientEntityMap;
365373
}
366374

367-
return userClientsMap.none;
375+
return userClientsMap;
368376
}
369377

370378
private async getClientByUserIdFromDb(requestedUserId: string): Promise<ClientRecord[]> {

src/script/client/ClientService.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
*
1818
*/
1919

20-
import type {NewClient, QualifiedPublicClients, RegisteredClient} from '@wireapp/api-client/src/client/';
20+
import type {NewClient, QualifiedPublicClients, RegisteredClient} from '@wireapp/api-client/src/client';
21+
import type {QualifiedId} from '@wireapp/api-client/src/user';
2122
import {container} from 'tsyringe';
2223

2324
import {Logger, getLogger} from 'Util/Logger';
@@ -100,13 +101,31 @@ export class ClientService {
100101
* @param userId ID of user to retrieve clients for
101102
* @returns Resolves with the clients of a user
102103
*/
103-
async getClientsByUserIds(userIds: string[]): Promise<QualifiedPublicClients> {
104-
const clients: QualifiedPublicClients = {none: {}};
105-
106-
for (const userId of userIds) {
104+
async getClientsByUserIds(userIds: (QualifiedId | string)[]): Promise<QualifiedPublicClients> {
105+
// Add 'none' as domain for non-federated users
106+
let clients: QualifiedPublicClients = {none: {}};
107+
108+
const {qualifiedIds, stringIds} = userIds.reduce(
109+
(result, userId) => {
110+
if (typeof userId === 'string') {
111+
result.stringIds.push(userId);
112+
} else {
113+
result.qualifiedIds.push(userId);
114+
}
115+
return result;
116+
},
117+
{qualifiedIds: [], stringIds: []},
118+
);
119+
120+
for (const userId of stringIds) {
107121
clients.none[userId] = await this.apiClient.user.api.getClients(userId);
108122
}
109123

124+
if (qualifiedIds.length) {
125+
const listedClients = await this.apiClient.user.api.postListClients(qualifiedIds);
126+
clients = {...clients, ...listedClients};
127+
}
128+
110129
return clients;
111130
}
112131

src/script/components/userDevices.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,15 @@ ko.components.register('user-devices', {
200200
this.showDevicesNotFound = () => showDeviceList() && this.deviceMode() === FIND_MODE.NOT_FOUND;
201201

202202
clientRepository
203-
.getClientsByUserIds([userEntity().id])
204-
.then(clientEntityMap => {
205-
for (const clientEntities of Object.values(clientEntityMap)) {
206-
this.clientEntities(sortUserDevices(clientEntities));
207-
const hasDevices = clientEntities.length > 0;
208-
const deviceMode = hasDevices ? FIND_MODE.FOUND : FIND_MODE.NOT_FOUND;
209-
this.deviceMode(deviceMode);
203+
.getClientsByUserIds([userEntity().id], true)
204+
.then(qualifiedUsersMap => {
205+
for (const userClientMaps of Object.values(qualifiedUsersMap)) {
206+
for (const clientEntities of Object.values(userClientMaps)) {
207+
this.clientEntities(sortUserDevices(clientEntities));
208+
const hasDevices = clientEntities.length > 0;
209+
const deviceMode = hasDevices ? FIND_MODE.FOUND : FIND_MODE.NOT_FOUND;
210+
this.deviceMode(deviceMode);
211+
}
210212
}
211213
})
212214
.catch(error => {

0 commit comments

Comments
 (0)