Skip to content
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
eeb1e54
fix: ensure user services object is loaded before loading is complete
yash-rajpal Feb 26, 2025
06ae4f7
add ui tests
yash-rajpal Feb 28, 2025
7b2b26e
fix unused var
yash-rajpal Feb 28, 2025
ce613d1
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
yash-rajpal Feb 28, 2025
4406b2f
refactor
yash-rajpal Mar 3, 2025
eaa1b58
add cs
yash-rajpal Mar 3, 2025
d6a3ef8
fix review
yash-rajpal Mar 3, 2025
e58a694
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
yash-rajpal Mar 5, 2025
376b317
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
scuciatto Mar 12, 2025
9f7a0b0
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
kodiakhq[bot] Mar 12, 2025
ad21e9d
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
kodiakhq[bot] Mar 12, 2025
d71a88d
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
kodiakhq[bot] Mar 12, 2025
1ec98ef
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
kodiakhq[bot] Mar 13, 2025
61c3e09
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
scuciatto Mar 13, 2025
df8bced
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
kodiakhq[bot] Mar 13, 2025
7103f72
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
scuciatto Mar 14, 2025
f11a2e3
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
yash-rajpal Mar 18, 2025
c909656
fix for microservices
yash-rajpal Mar 18, 2025
bbef593
remove getBaseUserFields from app
yash-rajpal Mar 18, 2025
1b375c7
refactor
yash-rajpal Mar 18, 2025
fd3fc82
refactor
yash-rajpal Mar 18, 2025
a92032d
Update apps/meteor/app/authentication/server/startup/index.js
yash-rajpal Mar 18, 2025
c88587e
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
yash-rajpal Mar 18, 2025
35c7ebf
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
scuciatto Mar 19, 2025
3c662ba
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
yash-rajpal Mar 19, 2025
93b03cd
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
yash-rajpal Mar 19, 2025
82b0c48
don't move getUserFields function to package
yash-rajpal Mar 19, 2025
4f323af
oops
yash-rajpal Mar 19, 2025
a1ffdfb
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
scuciatto Mar 19, 2025
d5f498b
Merge branch 'develop' into fix/2FA-mandatory-check-flashing
kodiakhq[bot] Mar 20, 2025
faa89ac
review
ggazzo Mar 20, 2025
d06ded3
lint
ggazzo Mar 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/chatty-kids-compare.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion apps/meteor/app/authentication/server/startup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)(getBaseUserFields(true)));

Meteor.startup(() => {
settings.watchMultiple(['Accounts_LoginExpiration', 'Site_Name', 'From_Email'], () => {
Expand Down
3 changes: 2 additions & 1 deletion apps/meteor/app/utils/server/functions/getBaseUserFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -31,4 +31,5 @@ export const getBaseUserFields = (): UserFields => ({
'avatarETag': 1,
'extension': 1,
'openBusinessHours': 1,
...(allowServiceKeys && { 'services.totp.enabled': 1, 'services.email2fa.enabled': 1 }),
});
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
2 changes: 1 addition & 1 deletion apps/meteor/server/startup/initialData.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ Meteor.startup(async () => {
emails: [
{
address: 'rocketchat.internal.admin.test@rocket.chat',
verified: false,
verified: true,
},
],
status: 'offline',
Expand Down
63 changes: 63 additions & 0 deletions apps/meteor/tests/e2e/enforce-2FA.spec.ts
Original file line number Diff line number Diff line change
@@ -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();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,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<void> {
await this.sidebarToolbar.getByRole('button', { name: 'Display', exact: true }).click();
await this.sidebarToolbar.getByRole('menuitemcheckbox', { name: mode }).click();
Expand Down
33 changes: 32 additions & 1 deletion ee/apps/ddp-streamer/src/DDPStreamer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,38 @@ 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: {
'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;
Expand Down