From 97a2cb82421b39be7c95c618161e58ab50b129d4 Mon Sep 17 00:00:00 2001 From: dougfabris Date: Fri, 22 Nov 2024 20:34:51 -0300 Subject: [PATCH] fix: `Setting` not considering license active modules --- .../views/admin/EditableSettingsContext.ts | 6 +++++- .../admin/settings/EditableSettingsProvider.tsx | 10 +++++++--- .../views/admin/settings/Setting/Setting.tsx | 16 +++++++++++++--- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/apps/meteor/client/views/admin/EditableSettingsContext.ts b/apps/meteor/client/views/admin/EditableSettingsContext.ts index 24c09cde2f3b..f54f08b7c228 100644 --- a/apps/meteor/client/views/admin/EditableSettingsContext.ts +++ b/apps/meteor/client/views/admin/EditableSettingsContext.ts @@ -1,4 +1,4 @@ -import type { ISettingBase, ISettingColor, ISetting } from '@rocket.chat/core-typings'; +import type { ISettingBase, ISettingColor, ISetting, LicenseModule } from '@rocket.chat/core-typings'; import type { SettingsContextQuery } from '@rocket.chat/ui-contexts'; import { createContext, useContext, useMemo } from 'react'; import { useSyncExternalStore } from 'use-sync-external-store/shim'; @@ -29,6 +29,7 @@ export type EditableSettingsContextValue = { ) => [subscribe: (onStoreChange: () => void) => () => void, getSnapshot: () => ISetting['_id'][]]; readonly dispatch: (changes: Partial[]) => void; readonly isEnterprise: boolean; + readonly activeModules: LicenseModule[]; }; export const EditableSettingsContext = createContext({ @@ -38,10 +39,13 @@ export const EditableSettingsContext = createContext [(): (() => void) => (): void => undefined, (): ISetting['_id'][] => []], dispatch: () => undefined, isEnterprise: false, + activeModules: [], }); export const useIsEnterprise = (): boolean => useContext(EditableSettingsContext).isEnterprise; +export const useLicenseActiveModules = () => useContext(EditableSettingsContext).activeModules; + export const useEditableSetting = (_id: ISetting['_id']): EditableSetting | undefined => { const { queryEditableSetting } = useContext(EditableSettingsContext); diff --git a/apps/meteor/client/views/admin/settings/EditableSettingsProvider.tsx b/apps/meteor/client/views/admin/settings/EditableSettingsProvider.tsx index be33c4617bf3..68e859aa9379 100644 --- a/apps/meteor/client/views/admin/settings/EditableSettingsProvider.tsx +++ b/apps/meteor/client/views/admin/settings/EditableSettingsProvider.tsx @@ -8,7 +8,7 @@ import type { FilterOperators } from 'mongodb'; import type { MutableRefObject, ReactNode } from 'react'; import React, { useEffect, useMemo, useRef } from 'react'; -import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; +import { useLicenseBase } from '../../../hooks/useLicense'; import { createReactiveSubscriptionFactory } from '../../../lib/createReactiveSubscriptionFactory'; import type { EditableSetting, EditableSettingsContextValue } from '../EditableSettingsContext'; import { EditableSettingsContext } from '../EditableSettingsContext'; @@ -193,9 +193,12 @@ const EditableSettingsProvider = ({ children, query = defaultQuery, omit = defau Tracker.flush(); }); - const { data } = useIsEnterprise(); + const { data } = useLicenseBase({ + select: (data) => ({ isEnterprise: Boolean(data?.license.license), activeModules: data?.license.activeModules }), + }); const isEnterprise = data?.isEnterprise ?? false; + const activeModules = useMemo(() => data?.activeModules ?? [], [data]); const contextValue = useMemo( () => ({ @@ -205,8 +208,9 @@ const EditableSettingsProvider = ({ children, query = defaultQuery, omit = defau queryGroupTabs, dispatch, isEnterprise, + activeModules, }), - [queryEditableSetting, queryEditableSettings, queryGroupSections, queryGroupTabs, dispatch, isEnterprise], + [queryEditableSetting, queryEditableSettings, queryGroupSections, queryGroupTabs, dispatch, isEnterprise, activeModules], ); return ; diff --git a/apps/meteor/client/views/admin/settings/Setting/Setting.tsx b/apps/meteor/client/views/admin/settings/Setting/Setting.tsx index 9e74f2e36b75..7511c7c56bd3 100644 --- a/apps/meteor/client/views/admin/settings/Setting/Setting.tsx +++ b/apps/meteor/client/views/admin/settings/Setting/Setting.tsx @@ -1,4 +1,4 @@ -import type { ISettingColor, SettingEditor, SettingValue } from '@rocket.chat/core-typings'; +import type { ISettingColor, LicenseModule, SettingEditor, SettingValue } from '@rocket.chat/core-typings'; import { isSettingColor, isSetting } from '@rocket.chat/core-typings'; import { Box, Button, Tag } from '@rocket.chat/fuselage'; import { useDebouncedCallback } from '@rocket.chat/fuselage-hooks'; @@ -9,7 +9,7 @@ import { useTranslation } from 'react-i18next'; import MemoizedSetting from './MemoizedSetting'; import MarkdownText from '../../../../components/MarkdownText'; -import { useEditableSetting, useEditableSettingsDispatch, useIsEnterprise } from '../../EditableSettingsContext'; +import { useEditableSetting, useEditableSettingsDispatch, useIsEnterprise, useLicenseActiveModules } from '../../EditableSettingsContext'; type SettingProps = { className?: string; @@ -21,6 +21,7 @@ function Setting({ className = undefined, settingId, sectionChanged }: SettingPr const setting = useEditableSetting(settingId); const persistedSetting = useSettingStructure(settingId); const isEnterprise = useIsEnterprise(); + const activeModules = useLicenseActiveModules(); if (!setting || !persistedSetting) { throw new Error(`Setting ${settingId} not found`); @@ -105,12 +106,21 @@ function Setting({ className = undefined, settingId, sectionChanged }: SettingPr ) : undefined, [i18n, i18nDescription, t], ); + const callout = useMemo( () => alert && , [alert, i18n, t], ); - const shouldDisableEnterprise = setting.enterprise && !isEnterprise; + const hasSettingModule = useMemo(() => { + if (!setting?.modules) { + return false; + } + + return setting.modules.every((module) => activeModules.includes(module as LicenseModule)); + }, [activeModules, setting?.modules]); + + const shouldDisableEnterprise = setting.enterprise && !isEnterprise && !hasSettingModule; const PRICING_URL = 'https://go.rocket.chat/i/see-paid-plan-customize-homepage';