diff --git a/.changeset/bump-patch-1718743154258.md b/.changeset/bump-patch-1718743154258.md new file mode 100644 index 000000000000..e1eaa7980afb --- /dev/null +++ b/.changeset/bump-patch-1718743154258.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Bump @rocket.chat/meteor version. diff --git a/.changeset/dry-shoes-tap.md b/.changeset/dry-shoes-tap.md new file mode 100644 index 000000000000..f5abf51c0df0 --- /dev/null +++ b/.changeset/dry-shoes-tap.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixes the supported versions problem, where in most cases the data chosen was the oldest diff --git a/.changeset/nervous-wolves-collect.md b/.changeset/nervous-wolves-collect.md new file mode 100644 index 000000000000..e32377f54179 --- /dev/null +++ b/.changeset/nervous-wolves-collect.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes the issue not allowing users without edit-room-retention-policy permission try to edit the room with the retention policy enabled diff --git a/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsChooseLatest.ts b/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsChooseLatest.ts index 3493401144cf..32753ba00429 100644 --- a/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsChooseLatest.ts +++ b/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsChooseLatest.ts @@ -2,7 +2,7 @@ import type { SignedSupportedVersions } from '@rocket.chat/server-cloud-communic export const supportedVersionsChooseLatest = async (...tokens: (SignedSupportedVersions | undefined)[]) => { const [token] = (tokens.filter((r) => r?.timestamp != null) as SignedSupportedVersions[]).sort((a, b) => { - return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(); + return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(); }); return token; diff --git a/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsToken.ts b/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsToken.ts index 473acef88c29..a543c0681f38 100644 --- a/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsToken.ts +++ b/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsToken.ts @@ -62,6 +62,7 @@ const cacheValueInSettings = ( reset: () => Promise; } => { const reset = async () => { + SystemLogger.debug(`Resetting cached value ${key} in settings`); const value = await fn(); await Settings.updateValueById(key, value); @@ -134,6 +135,31 @@ const getSupportedVersionsToken = async () => { (response.success && response.result) || undefined, ); + SystemLogger.debug({ + msg: 'Supported versions', + supportedVersionsFromBuild: supportedVersionsFromBuild.timestamp, + versionsFromLicense: versionsFromLicense?.supportedVersions?.timestamp, + response: response.success && response.result?.timestamp, + }); + + switch (supportedVersions) { + case supportedVersionsFromBuild: + SystemLogger.info({ + msg: 'Using supported versions from build', + }); + break; + case versionsFromLicense?.supportedVersions: + SystemLogger.info({ + msg: 'Using supported versions from license', + }); + break; + case response.success && response.result: + SystemLogger.info({ + msg: 'Using supported versions from cloud', + }); + break; + } + await buildVersionUpdateMessage(supportedVersions?.versions); return supportedVersions?.signed; diff --git a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomInitialValues.ts b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomInitialValues.ts index 128f6c3c66f8..1cb76cadd335 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomInitialValues.ts +++ b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomInitialValues.ts @@ -1,4 +1,5 @@ import type { IRoomWithRetentionPolicy } from '@rocket.chat/core-typings'; +import { usePermission } from '@rocket.chat/ui-contexts'; import { useMemo } from 'react'; import { roomCoordinator } from '../../../../../lib/rooms/roomCoordinator'; @@ -6,6 +7,8 @@ import { useRetentionPolicy } from '../../../hooks/useRetentionPolicy'; export const useEditRoomInitialValues = (room: IRoomWithRetentionPolicy) => { const retentionPolicy = useRetentionPolicy(room); + const canEditRoomRetentionPolicy = usePermission('edit-room-retention-policy', room._id); + const { t, ro, archived, topic, description, announcement, joinCodeRequired, sysMes, encrypted, retention, reactWhenReadOnly } = room; return useMemo( @@ -24,13 +27,14 @@ export const useEditRoomInitialValues = (room: IRoomWithRetentionPolicy) => { systemMessages: Array.isArray(sysMes) ? sysMes : [], hideSysMes: Array.isArray(sysMes) ? !!sysMes?.length : !!sysMes, encrypted, - ...(retentionPolicy?.enabled && { - retentionEnabled: retention?.enabled ?? retentionPolicy.isActive, - retentionOverrideGlobal: !!retention?.overrideGlobal, - retentionMaxAge: retention?.maxAge ?? retentionPolicy.maxAge, - retentionExcludePinned: retention?.excludePinned ?? retentionPolicy.excludePinned, - retentionFilesOnly: retention?.filesOnly ?? retentionPolicy.filesOnly, - }), + ...(canEditRoomRetentionPolicy && + retentionPolicy?.enabled && { + retentionEnabled: retention?.enabled ?? retentionPolicy.isActive, + retentionOverrideGlobal: !!retention?.overrideGlobal, + retentionMaxAge: retention?.maxAge ?? retentionPolicy.maxAge, + retentionExcludePinned: retention?.excludePinned ?? retentionPolicy.excludePinned, + retentionFilesOnly: retention?.filesOnly ?? retentionPolicy.filesOnly, + }), }), [ announcement, @@ -46,6 +50,7 @@ export const useEditRoomInitialValues = (room: IRoomWithRetentionPolicy) => { topic, encrypted, reactWhenReadOnly, + canEditRoomRetentionPolicy, ], ); }; diff --git a/apps/meteor/jest.config.ts b/apps/meteor/jest.config.ts index adbd8c26344f..72538cf14d16 100644 --- a/apps/meteor/jest.config.ts +++ b/apps/meteor/jest.config.ts @@ -33,6 +33,7 @@ const config: Config = { '/app/livechat/server/business-hour/**/*.spec.ts?(x)', '/app/livechat/server/api/**/*.spec.ts', '/ee/app/authorization/server/validateUserRoles.spec.ts', + '/app/cloud/server/functions/supportedVersionsToken/**.spec.ts', ], transformIgnorePatterns: ['!/node_modules/jose'], errorOnDeprecated: true, diff --git a/apps/meteor/packages/rocketchat-version/plugin/compile-version.js b/apps/meteor/packages/rocketchat-version/plugin/compile-version.js index e737f07663f3..8750c6851202 100644 --- a/apps/meteor/packages/rocketchat-version/plugin/compile-version.js +++ b/apps/meteor/packages/rocketchat-version/plugin/compile-version.js @@ -21,10 +21,10 @@ class VersionCompiler { function handleError(err) { console.error(err); // TODO remove this when we are ready to fail - // if (process.env.NODE_ENV !== 'development') { - // reject(err); - // return; - // } + if (process.env.NODE_ENV !== 'development') { + reject(err); + return; + } resolve({}); } @@ -34,11 +34,24 @@ class VersionCompiler { response.on('data', function (chunk) { data += chunk; }); - response.on('end', function () { + response.on('end', async function () { const supportedVersions = JSON.parse(data); if (!supportedVersions?.signed) { return handleError(new Error(`Invalid supportedVersions result:\n URL: ${url} \n RESULT: ${data}`)); } + + // check if timestamp is inside 1 hour within build + if (Math.abs(new Date().getTime() - new Date(supportedVersions.timestamp).getTime()) > 1000 * 60 * 60) { + return handleError(new Error(`Invalid supportedVersions timestamp:\n URL: ${url} \n RESULT: ${data}`)); + } + + for await (const version of supportedVersions.versions) { + // check if expiration is after the first rocket.chat release + if (new Date(version.expiration) < new Date('2019-04-01T00:00:00.000Z')) { + return handleError(new Error(`Invalid supportedVersions expiration:\n URL: ${url} \n RESULT: ${data}`)); + } + } + resolve(supportedVersions); }); response.on('error', function (err) { diff --git a/apps/meteor/tests/e2e/retention-policy.spec.ts b/apps/meteor/tests/e2e/retention-policy.spec.ts index ba9ec90eff3b..8a808aae579f 100644 --- a/apps/meteor/tests/e2e/retention-policy.spec.ts +++ b/apps/meteor/tests/e2e/retention-policy.spec.ts @@ -85,16 +85,31 @@ test.describe.serial('retention-policy', () => { await expect(poHomeChannel.tabs.room.pruneAccordion).toBeVisible(); }); - test('should not show prune section in edit channel for users without permission', async ({ browser }) => { - const { page } = await createAuxContext(browser, Users.user1); - const auxContext = { page, poHomeChannel: new HomeChannel(page) }; - await auxContext.poHomeChannel.sidenav.openChat(targetChannel); - await auxContext.poHomeChannel.tabs.btnRoomInfo.click(); - await auxContext.poHomeChannel.tabs.room.btnEdit.click(); + test.describe('edit-room-retention-policy permission', async () => { + test('should not show prune section in edit channel for users without permission', async ({ browser }) => { + const { page } = await createAuxContext(browser, Users.user1); + const auxContext = { page, poHomeChannel: new HomeChannel(page) }; + await auxContext.poHomeChannel.sidenav.openChat(targetChannel); + await auxContext.poHomeChannel.tabs.btnRoomInfo.click(); + await auxContext.poHomeChannel.tabs.room.btnEdit.click(); + + await expect(poHomeChannel.tabs.room.pruneAccordion).not.toBeVisible(); + await auxContext.page.close(); + }); - await expect(poHomeChannel.tabs.room.pruneAccordion).not.toBeVisible(); - await auxContext.page.close(); - }) + test('users without permission should be able to edit the channel', async ({ browser }) => { + const { page } = await createAuxContext(browser, Users.user1); + const auxContext = { page, poHomeChannel: new HomeChannel(page) }; + await auxContext.poHomeChannel.sidenav.openChat(targetChannel); + await auxContext.poHomeChannel.tabs.btnRoomInfo.click(); + await auxContext.poHomeChannel.tabs.room.btnEdit.click(); + await auxContext.poHomeChannel.tabs.room.checkboxReadOnly.check(); + await auxContext.poHomeChannel.tabs.room.btnSave.click(); + + await expect(auxContext.poHomeChannel.getSystemMessageByText('set room to read only')).toBeVisible(); + await auxContext.page.close(); + }); + }); test.describe('retention policy applies enabled by default', () => { test.beforeAll(async ({ api }) => { diff --git a/yarn.lock b/yarn.lock index 2688eb2a0cf8..55ea08d561de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8795,10 +8795,10 @@ __metadata: "@rocket.chat/icons": "*" "@rocket.chat/prettier-config": "*" "@rocket.chat/styled": "*" - "@rocket.chat/ui-avatar": 3.0.0 - "@rocket.chat/ui-contexts": 7.0.0 + "@rocket.chat/ui-avatar": 3.0.1 + "@rocket.chat/ui-contexts": 7.0.1 "@rocket.chat/ui-kit": 0.34.0 - "@rocket.chat/ui-video-conf": 7.0.0 + "@rocket.chat/ui-video-conf": 7.0.1 "@tanstack/react-query": "*" react: "*" react-dom: "*" @@ -8887,8 +8887,8 @@ __metadata: "@rocket.chat/fuselage-tokens": "*" "@rocket.chat/message-parser": 0.31.29 "@rocket.chat/styled": "*" - "@rocket.chat/ui-client": 7.0.0 - "@rocket.chat/ui-contexts": 7.0.0 + "@rocket.chat/ui-client": 7.0.1 + "@rocket.chat/ui-contexts": 7.0.1 katex: "*" react: "*" languageName: unknown @@ -10106,7 +10106,7 @@ __metadata: typescript: ~5.3.3 peerDependencies: "@rocket.chat/fuselage": "*" - "@rocket.chat/ui-contexts": 7.0.0 + "@rocket.chat/ui-contexts": 7.0.1 react: ~17.0.2 languageName: unknown linkType: soft @@ -10159,7 +10159,7 @@ __metadata: "@rocket.chat/fuselage": "*" "@rocket.chat/fuselage-hooks": "*" "@rocket.chat/icons": "*" - "@rocket.chat/ui-contexts": 7.0.0 + "@rocket.chat/ui-contexts": 7.0.1 react: ~17.0.2 languageName: unknown linkType: soft @@ -10335,8 +10335,8 @@ __metadata: "@rocket.chat/fuselage-hooks": "*" "@rocket.chat/icons": "*" "@rocket.chat/styled": "*" - "@rocket.chat/ui-avatar": 3.0.0 - "@rocket.chat/ui-contexts": 7.0.0 + "@rocket.chat/ui-avatar": 3.0.1 + "@rocket.chat/ui-contexts": 7.0.1 react: ^17.0.2 react-dom: ^17.0.2 languageName: unknown @@ -10426,7 +10426,7 @@ __metadata: peerDependencies: "@rocket.chat/layout": "*" "@rocket.chat/tools": 0.2.1 - "@rocket.chat/ui-contexts": 7.0.0 + "@rocket.chat/ui-contexts": 7.0.1 "@tanstack/react-query": "*" react: "*" react-hook-form: "*"