diff --git a/frontend/src/AppBuilder/CodeEditor/MultiLineCodeEditor.jsx b/frontend/src/AppBuilder/CodeEditor/MultiLineCodeEditor.jsx index f95baaa328..ef5a5dbd7d 100644 --- a/frontend/src/AppBuilder/CodeEditor/MultiLineCodeEditor.jsx +++ b/frontend/src/AppBuilder/CodeEditor/MultiLineCodeEditor.jsx @@ -7,6 +7,7 @@ import { keymap } from '@codemirror/view'; import { completionKeymap, acceptCompletion, autocompletion, completionStatus } from '@codemirror/autocomplete'; import { python } from '@codemirror/lang-python'; import { sql } from '@codemirror/lang-sql'; +import _ from 'lodash'; import { sass, sassCompletionSource } from '@codemirror/lang-sass'; import { okaidia } from '@uiw/codemirror-theme-okaidia'; import { githubLight } from '@uiw/codemirror-theme-github'; @@ -21,6 +22,7 @@ import useStore from '@/AppBuilder/_stores/store'; import { shallow } from 'zustand/shallow'; import { search, searchKeymap, searchPanelOpen } from '@codemirror/search'; import { handleSearchPanel, SearchBtn } from './SearchBox'; +import { isInsideParent } from './utils'; const langSupport = Object.freeze({ javascript: javascript(), @@ -51,8 +53,15 @@ const MultiLineCodeEditor = (props) => { renderCopilot, } = props; const replaceIdsWithName = useStore((state) => state.replaceIdsWithName, shallow); + const wrapperRef = useRef(null); const getSuggestions = useStore((state) => state.getSuggestions, shallow); + const getServerSideGlobalSuggestions = useStore((state) => state.getServerSideGlobalSuggestions, shallow); + const isInsideQueryPane = !!document.querySelector('.code-hinter-wrapper')?.closest('.query-details'); + const isInsideQueryManager = useMemo( + () => isInsideParent(wrapperRef?.current, 'query-manager'), + [wrapperRef.current] + ); const context = useContext(CodeHinterContext); @@ -100,9 +109,16 @@ const MultiLineCodeEditor = (props) => { const hints = getSuggestions(); + const serverHints = getServerSideGlobalSuggestions(isInsideQueryManager); + + const allHints = { + ...hints, + appHints: [...hints.appHints, ...serverHints], + }; + let JSLangHints = []; if (lang === 'javascript') { - JSLangHints = Object.keys(hints['jsHints']) + JSLangHints = Object.keys(allHints['jsHints']) .map((key) => { return hints['jsHints'][key]['methods'].map((hint) => ({ hint: hint, @@ -120,7 +136,7 @@ const MultiLineCodeEditor = (props) => { }); } - const appHints = hints['appHints']; + const appHints = allHints['appHints']; let autoSuggestionList = appHints.filter((suggestion) => { return suggestion.hint.includes(nearestSubstring); @@ -229,6 +245,7 @@ const MultiLineCodeEditor = (props) => {
diff --git a/frontend/src/AppBuilder/CodeEditor/PreviewBox.jsx b/frontend/src/AppBuilder/CodeEditor/PreviewBox.jsx index 6c28bdbb21..c123cb2b9c 100644 --- a/frontend/src/AppBuilder/CodeEditor/PreviewBox.jsx +++ b/frontend/src/AppBuilder/CodeEditor/PreviewBox.jsx @@ -96,6 +96,7 @@ export const PreviewBox = ({ const [largeDataset, setLargeDataset] = useState(false); const globals = useStore((state) => state.getAllExposedValues().constants || {}, shallow); const secrets = useStore((state) => state.getSecrets(), shallow); + const globalServerConstantsRegex = /^\{\{.*globals\.server.*\}\}$/; const getPreviewContent = (content, type) => { if (content === undefined || content === null) return currentValue; @@ -118,11 +119,11 @@ export const PreviewBox = ({ let previewContent = resolvedValue; let isGlobalConstant = currentValue && currentValue.includes('{{constants.'); let isSecretConstant = currentValue && currentValue.includes('{{secrets.'); + const isServerConstant = currentValue && currentValue.match(globalServerConstantsRegex); let invalidConstants = null; let undefinedError = null; if (isGlobalConstant || isSecretConstant) { invalidConstants = verifyConstant(currentValue, globals, secrets); - console.log('invalidConstants', invalidConstants); } if (invalidConstants?.length) { undefinedError = { type: 'Invalid constants' }; @@ -197,7 +198,11 @@ export const PreviewBox = ({ const errValue = ifCoersionErrorHasCircularDependency(_resolveValue); setError({ - message: isSecretError ? 'secrets cannot be used in apps' : _error, + message: isServerConstant + ? 'Server variables cannot be used in apps' + : isSecretError + ? 'secrets cannot be used in apps' + : _error, value: isSecretError ? 'Undefined' : jsErrorType === 'Invalid' @@ -222,6 +227,7 @@ export const PreviewBox = ({ isWorkspaceVariable={isWorkspaceVariable} isSecretConstant={isSecretConstant || false} isLargeDataset={largeDataset} + isServerConstant={isServerConstant} /> copyToClipboard(error ? error?.value : content)} @@ -240,8 +246,11 @@ const RenderResolvedValue = ({ withValidation, isWorkspaceVariable, isSecretConstant = false, + isServerConstant = false, isLargeDataset, }) => { + const isServerSideGlobalEnabled = useStore((state) => !!state?.license?.featureAccess?.serverSideGlobal, shallow); + const computeCoersionPreview = (resolvedValue, coersionData) => { if (coersionData?.typeBeforeCoercion === coersionData?.typeAfterCoercion) return resolvedValue; @@ -264,7 +273,11 @@ const RenderResolvedValue = ({ }` : previewType; - const previewContent = isSecretConstant + const previewContent = isServerConstant + ? isServerSideGlobalEnabled + ? 'Server variables would be resolved at runtime' + : 'Server variables are only available in paid plans' + : isSecretConstant ? 'Values of secret constants are hidden' : !withValidation ? resolvedValue diff --git a/frontend/src/AppBuilder/CodeEditor/SingleLineCodeEditor.jsx b/frontend/src/AppBuilder/CodeEditor/SingleLineCodeEditor.jsx index 7f8765e287..4c35f6d0ed 100644 --- a/frontend/src/AppBuilder/CodeEditor/SingleLineCodeEditor.jsx +++ b/frontend/src/AppBuilder/CodeEditor/SingleLineCodeEditor.jsx @@ -3,7 +3,7 @@ import React, { useEffect, useRef, useState } from 'react'; import { PreviewBox } from './PreviewBox'; import { ToolTip } from '@/Editor/Inspector/Elements/Components/ToolTip'; import { useTranslation } from 'react-i18next'; -import { camelCase, isEmpty, noop } from 'lodash'; +import { camelCase, isEmpty, noop, get } from 'lodash'; import CodeMirror from '@uiw/react-codemirror'; import { javascript } from '@codemirror/lang-javascript'; import { autocompletion, completionKeymap, completionStatus, acceptCompletion } from '@codemirror/autocomplete'; @@ -12,7 +12,7 @@ import { keymap } from '@codemirror/view'; import FxButton from '../CodeBuilder/Elements/FxButton'; import cx from 'classnames'; import { DynamicFxTypeRenderer } from './DynamicFxTypeRenderer'; -import { resolveReferences } from './utils'; +import { isInsideParent, resolveReferences } from './utils'; import { okaidia } from '@uiw/codemirror-theme-okaidia'; import { githubLight } from '@uiw/codemirror-theme-github'; import { getAutocompletion } from './autocompleteExtensionConfig'; @@ -161,6 +161,7 @@ const SingleLineCodeEditor = ({ componentName, fieldMeta = {}, componentId, ...r componentName={componentName} setShowPreview={setShowPreview} showPreview={showPreview} + wrapperRef={wrapperRef} showSuggestions={showSuggestions} {...restProps} /> @@ -194,11 +195,25 @@ const EditorInput = ({ previewRef, setShowPreview, onInputChange, + wrapperRef, showSuggestions, }) => { + const getServerSideGlobalSuggestions = useStore((state) => state.getServerSideGlobalSuggestions, shallow); + const getSuggestions = useStore((state) => state.getSuggestions, shallow); + const isInsideQueryManager = useMemo( + () => isInsideParent(wrapperRef?.current, 'query-manager'), + [wrapperRef.current] + ); function autoCompleteExtensionConfig(context) { const hints = getSuggestions(); + const serverHints = getServerSideGlobalSuggestions(isInsideQueryManager); + + const allHints = { + ...hints, + appHints: [...hints.appHints, ...serverHints], + }; + let word = context.matchBefore(/\w*/); const totalReferences = (context.state.doc.toString().match(/{{/g) || []).length; @@ -229,7 +244,7 @@ const EditorInput = ({ queryInput = '{{' + currentWord + '}}'; } - let completions = getAutocompletion(queryInput, validationType, hints, totalReferences, originalQueryInput); + let completions = getAutocompletion(queryInput, validationType, allHints, totalReferences, originalQueryInput); return { from: word.from, @@ -239,7 +254,7 @@ const EditorInput = ({ } // eslint-disable-next-line react-hooks/exhaustive-deps - const overRideFunction = React.useCallback((context) => autoCompleteExtensionConfig(context), []); + const overRideFunction = React.useCallback((context) => autoCompleteExtensionConfig(context), [isInsideQueryManager]); const autoCompleteConfig = autocompletion({ override: [overRideFunction], @@ -409,11 +424,11 @@ const EditorInput = ({ extensions={ showSuggestions ? [ - javascript({ jsx: lang === 'jsx' }), - autoCompleteConfig, - keymap.of([...customKeyMaps]), - customTabKeymap, - ] + javascript({ jsx: lang === 'jsx' }), + autoCompleteConfig, + keymap.of([...customKeyMaps]), + customTabKeymap, + ] : [javascript({ jsx: lang === 'jsx' })] } onChange={(val) => { @@ -485,9 +500,8 @@ const DynamicEditorBridge = (props) => {
)} @@ -495,9 +509,8 @@ const DynamicEditorBridge = (props) => {
{paramLabel !== 'Type' && isFxNotRequired === undefined && (
{ + while (element) { + if (element.classList?.contains(className)) { + console.log('element.classList', element.classList); + return true; + } + element = element.parentElement; + } + return false; +}; + function getMethods(type) { const arrayMethods = Object.getOwnPropertyNames(Array.prototype).filter( (p) => typeof Array.prototype[p] === 'function' diff --git a/frontend/src/AppBuilder/_stores/slices/codeHinterSlice.js b/frontend/src/AppBuilder/_stores/slices/codeHinterSlice.js index 953d253709..854cba49da 100644 --- a/frontend/src/AppBuilder/_stores/slices/codeHinterSlice.js +++ b/frontend/src/AppBuilder/_stores/slices/codeHinterSlice.js @@ -36,4 +36,27 @@ export const createCodeHinterSlice = (set, get) => ({ setSuggestions({ appHints: suggestionList, jsHints: jsHints }); }, getSuggestions: () => get().suggestions, + getServerSideGlobalSuggestions: (isInsideQueryManager) => { + const isServerSideGlobalEnabled = !!get()?.license?.featureAccess?.serverSideGlobal; + const serverHints = []; + const hints = get().getSuggestions(); + if (isInsideQueryManager && isServerSideGlobalEnabled) { + serverHints.push({ hint: 'globals.server', type: 'Object' }); + hints?.appHints?.forEach((appHint) => { + if (appHint?.hint?.startsWith('globals.currentUser')) { + const key = appHint?.hint?.replace('globals.currentUser', 'globals.server.currentUser'); + console.log({ + hint: key, + type: appHint?.type, + }); + serverHints.push({ + hint: key, + type: appHint?.type, + }); + } + }); + } + + return serverHints; + }, }); diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index 92712693b3..986c7011b1 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -122,7 +122,7 @@ module.exports = { '@cloud/modules': emptyModulePath, }, }, - devtool: environment === 'development' ? 'eval-source-map' : 'hidden-source-map', + devtool: environment === 'development' ? 'source-map' : 'hidden-source-map', module: { rules: [ { diff --git a/server/ee b/server/ee index 683647f83d..381d9771d1 160000 --- a/server/ee +++ b/server/ee @@ -1 +1 @@ -Subproject commit 683647f83d3efeeadbe69c40b8e8dd5ba4e8ea06 +Subproject commit 381d9771d1e237285a362f0c75bffe68f6de707f diff --git a/server/src/modules/data-queries/interfaces/IUtilService.ts b/server/src/modules/data-queries/interfaces/IUtilService.ts index 738108d75d..f070380b54 100644 --- a/server/src/modules/data-queries/interfaces/IUtilService.ts +++ b/server/src/modules/data-queries/interfaces/IUtilService.ts @@ -22,7 +22,8 @@ export interface IDataQueriesUtilService { dataQuery: any, queryOptions: object, organization_id: string, - environmentId?: string + environmentId?: string, + user?: User ): Promise<{ service: any; sourceOptions: object; @@ -31,5 +32,11 @@ export interface IDataQueriesUtilService { setCookiesBackToClient(response: Response, responseHeaders: any): void; - parseQueryOptions(object: any, options: object, organization_id: string, environmentId?: string): Promise; + parseQueryOptions( + object: any, + options: object, + organization_id: string, + environmentId?: string, + user?: User + ): Promise; } diff --git a/server/src/modules/data-queries/util.service.ts b/server/src/modules/data-queries/util.service.ts index 889b39046d..f99fb84718 100644 --- a/server/src/modules/data-queries/util.service.ts +++ b/server/src/modules/data-queries/util.service.ts @@ -89,7 +89,8 @@ export class DataQueriesUtilService implements IDataQueriesUtilService { dataQuery, queryOptions, organizationId, - environmentId + environmentId, + user ); queryStatus.setOptions(parsedQueryOptions); @@ -217,7 +218,8 @@ export class DataQueriesUtilService implements IDataQueriesUtilService { dataQuery, queryOptions, organizationId, - environmentId + environmentId, + user )); queryStatus.setOptions(parsedQueryOptions); result = await service.run( @@ -291,18 +293,27 @@ export class DataQueriesUtilService implements IDataQueriesUtilService { } } - async fetchServiceAndParsedParams(dataSource, dataQuery, queryOptions, organization_id, environmentId = undefined) { + async fetchServiceAndParsedParams( + dataSource, + dataQuery, + queryOptions, + organization_id, + environmentId = undefined, + user = undefined + ) { const sourceOptions = await this.dataSourceUtilService.parseSourceOptions( dataSource.options, organization_id, - environmentId + environmentId, + user ); const parsedQueryOptions = await this.parseQueryOptions( dataQuery.options, queryOptions, organization_id, - environmentId + environmentId, + user ); const service = await this.pluginsSelectorService.getService(dataSource.pluginId, dataSource.kind); @@ -368,7 +379,8 @@ export class DataQueriesUtilService implements IDataQueriesUtilService { object: any, options: object, organization_id: string, - environmentId?: string + environmentId?: string, + user?: User ): Promise { const stack: any[] = [{ obj: object, key: null, parent: null }]; @@ -406,12 +418,14 @@ export class DataQueriesUtilService implements IDataQueriesUtilService { // b: Handle {{constants.}} or {{secrets.}} if ( (typeof resolvedValue === 'string' && resolvedValue.includes('{{constants.')) || - resolvedValue.includes('{{secrets.') + resolvedValue.includes('{{secrets.') || + resolvedValue.includes('{{globals.server.') ) { const resolvingConstant = await this.dataSourceUtilService.resolveConstants( resolvedValue, organization_id, - environmentId + environmentId, + user ); resolvedValue = resolvingConstant; if (parent && key !== null) { diff --git a/server/src/modules/data-sources/interfaces/IUtilService.ts b/server/src/modules/data-sources/interfaces/IUtilService.ts index f8db416617..1539d73019 100644 --- a/server/src/modules/data-sources/interfaces/IUtilService.ts +++ b/server/src/modules/data-sources/interfaces/IUtilService.ts @@ -34,7 +34,7 @@ export interface IDataSourcesUtilService { parseOptionsForOauthDataSource(options: Array, resetSecureData?: boolean): Promise>; - resolveConstants(value: string, organizationId: string, environmentId: string): Promise; + resolveConstants(value: string, organizationId: string, environmentId: string, user?: User): Promise; resolveKeyValuePair(element: any, organizationId: string, environmentId: string): Promise; diff --git a/server/src/modules/data-sources/module.ts b/server/src/modules/data-sources/module.ts index 27072f6d2c..e247ddba38 100644 --- a/server/src/modules/data-sources/module.ts +++ b/server/src/modules/data-sources/module.ts @@ -10,6 +10,7 @@ import { InstanceSettingsModule } from '@modules/instance-settings/module'; import { VersionRepository } from '@modules/versions/repository'; import { AppsRepository } from '@modules/apps/repository'; import { TooljetDbModule } from '@modules/tooljet-db/module'; +import { SessionModule } from '@modules/session/module'; export class DataSourcesModule { static async register(configs?: { IS_GET_CONTEXT: boolean }): Promise { @@ -28,6 +29,7 @@ export class DataSourcesModule { await OrganizationConstantModule.register(configs), await InstanceSettingsModule.register(configs), await TooljetDbModule.register(configs), + await SessionModule.register(configs), ], providers: [ DataSourcesService, diff --git a/server/src/modules/data-sources/util.service.ts b/server/src/modules/data-sources/util.service.ts index b4329dd4c5..28d5719ad1 100644 --- a/server/src/modules/data-sources/util.service.ts +++ b/server/src/modules/data-sources/util.service.ts @@ -302,8 +302,9 @@ export class DataSourcesUtilService implements IDataSourcesUtilService { return dataSource; } - async resolveConstants(str: string, organizationId: string, environmentId: string): Promise { + async resolveConstants(str: string, organizationId: string, environmentId: string, user?: User): Promise { const regex = /\{\{(constants|secrets)\.(.*?)\}\}/g; + const matches = Array.from(str.matchAll(regex)); if (matches.length === 0) return str; @@ -353,7 +354,7 @@ export class DataSourcesUtilService implements IDataSourcesUtilService { } async resolveValue(value, organization_id, environment_id) { - const constantMatcher = /{{constants|secrets\..+?}}/g; + const constantMatcher = /{{constants|secrets|globals.server\..+?}}/g; if (typeof value === 'string' && constantMatcher.test(value)) { return await this.resolveConstants(value, organization_id, environment_id); @@ -371,7 +372,7 @@ export class DataSourcesUtilService implements IDataSourcesUtilService { const parsedOptions = JSON.parse(JSON.stringify(options)); // need to match if currentOption is a contant, {{constants.psql_db} - const constantMatcher = /{{constants|secrets\..+?}}/g; + const constantMatcher = /{{constants|secrets|globals.server\..+?}}/g; for (const key of Object.keys(parsedOptions)) { let currentOption = parsedOptions[key]?.['value']; @@ -590,10 +591,10 @@ export class DataSourcesUtilService implements IDataSourcesUtilService { return options; } - async parseSourceOptions(options: any, organizationId: string, environmentId: string): Promise { + async parseSourceOptions(options: any, organizationId: string, environmentId: string, user?: User): Promise { // For adhoc queries such as REST API queries, source options will be null if (!options) return {}; - const constantMatcher = /\{\{(constants|secrets)\..*?\}\}/g; + const constantMatcher = /\{\{(constants|secrets|globals.server)\..*?\}\}/g; for (const key of Object.keys(options)) { const currentOption = options[key]?.['value']; @@ -609,7 +610,7 @@ export class DataSourcesUtilService implements IDataSourcesUtilService { constantMatcher.lastIndex = 0; if (constantMatcher.test(inner)) { - const resolved = await this.resolveConstants(inner, organizationId, environmentId); + const resolved = await this.resolveConstants(inner, organizationId, environmentId, user); curr[j] = resolved; } } @@ -618,7 +619,7 @@ export class DataSourcesUtilService implements IDataSourcesUtilService { } if (constantMatcher.test(currentOption)) { - const resolved = await this.resolveConstants(currentOption, organizationId, environmentId); + const resolved = await this.resolveConstants(currentOption, organizationId, environmentId, user); options[key]['value'] = resolved; } } @@ -633,7 +634,7 @@ export class DataSourcesUtilService implements IDataSourcesUtilService { const value = await this.credentialService.getValue(credentialId); if (value.includes('{{constants') || value.includes('{{secrets')) { - const resolved = await this.resolveConstants(value, organizationId, environmentId); + const resolved = await this.resolveConstants(value, organizationId, environmentId, user); parsedOptions[key] = resolved; continue; } else { diff --git a/server/src/modules/licensing/configs/LicenseBase.ts b/server/src/modules/licensing/configs/LicenseBase.ts index 6f7764addd..8b616a8d21 100644 --- a/server/src/modules/licensing/configs/LicenseBase.ts +++ b/server/src/modules/licensing/configs/LicenseBase.ts @@ -15,6 +15,7 @@ export default class LicenseBase { private _isCustomStyling: boolean; private _isWhiteLabelling: boolean; private _isCustomThemes: boolean; + private _isServerSideGlobal: boolean; private _isMultiEnvironment: boolean; private _isMultiPlayerEdit: boolean; private _isComments: boolean; @@ -49,6 +50,7 @@ export default class LicenseBase { this._isCustomStyling = true; this._isWhiteLabelling = true; this._isCustomThemes = true; + this._isServerSideGlobal = true; this._isLicenseValid = true; this._isMultiEnvironment = true; this._isAi = true; @@ -88,6 +90,7 @@ export default class LicenseBase { this._isCustomStyling = this.getFeatureValue('customStyling'); this._isWhiteLabelling = this.getFeatureValue('whiteLabelling'); this._isCustomThemes = this.getFeatureValue('customThemes'); + this._isServerSideGlobal = this.getFeatureValue('serverSideGlobal'); this._isMultiEnvironment = this.getFeatureValue('multiEnvironment'); this._isMultiPlayerEdit = this.getFeatureValue('multiPlayerEdit'); this._isComments = this.getFeatureValue('comments'); @@ -256,6 +259,13 @@ export default class LicenseBase { return this._isCustomThemes; } + public get serverSideGlobal(): boolean { + if (this.IsBasicPlan) { + return !!BASIC_PLAN_TERMS.features?.serverSideGlobal; + } + return this._isServerSideGlobal; + } + public get multiPlayerEdit(): boolean { if (this.IsBasicPlan) { return !!BASIC_PLAN_TERMS.features?.multiPlayerEdit; @@ -298,6 +308,7 @@ export default class LicenseBase { customStyling: this.customStyling, whiteLabelling: this.whiteLabelling, customThemes: this.customThemes, + serverSideGlobal: this.serverSideGlobal, multiEnvironment: this.multiEnvironment, multiPlayerEdit: this.multiPlayerEdit, gitSync: this.gitSync, @@ -326,6 +337,7 @@ export default class LicenseBase { samlEnabled: this.saml, customStylingEnabled: this.customStyling, customThemesEnabled: this.customThemes, + serverSideGlobalEnabled: this.serverSideGlobal, multiEnvironmentEnabled: this.multiEnvironment, multiPlayerEditEnabled: this.multiPlayerEdit, commentsEnabled: this.comments, diff --git a/server/src/modules/licensing/constants/PlanTerms.ts b/server/src/modules/licensing/constants/PlanTerms.ts index 0eb05cfe6c..c896a1aa46 100644 --- a/server/src/modules/licensing/constants/PlanTerms.ts +++ b/server/src/modules/licensing/constants/PlanTerms.ts @@ -25,6 +25,7 @@ export const BASIC_PLAN_TERMS: Partial = { gitSync: false, comments: false, customThemes: false, + serverSideGlobal: false, ai: true, }, domains: [], diff --git a/server/src/modules/licensing/constants/index.ts b/server/src/modules/licensing/constants/index.ts index 49c7428a84..f5bcf3bd14 100644 --- a/server/src/modules/licensing/constants/index.ts +++ b/server/src/modules/licensing/constants/index.ts @@ -104,6 +104,7 @@ export enum LICENSE_FIELD { CUSTOM_STYLE = 'customStylingEnabled', WHITE_LABEL = 'whitelabellingEnabled', CUSTOM_THEMES = 'customThemeEnabled', + SERVER_SIDE_GLOBAL = 'serverSideGlobalEnabled', AUDIT_LOGS = 'auditLogsEnabled', MAX_DURATION_FOR_AUDIT_LOGS = 'maxDaysForAuditLogs', MULTI_ENVIRONMENT = 'multiEnvironmentEnabled', diff --git a/server/src/modules/licensing/helper.ts b/server/src/modules/licensing/helper.ts index a9ffdc3305..0a8bc949b5 100644 --- a/server/src/modules/licensing/helper.ts +++ b/server/src/modules/licensing/helper.ts @@ -59,6 +59,9 @@ export function getLicenseFieldValue(type: LICENSE_FIELD, licenseInstance: Licen case LICENSE_FIELD.CUSTOM_THEMES: return licenseInstance.customThemes; + case LICENSE_FIELD.SERVER_SIDE_GLOBAL: + return licenseInstance.serverSideGlobal; + case LICENSE_FIELD.AUDIT_LOGS: return licenseInstance.auditLogs; diff --git a/server/src/modules/licensing/interfaces/terms.ts b/server/src/modules/licensing/interfaces/terms.ts index 5be1902aef..c7cbb86690 100644 --- a/server/src/modules/licensing/interfaces/terms.ts +++ b/server/src/modules/licensing/interfaces/terms.ts @@ -27,6 +27,7 @@ export interface Terms { gitSync?: boolean; comments?: boolean; customThemes?: boolean; + serverSideGlobal?: boolean; ai?: boolean; }; type?: LICENSE_TYPE; diff --git a/server/src/modules/organization-constants/constants/index.ts b/server/src/modules/organization-constants/constants/index.ts index edd867b913..7ed5e37bca 100644 --- a/server/src/modules/organization-constants/constants/index.ts +++ b/server/src/modules/organization-constants/constants/index.ts @@ -1,6 +1,7 @@ export enum OrganizationConstantType { GLOBAL = 'Global', SECRET = 'Secret', + SERVER = 'Server', } export enum FEATURE_KEY { diff --git a/server/src/modules/organization-users/module.ts b/server/src/modules/organization-users/module.ts index 174c1b8a92..3ebec059aa 100644 --- a/server/src/modules/organization-users/module.ts +++ b/server/src/modules/organization-users/module.ts @@ -20,7 +20,9 @@ export class OrganizationUsersModule { const { OrganizationUsersController } = await import( `${await getImportPath(IS_GET_CONTEXT)}/organization-users/controller` ); - const { OrganizationUsersService } = await import(`${await getImportPath(IS_GET_CONTEXT)}/organization-users/service`); + const { OrganizationUsersService } = await import( + `${await getImportPath(IS_GET_CONTEXT)}/organization-users/service` + ); const { OrganizationUsersUtilService } = await import( `${await getImportPath(IS_GET_CONTEXT)}/organization-users/util.service` );