From eeb1e548ae0359af972c13e91f67309e5bfa3a3f Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Wed, 26 Feb 2025 21:04:37 +0530 Subject: [PATCH 01/15] fix: ensure user services object is loaded before loading is complete --- apps/meteor/app/authentication/server/startup/index.js | 4 ++-- apps/meteor/app/utils/server/functions/getBaseUserFields.ts | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 03c9602e59f00..5f369d7a1ca27 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -23,7 +23,7 @@ import { setAvatarFromServiceWithValidation } from '../../../lib/server/function import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import * as Mailer from '../../../mailer/server/api'; import { settings } from '../../../settings/server'; -import { getBaseUserFields } from '../../../utils/server/functions/getBaseUserFields'; +import { getBaseUserFields, getBaseUserFieldsWithTwoFactor } from '../../../utils/server/functions/getBaseUserFields'; import { safeGetMeteorUser } from '../../../utils/server/functions/safeGetMeteorUser'; import { isValidAttemptByUser, isValidLoginAttemptByIp } from '../lib/restrictLoginAttempts'; @@ -40,7 +40,7 @@ Accounts.config({ * * we are removing the status here because meteor send 'offline' */ -Object.assign(Accounts._defaultPublishFields.projection, (({ status, ...rest }) => rest)(getBaseUserFields())); +Object.assign(Accounts._defaultPublishFields.projection, (({ status, ...rest }) => rest)(getBaseUserFieldsWithTwoFactor())); Meteor.startup(() => { settings.watchMultiple(['Accounts_LoginExpiration', 'Site_Name', 'From_Email'], () => { diff --git a/apps/meteor/app/utils/server/functions/getBaseUserFields.ts b/apps/meteor/app/utils/server/functions/getBaseUserFields.ts index 5e2a3bf2b4d73..68db5318c3b96 100644 --- a/apps/meteor/app/utils/server/functions/getBaseUserFields.ts +++ b/apps/meteor/app/utils/server/functions/getBaseUserFields.ts @@ -32,3 +32,9 @@ export const getBaseUserFields = (): UserFields => ({ 'extension': 1, 'openBusinessHours': 1, }); + +export const getBaseUserFieldsWithTwoFactor = (): UserFields => ({ + ...getBaseUserFields(), + 'services.totp.enabled': 1, + 'services.email2fa.enabled': 1, +}); From 06ae4f7e4986499108424fe73cce3d140bad73a8 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Fri, 28 Feb 2025 21:45:57 +0530 Subject: [PATCH 02/15] add ui tests --- apps/meteor/server/startup/initialData.js | 2 +- apps/meteor/tests/e2e/enforce-2FA.spec.ts | 63 +++++++++++++++++++ .../page-objects/fragments/home-sidenav.ts | 4 ++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 apps/meteor/tests/e2e/enforce-2FA.spec.ts diff --git a/apps/meteor/server/startup/initialData.js b/apps/meteor/server/startup/initialData.js index 30415e8b20224..5de4aad42aab5 100644 --- a/apps/meteor/server/startup/initialData.js +++ b/apps/meteor/server/startup/initialData.js @@ -217,7 +217,7 @@ Meteor.startup(async () => { emails: [ { address: 'rocketchat.internal.admin.test@rocket.chat', - verified: false, + verified: true, }, ], status: 'offline', diff --git a/apps/meteor/tests/e2e/enforce-2FA.spec.ts b/apps/meteor/tests/e2e/enforce-2FA.spec.ts new file mode 100644 index 0000000000000..cb5671864e3d5 --- /dev/null +++ b/apps/meteor/tests/e2e/enforce-2FA.spec.ts @@ -0,0 +1,63 @@ +import { IS_EE } from './config/constants'; +import { Users } from './fixtures/userStates'; +import { HomeChannel, AccountProfile } from './page-objects'; +import { createCustomRole, deleteCustomRole } from './utils/custom-role'; +import { test, expect } from './utils/test'; + +test.use({ storageState: Users.admin.state }); + +test.describe('enforce two factor authentication', () => { + test.skip(!IS_EE, 'Enterprise Only'); + + let poHomeChannel: HomeChannel; + let poAccountProfile: AccountProfile; + let customRoleId = ''; + test.beforeEach(async ({ page }) => { + poHomeChannel = new HomeChannel(page); + poAccountProfile = new AccountProfile(page); + }); + + test.beforeAll(async ({ api }) => { + const roleResponse = await createCustomRole(api, { name: 'enforce-2FA', mandatory2fa: true }); + expect(roleResponse.status()).toBe(200); + const { role } = await roleResponse.json(); + customRoleId = role._id; + + const userUpdateRes = await api.post('/users.update', { + data: { roles: ['user', customRoleId, 'admin'] }, + userId: 'rocketchat.internal.admin.test', + }); + expect(userUpdateRes.status()).toBe(200); + + const disableEmail2FA = await api.post('/users.2fa.disableEmail', {}); + expect(disableEmail2FA.status()).toBe(200); + }); + + test.afterAll(async ({ api }) => { + const userUpdateRes = await api.post('/users.update', { + data: { roles: ['user', 'admin'] }, + userId: 'rocketchat.internal.admin.test', + }); + expect(userUpdateRes.status()).toBe(200); + + const deleteRole = await deleteCustomRole(api, 'enforce-2FA'); + expect(deleteRole.status()).toBe(200); + + const enableEmail2FA = await api.post('/users.2fa.enableEmail', {}); + expect(enableEmail2FA.status()).toBe(200); + }); + + test('should redirect to 2FA setup page and setup email 2FA', async ({ page }) => { + await page.goto('/home'); + await expect(poHomeChannel.sidenav.sidebarHomeAction).not.toBeVisible(); + await expect(poAccountProfile.securityHeader).toBeVisible(); + + await poAccountProfile.security2FASection.click(); + await expect(poAccountProfile.enableEmail2FAButton).toBeVisible(); + await poAccountProfile.enableEmail2FAButton.click(); + + await expect(poHomeChannel.toastSuccess).toBeVisible(); + await expect(poHomeChannel.sidenav.sidebarHomeAction).toBeVisible(); + await expect(poAccountProfile.securityHeader).not.toBeVisible(); + }); +}); diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts index 7b6a67ced7cdf..4f96197d0c5c0 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts @@ -53,6 +53,10 @@ export class HomeSidenav { return this.page.getByRole('toolbar', { name: 'Sidebar actions' }); } + get sidebarHomeAction(): Locator { + return this.sidebarToolbar.getByRole('button', { name: 'Home' }); + } + async setDisplayMode(mode: 'Extended' | 'Medium' | 'Condensed'): Promise { await this.sidebarToolbar.getByRole('button', { name: 'Display', exact: true }).click(); await this.sidebarToolbar.getByRole('menuitemcheckbox', { name: mode }).click(); From 7b2b26e7faecb9bcac36506e6c465221c27eb917 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Fri, 28 Feb 2025 22:00:44 +0530 Subject: [PATCH 03/15] fix unused var --- apps/meteor/app/authentication/server/startup/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 5f369d7a1ca27..89b17f2f83f77 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -23,7 +23,7 @@ import { setAvatarFromServiceWithValidation } from '../../../lib/server/function import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import * as Mailer from '../../../mailer/server/api'; import { settings } from '../../../settings/server'; -import { getBaseUserFields, getBaseUserFieldsWithTwoFactor } from '../../../utils/server/functions/getBaseUserFields'; +import { getBaseUserFieldsWithTwoFactor } from '../../../utils/server/functions/getBaseUserFields'; import { safeGetMeteorUser } from '../../../utils/server/functions/safeGetMeteorUser'; import { isValidAttemptByUser, isValidLoginAttemptByIp } from '../lib/restrictLoginAttempts'; From 4406b2fd626a5a3bebe17bf8f90633cd03e38bb0 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Mon, 3 Mar 2025 20:18:51 +0530 Subject: [PATCH 04/15] refactor --- apps/meteor/app/authentication/server/startup/index.js | 4 ++-- apps/meteor/app/utils/server/functions/getBaseUserFields.ts | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 89b17f2f83f77..ec3aa52b1a10f 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -23,7 +23,7 @@ import { setAvatarFromServiceWithValidation } from '../../../lib/server/function import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import * as Mailer from '../../../mailer/server/api'; import { settings } from '../../../settings/server'; -import { getBaseUserFieldsWithTwoFactor } from '../../../utils/server/functions/getBaseUserFields'; +import { getDefaultUserFields } from '../../../utils/server/functions/getDefaultUserFields'; import { safeGetMeteorUser } from '../../../utils/server/functions/safeGetMeteorUser'; import { isValidAttemptByUser, isValidLoginAttemptByIp } from '../lib/restrictLoginAttempts'; @@ -40,7 +40,7 @@ Accounts.config({ * * we are removing the status here because meteor send 'offline' */ -Object.assign(Accounts._defaultPublishFields.projection, (({ status, ...rest }) => rest)(getBaseUserFieldsWithTwoFactor())); +Object.assign(Accounts._defaultPublishFields.projection, (({ status, ...rest }) => rest)(getDefaultUserFields())); Meteor.startup(() => { settings.watchMultiple(['Accounts_LoginExpiration', 'Site_Name', 'From_Email'], () => { diff --git a/apps/meteor/app/utils/server/functions/getBaseUserFields.ts b/apps/meteor/app/utils/server/functions/getBaseUserFields.ts index 68db5318c3b96..5e2a3bf2b4d73 100644 --- a/apps/meteor/app/utils/server/functions/getBaseUserFields.ts +++ b/apps/meteor/app/utils/server/functions/getBaseUserFields.ts @@ -32,9 +32,3 @@ export const getBaseUserFields = (): UserFields => ({ 'extension': 1, 'openBusinessHours': 1, }); - -export const getBaseUserFieldsWithTwoFactor = (): UserFields => ({ - ...getBaseUserFields(), - 'services.totp.enabled': 1, - 'services.email2fa.enabled': 1, -}); From eaa1b58154623a6a07d1eb0f2d405e8c8bcbdaac Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Mon, 3 Mar 2025 20:24:16 +0530 Subject: [PATCH 05/15] add cs --- .changeset/chatty-kids-compare.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/chatty-kids-compare.md diff --git a/.changeset/chatty-kids-compare.md b/.changeset/chatty-kids-compare.md new file mode 100644 index 0000000000000..da889e416ddf5 --- /dev/null +++ b/.changeset/chatty-kids-compare.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes an issue where account security page was flashing sometimes for users with mandatory two factor configured. From d6a3ef8ba1c8fd8504e259b6ee5068eed51b461c Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 4 Mar 2025 03:15:00 +0530 Subject: [PATCH 06/15] fix review --- apps/meteor/app/authentication/server/startup/index.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index ec3aa52b1a10f..3704a3e46e815 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -23,7 +23,7 @@ import { setAvatarFromServiceWithValidation } from '../../../lib/server/function import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import * as Mailer from '../../../mailer/server/api'; import { settings } from '../../../settings/server'; -import { getDefaultUserFields } from '../../../utils/server/functions/getDefaultUserFields'; +import { getBaseUserFields } from '../../../utils/server/functions/getBaseUserFields'; import { safeGetMeteorUser } from '../../../utils/server/functions/safeGetMeteorUser'; import { isValidAttemptByUser, isValidLoginAttemptByIp } from '../lib/restrictLoginAttempts'; @@ -40,7 +40,10 @@ Accounts.config({ * * we are removing the status here because meteor send 'offline' */ -Object.assign(Accounts._defaultPublishFields.projection, (({ status, ...rest }) => rest)(getDefaultUserFields())); +Object.assign( + Accounts._defaultPublishFields.projection, + (({ status, ...rest }) => rest)({ ...getBaseUserFields(), 'services.totp.enabled': 1, 'services.email2fa.enabled': 1 }), +); Meteor.startup(() => { settings.watchMultiple(['Accounts_LoginExpiration', 'Site_Name', 'From_Email'], () => { From c9096568d4d835f5f3f9880724627eadc5ae5bb3 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 18 Mar 2025 20:01:42 +0530 Subject: [PATCH 07/15] fix for microservices --- ee/apps/ddp-streamer/src/DDPStreamer.ts | 3 +- .../src/helpers/getBaseUserFields.ts | 34 +++++++++++++++++++ packages/rest-typings/src/index.ts | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 packages/rest-typings/src/helpers/getBaseUserFields.ts diff --git a/ee/apps/ddp-streamer/src/DDPStreamer.ts b/ee/apps/ddp-streamer/src/DDPStreamer.ts index 1c880929650db..4ff366a523ef5 100644 --- a/ee/apps/ddp-streamer/src/DDPStreamer.ts +++ b/ee/apps/ddp-streamer/src/DDPStreamer.ts @@ -3,6 +3,7 @@ import crypto from 'crypto'; import { MeteorService, Presence, ServiceClass } from '@rocket.chat/core-services'; import { InstanceStatus } from '@rocket.chat/instance-status'; import { Users } from '@rocket.chat/models'; +import { getBaseUserFields } from '@rocket.chat/rest-typings'; import polka from 'polka'; import { throttle } from 'underscore'; import WebSocket from 'ws'; @@ -127,7 +128,7 @@ export class DDPStreamer extends ServiceClass { async function sendUserData(client: Client, userId: string) { // TODO figure out what fields to send. maybe to to export function getBaseUserFields to a package const loggedUser = await Users.findOneById(userId, { - projection: { name: 1, username: 1, settings: 1, roles: 1, active: 1, statusLivechat: 1, statusDefault: 1, status: 1 }, + projection: { ...getBaseUserFields(), 'services.totp.enabled': 1, 'services.email2fa.enabled': 1 }, }); if (!loggedUser) { return; diff --git a/packages/rest-typings/src/helpers/getBaseUserFields.ts b/packages/rest-typings/src/helpers/getBaseUserFields.ts new file mode 100644 index 0000000000000..5e2a3bf2b4d73 --- /dev/null +++ b/packages/rest-typings/src/helpers/getBaseUserFields.ts @@ -0,0 +1,34 @@ +type UserFields = { + [k: string]: number; +}; + +export const getBaseUserFields = (): UserFields => ({ + 'name': 1, + 'username': 1, + 'nickname': 1, + 'emails': 1, + 'status': 1, + 'statusDefault': 1, + 'statusText': 1, + 'statusConnection': 1, + 'bio': 1, + 'avatarOrigin': 1, + 'utcOffset': 1, + 'language': 1, + 'settings': 1, + 'enableAutoAway': 1, + 'idleTimeLimit': 1, + 'roles': 1, + 'active': 1, + 'defaultRoom': 1, + 'customFields': 1, + 'requirePasswordChange': 1, + 'requirePasswordChangeReason': 1, + 'statusLivechat': 1, + 'banners': 1, + 'oauth.authorizedClients': 1, + '_updatedAt': 1, + 'avatarETag': 1, + 'extension': 1, + 'openBusinessHours': 1, +}); diff --git a/packages/rest-typings/src/index.ts b/packages/rest-typings/src/index.ts index c3d5721493a6c..bd93162e03a9a 100644 --- a/packages/rest-typings/src/index.ts +++ b/packages/rest-typings/src/index.ts @@ -239,6 +239,7 @@ export * from './v1/oauthapps/UpdateOAuthAppParamsPOST'; export * from './v1/oauthapps/OAuthAppsGetParamsGET'; export * from './v1/oauthapps/OAuthAppsAddParamsPOST'; export * from './v1/oauthapps/DeleteOAuthAppParamsDELETE'; +export * from './helpers/getBaseUserFields'; export * from './helpers/PaginatedRequest'; export * from './helpers/PaginatedResult'; export * from './helpers/ReplacePlaceholders'; From bbef5936226e7f4290273c804269718d2475a491 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 18 Mar 2025 20:34:57 +0530 Subject: [PATCH 08/15] remove getBaseUserFields from app --- apps/meteor/app/api/server/v1/misc.ts | 2 +- .../authentication/server/startup/index.js | 2 +- .../server/functions/getBaseUserFields.ts | 34 ------------------- .../server/functions/getDefaultUserFields.ts | 2 +- 4 files changed, 3 insertions(+), 37 deletions(-) delete mode 100644 apps/meteor/app/utils/server/functions/getBaseUserFields.ts diff --git a/apps/meteor/app/api/server/v1/misc.ts b/apps/meteor/app/api/server/v1/misc.ts index 1d502f04df1ef..e26a3c6f47fb2 100644 --- a/apps/meteor/app/api/server/v1/misc.ts +++ b/apps/meteor/app/api/server/v1/misc.ts @@ -10,6 +10,7 @@ import { isMethodCallAnonProps, isFingerprintProps, isMeteorCall, + getBaseUserFields, } from '@rocket.chat/rest-typings'; import { escapeHTML } from '@rocket.chat/string-helpers'; import EJSON from 'ejson'; @@ -25,7 +26,6 @@ import { getLogs } from '../../../../server/stream/stdout'; import { passwordPolicy } from '../../../lib/server'; import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import { settings } from '../../../settings/server'; -import { getBaseUserFields } from '../../../utils/server/functions/getBaseUserFields'; import { isSMTPConfigured } from '../../../utils/server/functions/isSMTPConfigured'; import { getURL } from '../../../utils/server/getURL'; import { API } from '../api'; diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 3704a3e46e815..24d5e0488237b 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -1,6 +1,7 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; import { User } from '@rocket.chat/core-services'; import { Roles, Settings, Users } from '@rocket.chat/models'; +import { getBaseUserFields } from '@rocket.chat/rest-typings'; import { escapeRegExp, escapeHTML } from '@rocket.chat/string-helpers'; import { getLoginExpirationInDays } from '@rocket.chat/tools'; import { Accounts } from 'meteor/accounts-base'; @@ -23,7 +24,6 @@ import { setAvatarFromServiceWithValidation } from '../../../lib/server/function import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import * as Mailer from '../../../mailer/server/api'; import { settings } from '../../../settings/server'; -import { getBaseUserFields } from '../../../utils/server/functions/getBaseUserFields'; import { safeGetMeteorUser } from '../../../utils/server/functions/safeGetMeteorUser'; import { isValidAttemptByUser, isValidLoginAttemptByIp } from '../lib/restrictLoginAttempts'; diff --git a/apps/meteor/app/utils/server/functions/getBaseUserFields.ts b/apps/meteor/app/utils/server/functions/getBaseUserFields.ts deleted file mode 100644 index 5e2a3bf2b4d73..0000000000000 --- a/apps/meteor/app/utils/server/functions/getBaseUserFields.ts +++ /dev/null @@ -1,34 +0,0 @@ -type UserFields = { - [k: string]: number; -}; - -export const getBaseUserFields = (): UserFields => ({ - 'name': 1, - 'username': 1, - 'nickname': 1, - 'emails': 1, - 'status': 1, - 'statusDefault': 1, - 'statusText': 1, - 'statusConnection': 1, - 'bio': 1, - 'avatarOrigin': 1, - 'utcOffset': 1, - 'language': 1, - 'settings': 1, - 'enableAutoAway': 1, - 'idleTimeLimit': 1, - 'roles': 1, - 'active': 1, - 'defaultRoom': 1, - 'customFields': 1, - 'requirePasswordChange': 1, - 'requirePasswordChangeReason': 1, - 'statusLivechat': 1, - 'banners': 1, - 'oauth.authorizedClients': 1, - '_updatedAt': 1, - 'avatarETag': 1, - 'extension': 1, - 'openBusinessHours': 1, -}); diff --git a/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts b/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts index 293eb8607342d..e5ca39688f952 100644 --- a/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts +++ b/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts @@ -1,4 +1,4 @@ -import { getBaseUserFields } from './getBaseUserFields'; +import { getBaseUserFields } from '@rocket.chat/rest-typings'; type UserFields = { [k: string]: number; From 1b375c7a9f993f2501aa42366e9ebe6080cc3d40 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 18 Mar 2025 21:42:50 +0530 Subject: [PATCH 09/15] refactor --- ee/apps/ddp-streamer/src/DDPStreamer.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ee/apps/ddp-streamer/src/DDPStreamer.ts b/ee/apps/ddp-streamer/src/DDPStreamer.ts index 4ff366a523ef5..69a589e67c4bc 100644 --- a/ee/apps/ddp-streamer/src/DDPStreamer.ts +++ b/ee/apps/ddp-streamer/src/DDPStreamer.ts @@ -126,9 +126,8 @@ export class DDPStreamer extends ServiceClass { }); async function sendUserData(client: Client, userId: string) { - // TODO figure out what fields to send. maybe to to export function getBaseUserFields to a package const loggedUser = await Users.findOneById(userId, { - projection: { ...getBaseUserFields(), 'services.totp.enabled': 1, 'services.email2fa.enabled': 1 }, + projection: { ...getBaseUserFields(true) }, }); if (!loggedUser) { return; From fd3fc828efc0734654986daca85a2905c14d40f4 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 18 Mar 2025 21:43:22 +0530 Subject: [PATCH 10/15] refactor --- apps/meteor/app/authentication/server/startup/index.js | 5 +---- .../app/utils/server/functions/getDefaultUserFields.ts | 4 +--- packages/rest-typings/src/helpers/getBaseUserFields.ts | 3 ++- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 24d5e0488237b..2a8364692ecc2 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -40,10 +40,7 @@ Accounts.config({ * * we are removing the status here because meteor send 'offline' */ -Object.assign( - Accounts._defaultPublishFields.projection, - (({ status, ...rest }) => rest)({ ...getBaseUserFields(), 'services.totp.enabled': 1, 'services.email2fa.enabled': 1 }), -); +Object.assign(Accounts._defaultPublishFields.projection, (({ status, ...rest }) => rest)({ ...getBaseUserFields(true) })); Meteor.startup(() => { settings.watchMultiple(['Accounts_LoginExpiration', 'Site_Name', 'From_Email'], () => { diff --git a/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts b/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts index e5ca39688f952..8515aa63e625d 100644 --- a/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts +++ b/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts @@ -5,10 +5,8 @@ type UserFields = { }; export const getDefaultUserFields = (): UserFields => ({ - ...getBaseUserFields(), + ...getBaseUserFields(true), 'services.github': 1, 'services.gitlab': 1, 'services.password.bcrypt': 1, - 'services.totp.enabled': 1, - 'services.email2fa.enabled': 1, }); diff --git a/packages/rest-typings/src/helpers/getBaseUserFields.ts b/packages/rest-typings/src/helpers/getBaseUserFields.ts index 5e2a3bf2b4d73..a366f95a2fe54 100644 --- a/packages/rest-typings/src/helpers/getBaseUserFields.ts +++ b/packages/rest-typings/src/helpers/getBaseUserFields.ts @@ -2,7 +2,7 @@ type UserFields = { [k: string]: number; }; -export const getBaseUserFields = (): UserFields => ({ +export const getBaseUserFields = (allowServiceKeys = false): UserFields => ({ 'name': 1, 'username': 1, 'nickname': 1, @@ -31,4 +31,5 @@ export const getBaseUserFields = (): UserFields => ({ 'avatarETag': 1, 'extension': 1, 'openBusinessHours': 1, + ...(allowServiceKeys && { 'services.totp.enabled': 1, 'services.email2fa.enabled': 1 }), }); From a92032d7d9c460f8d7672dcfd79bd672f01f26f8 Mon Sep 17 00:00:00 2001 From: Yash Rajpal <58601732+yash-rajpal@users.noreply.github.com> Date: Tue, 18 Mar 2025 22:42:29 +0530 Subject: [PATCH 11/15] Update apps/meteor/app/authentication/server/startup/index.js Co-authored-by: Pierre Lehnen <55164754+pierre-lehnen-rc@users.noreply.github.com> --- apps/meteor/app/authentication/server/startup/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 2a8364692ecc2..1e1125b91a763 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -40,7 +40,7 @@ Accounts.config({ * * we are removing the status here because meteor send 'offline' */ -Object.assign(Accounts._defaultPublishFields.projection, (({ status, ...rest }) => rest)({ ...getBaseUserFields(true) })); +Object.assign(Accounts._defaultPublishFields.projection, (({ status, ...rest }) => rest)(getBaseUserFields(true))); Meteor.startup(() => { settings.watchMultiple(['Accounts_LoginExpiration', 'Site_Name', 'From_Email'], () => { From 82b0c48eba0896a6f026be0449b95a7c1227206f Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Wed, 19 Mar 2025 22:48:51 +0530 Subject: [PATCH 12/15] don't move getUserFields function to package --- apps/meteor/app/api/server/v1/misc.ts | 2 +- apps/meteor/app/authentication/server/startup/index.js | 2 +- .../meteor/app/utils/server/functions}/getBaseUserFields.ts | 0 apps/meteor/app/utils/server/functions/getDefaultUserFields.ts | 2 +- ee/apps/ddp-streamer/src/DDPStreamer.ts | 2 +- packages/rest-typings/src/index.ts | 1 - 6 files changed, 4 insertions(+), 5 deletions(-) rename {packages/rest-typings/src/helpers => apps/meteor/app/utils/server/functions}/getBaseUserFields.ts (100%) diff --git a/apps/meteor/app/api/server/v1/misc.ts b/apps/meteor/app/api/server/v1/misc.ts index cb934aa40e8bf..bf273b75070dc 100644 --- a/apps/meteor/app/api/server/v1/misc.ts +++ b/apps/meteor/app/api/server/v1/misc.ts @@ -10,7 +10,6 @@ import { isMethodCallAnonProps, isFingerprintProps, isMeteorCall, - getBaseUserFields, } from '@rocket.chat/rest-typings'; import { escapeHTML } from '@rocket.chat/string-helpers'; import EJSON from 'ejson'; @@ -26,6 +25,7 @@ import { getLogs } from '../../../../server/stream/stdout'; import { passwordPolicy } from '../../../lib/server'; import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import { settings } from '../../../settings/server'; +import { getBaseUserFields } from '../../../utils/server/functions/getBaseUserFields'; import { isSMTPConfigured } from '../../../utils/server/functions/isSMTPConfigured'; import { getURL } from '../../../utils/server/getURL'; import { API } from '../api'; diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 1e1125b91a763..345aa01e688ea 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -1,7 +1,6 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; import { User } from '@rocket.chat/core-services'; import { Roles, Settings, Users } from '@rocket.chat/models'; -import { getBaseUserFields } from '@rocket.chat/rest-typings'; import { escapeRegExp, escapeHTML } from '@rocket.chat/string-helpers'; import { getLoginExpirationInDays } from '@rocket.chat/tools'; import { Accounts } from 'meteor/accounts-base'; @@ -24,6 +23,7 @@ import { setAvatarFromServiceWithValidation } from '../../../lib/server/function import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import * as Mailer from '../../../mailer/server/api'; import { settings } from '../../../settings/server'; +import { getBaseUserFields } from '../../../utils/server/functions/getBaseUserFields'; import { safeGetMeteorUser } from '../../../utils/server/functions/safeGetMeteorUser'; import { isValidAttemptByUser, isValidLoginAttemptByIp } from '../lib/restrictLoginAttempts'; diff --git a/packages/rest-typings/src/helpers/getBaseUserFields.ts b/apps/meteor/app/utils/server/functions/getBaseUserFields.ts similarity index 100% rename from packages/rest-typings/src/helpers/getBaseUserFields.ts rename to apps/meteor/app/utils/server/functions/getBaseUserFields.ts diff --git a/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts b/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts index 8515aa63e625d..c9d7cb0fc8945 100644 --- a/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts +++ b/apps/meteor/app/utils/server/functions/getDefaultUserFields.ts @@ -1,4 +1,4 @@ -import { getBaseUserFields } from '@rocket.chat/rest-typings'; +import { getBaseUserFields } from './getBaseUserFields'; type UserFields = { [k: string]: number; diff --git a/ee/apps/ddp-streamer/src/DDPStreamer.ts b/ee/apps/ddp-streamer/src/DDPStreamer.ts index 69a589e67c4bc..a44f815ad12f2 100644 --- a/ee/apps/ddp-streamer/src/DDPStreamer.ts +++ b/ee/apps/ddp-streamer/src/DDPStreamer.ts @@ -3,7 +3,6 @@ import crypto from 'crypto'; import { MeteorService, Presence, ServiceClass } from '@rocket.chat/core-services'; import { InstanceStatus } from '@rocket.chat/instance-status'; import { Users } from '@rocket.chat/models'; -import { getBaseUserFields } from '@rocket.chat/rest-typings'; import polka from 'polka'; import { throttle } from 'underscore'; import WebSocket from 'ws'; @@ -13,6 +12,7 @@ import { events, server } from './configureServer'; import { DDP_EVENTS } from './constants'; import { Autoupdate } from './lib/Autoupdate'; import { proxy } from './proxy'; +import { getBaseUserFields } from '../../../../apps/meteor/app/utils/server/functions/getBaseUserFields'; import { ListenersModule } from '../../../../apps/meteor/server/modules/listeners/listeners.module'; import type { NotificationsModule } from '../../../../apps/meteor/server/modules/notifications/notifications.module'; import { StreamerCentral } from '../../../../apps/meteor/server/modules/streamer/streamer.module'; diff --git a/packages/rest-typings/src/index.ts b/packages/rest-typings/src/index.ts index b881358a22664..9c466272f63bb 100644 --- a/packages/rest-typings/src/index.ts +++ b/packages/rest-typings/src/index.ts @@ -241,7 +241,6 @@ export * from './v1/oauthapps/UpdateOAuthAppParamsPOST'; export * from './v1/oauthapps/OAuthAppsGetParamsGET'; export * from './v1/oauthapps/OAuthAppsAddParamsPOST'; export * from './v1/oauthapps/DeleteOAuthAppParamsDELETE'; -export * from './helpers/getBaseUserFields'; export * from './helpers/PaginatedRequest'; export * from './helpers/PaginatedResult'; export * from './helpers/ReplacePlaceholders'; From 4f323af1b909d801fefcca62cb49d2fd20cd2eef Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Wed, 19 Mar 2025 22:50:19 +0530 Subject: [PATCH 13/15] oops --- ee/apps/ddp-streamer/src/DDPStreamer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/apps/ddp-streamer/src/DDPStreamer.ts b/ee/apps/ddp-streamer/src/DDPStreamer.ts index a44f815ad12f2..28e23d7dc5ba6 100644 --- a/ee/apps/ddp-streamer/src/DDPStreamer.ts +++ b/ee/apps/ddp-streamer/src/DDPStreamer.ts @@ -127,7 +127,7 @@ export class DDPStreamer extends ServiceClass { async function sendUserData(client: Client, userId: string) { const loggedUser = await Users.findOneById(userId, { - projection: { ...getBaseUserFields(true) }, + projection: getBaseUserFields(true), }); if (!loggedUser) { return; From faa89acaaeca794b8e99d3f2a6771dae02d94ba6 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 20 Mar 2025 15:09:07 -0300 Subject: [PATCH 14/15] review --- ee/apps/ddp-streamer/src/DDPStreamer.ts | 35 +++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/ee/apps/ddp-streamer/src/DDPStreamer.ts b/ee/apps/ddp-streamer/src/DDPStreamer.ts index 28e23d7dc5ba6..a56fd0bee3d9d 100644 --- a/ee/apps/ddp-streamer/src/DDPStreamer.ts +++ b/ee/apps/ddp-streamer/src/DDPStreamer.ts @@ -12,7 +12,6 @@ import { events, server } from './configureServer'; import { DDP_EVENTS } from './constants'; import { Autoupdate } from './lib/Autoupdate'; import { proxy } from './proxy'; -import { getBaseUserFields } from '../../../../apps/meteor/app/utils/server/functions/getBaseUserFields'; import { ListenersModule } from '../../../../apps/meteor/server/modules/listeners/listeners.module'; import type { NotificationsModule } from '../../../../apps/meteor/server/modules/notifications/notifications.module'; import { StreamerCentral } from '../../../../apps/meteor/server/modules/streamer/streamer.module'; @@ -126,8 +125,40 @@ export class DDPStreamer extends ServiceClass { }); async function sendUserData(client: Client, userId: string) { + // TODO figure out what fields to send. maybe to to export function getBaseUserFields to a package const loggedUser = await Users.findOneById(userId, { - projection: getBaseUserFields(true), + projection: { + 'name': 1, + 'username': 1, + 'nickname': 1, + 'emails': 1, + 'status': 1, + 'statusDefault': 1, + 'statusText': 1, + 'statusConnection': 1, + 'bio': 1, + 'avatarOrigin': 1, + 'utcOffset': 1, + 'language': 1, + 'settings': 1, + 'enableAutoAway': 1, + 'idleTimeLimit': 1, + 'roles': 1, + 'active': 1, + 'defaultRoom': 1, + 'customFields': 1, + 'requirePasswordChange': 1, + 'requirePasswordChangeReason': 1, + 'statusLivechat': 1, + 'banners': 1, + 'oauth.authorizedClients': 1, + '_updatedAt': 1, + 'avatarETag': 1, + 'extension': 1, + 'openBusinessHours': 1, + 'services.totp.enabled': 1, + 'services.email2fa.enabled': 1 + }, }); if (!loggedUser) { return; From d06ded3c7b2762741c9f3ccc391ca4a908e3eb08 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 20 Mar 2025 16:05:57 -0300 Subject: [PATCH 15/15] lint --- ee/apps/ddp-streamer/src/DDPStreamer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/apps/ddp-streamer/src/DDPStreamer.ts b/ee/apps/ddp-streamer/src/DDPStreamer.ts index a56fd0bee3d9d..1a6a1046ae776 100644 --- a/ee/apps/ddp-streamer/src/DDPStreamer.ts +++ b/ee/apps/ddp-streamer/src/DDPStreamer.ts @@ -157,7 +157,7 @@ export class DDPStreamer extends ServiceClass { 'extension': 1, 'openBusinessHours': 1, 'services.totp.enabled': 1, - 'services.email2fa.enabled': 1 + 'services.email2fa.enabled': 1, }, }); if (!loggedUser) {