Skip to content

Commit 7ec0d6f

Browse files
aleksandernsilvaggazzo
authored andcommitted
feat: User phone identity lookup for external voice calls (#40680)
1 parent 7a45180 commit 7ec0d6f

3 files changed

Lines changed: 38 additions & 3 deletions

File tree

ee/packages/media-calls/src/server/CastDirector.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import type { IUser, MediaCallActor, MediaCallActorType, MediaCallContact, Media
22
import type { CallRole } from '@rocket.chat/media-signaling';
33
import { Users } from '@rocket.chat/models';
44

5+
import { BroadcastActorAgent } from './BroadcastAgent';
56
import type { IMediaCallAgent } from '../definition/IMediaCallAgent';
67
import type { IMediaCallCastDirector } from '../definition/IMediaCallCastDirector';
78
import type { GetActorContactOptions, MinimalUserData, MediaCallHeader } from '../definition/common';
89
import { UserActorAgent } from '../internal/agents/UserActorAgent';
910
import { logger } from '../logger';
10-
import { BroadcastActorAgent } from './BroadcastAgent';
1111

1212
type ContactList = Record<MediaCallActorType, MediaCallContact | null>;
1313

@@ -89,11 +89,28 @@ export class MediaCallCastDirector implements IMediaCallCastDirector {
8989

9090
const list = user
9191
? this.buildContactListForUser(user, defaultContactInfo)
92-
: this.buildContactListForExtension(sipExtension, defaultContactInfo);
92+
: await this.buildContactListForExtension(sipExtension, defaultContactInfo);
9393

9494
return this.getContactFromList(list, options);
9595
}
9696

97+
private async findUserByPhone(phoneNumber: string): Promise<Pick<IUser, '_id' | 'name' | 'username' | 'freeSwitchExtension'> | null> {
98+
const users = await Users.findByPhone<Pick<IUser, '_id' | 'name' | 'username' | 'freeSwitchExtension'>>(phoneNumber, {
99+
projection: { name: 1, username: 1, freeSwitchExtension: 1 },
100+
}).toArray();
101+
102+
if (!users.length) {
103+
return null;
104+
}
105+
106+
if (users.length > 1) {
107+
logger.warn({ msg: 'Multiple users found for phone number, identity cannot be resolved', phoneNumber });
108+
return null;
109+
}
110+
111+
return users[0];
112+
}
113+
97114
public async getAgentForActorAndRole(actor: MediaCallContact, role: CallRole): Promise<IMediaCallAgent | null> {
98115
if (actor.type === 'user') {
99116
return this.getAgentForUserActorAndRole(actor, role);
@@ -141,10 +158,17 @@ export class MediaCallCastDirector implements IMediaCallCastDirector {
141158
};
142159
}
143160

144-
protected buildContactListForExtension(sipExtension: string, defaultContactInfo?: MediaCallContactInformation): ContactList {
161+
protected async buildContactListForExtension(
162+
sipExtension: string,
163+
defaultContactInfo?: MediaCallContactInformation,
164+
): Promise<ContactList> {
165+
const user = await this.findUserByPhone(sipExtension);
166+
145167
const data: Partial<MediaCallContact> = {
146168
...defaultContactInfo,
147169
...(sipExtension && { sipExtension }),
170+
...(user?.username && { username: user.username }),
171+
...(user?.name && { displayName: user.name }),
148172
};
149173

150174
return {

packages/model-typings/src/models/IUsersModel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ export interface IUsersModel extends IBaseModel<IUser> {
443443
findAgentsAvailableWithoutBusinessHours(userIds?: IUser['_id'][]): FindCursor<Pick<ILivechatAgent, '_id' | 'openBusinessHours'>>;
444444
updateLivechatStatusByAgentIds(userIds: string[], status: ILivechatAgentStatus): Promise<UpdateResult | Document>;
445445
findOneByFreeSwitchExtension<T extends Document = IUser>(freeSwitchExtension: string, options?: FindOptions<IUser>): Promise<T | null>;
446+
findByPhone<T extends Document = IUser>(phoneNumber: string, options?: FindOptions<IUser>): FindCursor<T>;
446447
countUsersInRoles(roles: IRole['_id'][]): Promise<number>;
447448
countAllUsersWithPendingAvatar(): Promise<number>;
448449
findOneByIdAndRole(userId: IUser['_id'], role: string, options: FindOptions<IUser>): Promise<IUser | null>;

packages/models/src/models/Users.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export class UsersRaw extends BaseRaw<IUser, DefaultFields<IUser>> implements IU
6868
{ key: { openBusinessHours: 1 }, sparse: true },
6969
{ key: { statusLivechat: 1 }, sparse: true },
7070
{ key: { freeSwitchExtension: 1 }, sparse: true, unique: true },
71+
{ key: { 'phones.number': 1 }, sparse: true },
7172
{ key: { language: 1 }, sparse: true },
7273
{ key: { 'active': 1, 'services.email2fa.enabled': 1 }, sparse: true }, // used by statistics
7374
{ key: { 'active': 1, 'services.totp.enabled': 1 }, sparse: true }, // used by statistics
@@ -2765,6 +2766,15 @@ export class UsersRaw extends BaseRaw<IUser, DefaultFields<IUser>> implements IU
27652766
);
27662767
}
27672768

2769+
findByPhone<T extends Document = IUser>(phoneNumber: string, options: FindOptions<IUser> = {}): FindCursor<T> {
2770+
return this.find<T>(
2771+
{
2772+
'phones.number': phoneNumber,
2773+
} as Filter<IUser>,
2774+
options,
2775+
);
2776+
}
2777+
27682778
// UPDATE
27692779
addImportIds(_id: IUser['_id'], importIds: string[]) {
27702780
importIds = ([] as string[]).concat(importIds);

0 commit comments

Comments
 (0)