From 762b0bfe3f033bf368a1c91318ec5b63c2b81788 Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Thu, 30 Oct 2025 11:35:41 -0300 Subject: [PATCH 1/4] fix: settings cached collection keeping stale state after logout --- .../meteor/client/providers/SettingsProvider.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/meteor/client/providers/SettingsProvider.tsx b/apps/meteor/client/providers/SettingsProvider.tsx index 8010ee0e46a30..b4e82ac87cd78 100644 --- a/apps/meteor/client/providers/SettingsProvider.tsx +++ b/apps/meteor/client/providers/SettingsProvider.tsx @@ -4,7 +4,7 @@ import type { SettingsContextQuery, SettingsContextValue } from '@rocket.chat/ui import { SettingsContext, useAtLeastOnePermission, useMethod } from '@rocket.chat/ui-contexts'; import { useQueryClient } from '@tanstack/react-query'; import type { ReactNode } from 'react'; -import { useCallback, useMemo } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { PublicSettingsCachedStore, PrivateSettingsCachedStore } from '../cachedStores'; import { applyQueryOptions } from '../lib/cachedStores/applyQueryOptions'; @@ -15,6 +15,12 @@ type SettingsProviderProps = { children?: ReactNode; }; +const isPublicSettingsCollection = ( + collection: typeof PublicSettingsCachedStore | typeof PrivateSettingsCachedStore, +): collection is typeof PublicSettingsCachedStore => { + return collection === PublicSettingsCachedStore; +}; + const SettingsProvider = ({ children }: SettingsProviderProps) => { const canManageSettings = useAtLeastOnePermission(settingsManagementPermissions); @@ -22,6 +28,14 @@ const SettingsProvider = ({ children }: SettingsProviderProps) => { const isLoading = !cachedCollection.useReady(); + useEffect(() => { + if (isPublicSettingsCollection(cachedCollection)) { + return; + } + + cachedCollection.listen(); + }, [cachedCollection]); + if (isLoading) { throw (async () => { await cachedCollection.init(); From dc9af1c19f309bd28a20806eb53af5dc681fe355 Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Thu, 30 Oct 2025 11:38:21 -0300 Subject: [PATCH 2/4] test: e2e tests for settings list --- .../tests/e2e/administration-settings.spec.ts | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/apps/meteor/tests/e2e/administration-settings.spec.ts b/apps/meteor/tests/e2e/administration-settings.spec.ts index 24ffa09d34c1c..7c45b14277ba3 100644 --- a/apps/meteor/tests/e2e/administration-settings.spec.ts +++ b/apps/meteor/tests/e2e/administration-settings.spec.ts @@ -1,5 +1,7 @@ import { Users } from './fixtures/userStates'; -import { Admin } from './page-objects'; +import { Admin, AdminSectionsHref } from './page-objects'; +import { HomeSidenav } from './page-objects/fragments'; +import { LoginPage } from './page-objects/login'; import { getSettingValueById, setSettingValueById } from './utils'; import { test, expect } from './utils/test'; @@ -7,9 +9,38 @@ test.use({ storageState: Users.admin.state }); test.describe.parallel('administration-settings', () => { let poAdmin: Admin; + let poHomeSidenav: HomeSidenav; + let poLoginPage: LoginPage; test.beforeEach(async ({ page }) => { poAdmin = new Admin(page); + poHomeSidenav = new HomeSidenav(page); + poLoginPage = new LoginPage(page); + }); + + test.describe('Settings Page', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/admin/settings'); + }); + + test('should display settings list', async ({ page }) => { + await test.step('should list settings on load', async () => { + await expect(page.getByText('No results found')).not.toBeVisible(); + }); + + await test.step('should list settings after logout and login', async () => { + await poAdmin.btnClose.click(); + await poHomeSidenav.logout(); + + await poLoginPage.loginByUserState(Users.admin); + + await poHomeSidenav.openAdministrationByLabel('Workspace'); + const settingsButton = await poAdmin.adminSectionButton(AdminSectionsHref.Settings); + await settingsButton.click(); + + await expect(page.getByText('No results found')).not.toBeVisible(); + }); + }); }); test.describe('General', () => { From 63463295f401f6376668414cc1f01c590db461aa Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Thu, 30 Oct 2025 11:59:16 -0300 Subject: [PATCH 3/4] chore: changeset Fixes administration settings page not listing the settings after logging out and back into the workspace --- .changeset/stupid-cameras-nail.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/stupid-cameras-nail.md diff --git a/.changeset/stupid-cameras-nail.md b/.changeset/stupid-cameras-nail.md new file mode 100644 index 0000000000000..db9d3067ed8b7 --- /dev/null +++ b/.changeset/stupid-cameras-nail.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixes administration settings page not listing the settings after logging out and back into the workspace From 4205d46a9b7ea0a76f4497134a3a7ffd93dad673 Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Fri, 31 Oct 2025 14:51:12 -0300 Subject: [PATCH 4/4] refactor: call init and listen together --- .../providers/AuthorizationProvider.tsx | 7 ++----- .../client/providers/SettingsProvider.tsx | 21 ++++++------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/apps/meteor/client/providers/AuthorizationProvider.tsx b/apps/meteor/client/providers/AuthorizationProvider.tsx index 542c90f3ca366..52e0d6e37decf 100644 --- a/apps/meteor/client/providers/AuthorizationProvider.tsx +++ b/apps/meteor/client/providers/AuthorizationProvider.tsx @@ -1,6 +1,6 @@ import { AuthorizationContext, useUserId } from '@rocket.chat/ui-contexts'; import type { ReactNode } from 'react'; -import { useEffect, useMemo } from 'react'; +import { useMemo } from 'react'; import { hasPermission, hasAtLeastOnePermission, hasAllPermission, hasRole } from '../../app/authorization/client'; import { PermissionsCachedStore } from '../cachedStores'; @@ -12,14 +12,11 @@ type AuthorizationProviderProps = { }; const AuthorizationProvider = ({ children }: AuthorizationProviderProps) => { - useEffect(() => { - PermissionsCachedStore.listen(); - }, []); - const isLoading = !PermissionsCachedStore.useReady(); if (isLoading) { throw (async () => { + PermissionsCachedStore.listen(); await PermissionsCachedStore.init(); })(); } diff --git a/apps/meteor/client/providers/SettingsProvider.tsx b/apps/meteor/client/providers/SettingsProvider.tsx index b4e82ac87cd78..bb9c4e9128257 100644 --- a/apps/meteor/client/providers/SettingsProvider.tsx +++ b/apps/meteor/client/providers/SettingsProvider.tsx @@ -4,9 +4,10 @@ import type { SettingsContextQuery, SettingsContextValue } from '@rocket.chat/ui import { SettingsContext, useAtLeastOnePermission, useMethod } from '@rocket.chat/ui-contexts'; import { useQueryClient } from '@tanstack/react-query'; import type { ReactNode } from 'react'; -import { useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { PublicSettingsCachedStore, PrivateSettingsCachedStore } from '../cachedStores'; +import { PrivateCachedStore } from '../lib/cachedStores/CachedStore'; import { applyQueryOptions } from '../lib/cachedStores/applyQueryOptions'; const settingsManagementPermissions = ['view-privileged-setting', 'edit-privileged-setting', 'manage-selected-settings']; @@ -15,12 +16,6 @@ type SettingsProviderProps = { children?: ReactNode; }; -const isPublicSettingsCollection = ( - collection: typeof PublicSettingsCachedStore | typeof PrivateSettingsCachedStore, -): collection is typeof PublicSettingsCachedStore => { - return collection === PublicSettingsCachedStore; -}; - const SettingsProvider = ({ children }: SettingsProviderProps) => { const canManageSettings = useAtLeastOnePermission(settingsManagementPermissions); @@ -28,16 +23,12 @@ const SettingsProvider = ({ children }: SettingsProviderProps) => { const isLoading = !cachedCollection.useReady(); - useEffect(() => { - if (isPublicSettingsCollection(cachedCollection)) { - return; - } - - cachedCollection.listen(); - }, [cachedCollection]); - if (isLoading) { throw (async () => { + if (cachedCollection instanceof PrivateCachedStore) { + cachedCollection.listen(); + } + await cachedCollection.init(); })(); }