diff --git a/packages/cli/src/Interfaces.ts b/packages/cli/src/Interfaces.ts index 1caadbee57..b57836d397 100644 --- a/packages/cli/src/Interfaces.ts +++ b/packages/cli/src/Interfaces.ts @@ -356,6 +356,13 @@ export interface IInternalHooksClass { target_user_id: string[]; public_api: boolean; email_sent: boolean; + invitee_role: string; + }): Promise; + onUserRoleChange(userInviteData: { + user: User; + target_user_id: string; + public_api: boolean; + target_user_new_role: string; }): Promise; onUserReinvite(userReinviteData: { user: User; diff --git a/packages/cli/src/InternalHooks.ts b/packages/cli/src/InternalHooks.ts index 863a0e05bc..45b5c8ed1c 100644 --- a/packages/cli/src/InternalHooks.ts +++ b/packages/cli/src/InternalHooks.ts @@ -498,6 +498,7 @@ export class InternalHooks implements IInternalHooksClass { target_user_id: string[]; public_api: boolean; email_sent: boolean; + invitee_role: string; }): Promise { void Promise.all([ eventBus.sendAuditEvent({ @@ -507,15 +508,28 @@ export class InternalHooks implements IInternalHooksClass { targetUserId: userInviteData.target_user_id, }, }), + this.telemetry.track('User invited new user', { user_id: userInviteData.user.id, target_user_id: userInviteData.target_user_id, public_api: userInviteData.public_api, email_sent: userInviteData.email_sent, + invitee_role: userInviteData.invitee_role, }), ]); } + async onUserRoleChange(userRoleChangeData: { + user: User; + target_user_id: string; + public_api: boolean; + target_user_new_role: string; + }) { + const { user, ...rest } = userRoleChangeData; + + void this.telemetry.track('User changed role', { user_id: user.id, ...rest }); + } + async onUserReinvite(userReinviteData: { user: User; target_user_id: string; diff --git a/packages/cli/src/controllers/users.controller.ts b/packages/cli/src/controllers/users.controller.ts index 0ef0ae55b6..6e0ae6438e 100644 --- a/packages/cli/src/controllers/users.controller.ts +++ b/packages/cli/src/controllers/users.controller.ts @@ -391,6 +391,13 @@ export class UsersController { await this.userService.update(targetUser.id, { globalRole: roleToSet }); + void this.internalHooks.onUserRoleChange({ + user: req.user, + target_user_id: targetUser.id, + target_user_new_role: [newRole.scope, newRole.name].join(' '), + public_api: false, + }); + return { success: true }; } } diff --git a/packages/cli/src/services/user.service.ts b/packages/cli/src/services/user.service.ts index 2dd4122f1a..41037f26c2 100644 --- a/packages/cli/src/services/user.service.ts +++ b/packages/cli/src/services/user.service.ts @@ -188,7 +188,11 @@ export class UserService { return Promise.race([fetchPromise, timeoutPromise]); } - private async sendEmails(owner: User, toInviteUsers: { [key: string]: string }) { + private async sendEmails( + owner: User, + toInviteUsers: { [key: string]: string }, + role: 'member' | 'admin', + ) { const domain = getInstanceBaseUrl(); return Promise.all( @@ -225,6 +229,7 @@ export class UserService { target_user_id: Object.values(toInviteUsers), public_api: false, email_sent: result.emailSent, + invitee_role: role, // same role for all invited users }); } catch (e) { if (e instanceof Error) { @@ -294,7 +299,11 @@ export class UserService { pendingUsersToInvite.forEach(({ email, id }) => createdUsers.set(email, id)); - const usersInvited = await this.sendEmails(owner, Object.fromEntries(createdUsers)); + const usersInvited = await this.sendEmails( + owner, + Object.fromEntries(createdUsers), + toCreateUsers[0].role, // same role for all invited users + ); return { usersInvited, usersCreated: toCreateUsers.map(({ email }) => email) }; }