diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index dedafd5f4e..d71c26ea2c 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -145,6 +145,25 @@ export type Billing = { trialPeriods: Array; }; +export type BillingEndTrialPeriodOutput = { + __typename?: 'BillingEndTrialPeriodOutput'; + /** Boolean that confirms if a payment method was found */ + hasPaymentMethod: Scalars['Boolean']['output']; + /** Updated subscription status */ + status?: Maybe; +}; + +export type BillingMeteredProductUsageOutput = { + __typename?: 'BillingMeteredProductUsageOutput'; + includedFreeQuantity: Scalars['Float']['output']; + periodEnd: Scalars['DateTime']['output']; + periodStart: Scalars['DateTime']['output']; + productKey: BillingProductKey; + totalCostCents: Scalars['Float']['output']; + unitPriceCents: Scalars['Float']['output']; + usageQuantity: Scalars['Float']['output']; +}; + /** The different billing plans available */ export enum BillingPlanKey { ENTERPRISE = 'ENTERPRISE', @@ -153,9 +172,9 @@ export enum BillingPlanKey { export type BillingPlanOutput = { __typename?: 'BillingPlanOutput'; - baseProduct: BillingProductDto; - meteredProducts: Array; - otherLicensedProducts: Array; + baseProduct: BillingProduct; + meteredProducts: Array; + otherLicensedProducts: Array; planKey: BillingPlanKey; }; @@ -191,13 +210,26 @@ export enum BillingPriceTiersMode { export type BillingPriceUnionDto = BillingPriceLicensedDto | BillingPriceMeteredDto; -export type BillingProductDto = { - __typename?: 'BillingProductDTO'; +export type BillingProduct = { + __typename?: 'BillingProduct'; description: Scalars['String']['output']; images?: Maybe>; + metadata: BillingProductMetadata; name: Scalars['String']['output']; - prices: Array; - type: BillingUsageType; + prices?: Maybe>; +}; + +/** The different billing products available */ +export enum BillingProductKey { + BASE_PRODUCT = 'BASE_PRODUCT', + WORKFLOW_NODE_EXECUTION = 'WORKFLOW_NODE_EXECUTION' +} + +export type BillingProductMetadata = { + __typename?: 'BillingProductMetadata'; + planKey: BillingPlanKey; + priceUsageBased: BillingUsageType; + productKey: BillingProductKey; }; export type BillingSessionOutput = { @@ -207,11 +239,19 @@ export type BillingSessionOutput = { export type BillingSubscription = { __typename?: 'BillingSubscription'; + billingSubscriptionItems?: Maybe>; id: Scalars['UUID']['output']; interval?: Maybe; status: SubscriptionStatus; }; +export type BillingSubscriptionItem = { + __typename?: 'BillingSubscriptionItem'; + billingProduct?: Maybe; + hasReachedCurrentPeriodCap: Scalars['Boolean']['output']; + id: Scalars['UUID']['output']; +}; + export type BillingTrialPeriodDto = { __typename?: 'BillingTrialPeriodDTO'; duration: Scalars['Float']['output']; @@ -280,6 +320,49 @@ export type ComputeStepOutputSchemaInput = { step: Scalars['JSON']['input']; }; +export type ConfigVariable = { + __typename?: 'ConfigVariable'; + description: Scalars['String']['output']; + isSensitive: Scalars['Boolean']['output']; + name: Scalars['String']['output']; + value: Scalars['String']['output']; +}; + +export enum ConfigVariablesGroup { + AnalyticsConfig = 'AnalyticsConfig', + BillingConfig = 'BillingConfig', + CaptchaConfig = 'CaptchaConfig', + CloudflareConfig = 'CloudflareConfig', + EmailSettings = 'EmailSettings', + ExceptionHandler = 'ExceptionHandler', + GoogleAuth = 'GoogleAuth', + LLM = 'LLM', + Logging = 'Logging', + Metering = 'Metering', + MicrosoftAuth = 'MicrosoftAuth', + Other = 'Other', + RateLimiting = 'RateLimiting', + SSL = 'SSL', + ServerConfig = 'ServerConfig', + ServerlessConfig = 'ServerlessConfig', + StorageConfig = 'StorageConfig', + SupportChatConfig = 'SupportChatConfig', + TokensDuration = 'TokensDuration' +} + +export type ConfigVariablesGroupData = { + __typename?: 'ConfigVariablesGroupData'; + description: Scalars['String']['output']; + isHiddenOnLoad: Scalars['Boolean']['output']; + name: ConfigVariablesGroup; + variables: Array; +}; + +export type ConfigVariablesOutput = { + __typename?: 'ConfigVariablesOutput'; + groups: Array; +}; + export type CreateAppTokenInput = { expiresAt: Scalars['DateTime']['input']; }; @@ -498,49 +581,6 @@ export type EmailPasswordResetLink = { success: Scalars['Boolean']['output']; }; -export type EnvironmentVariable = { - __typename?: 'EnvironmentVariable'; - description: Scalars['String']['output']; - name: Scalars['String']['output']; - sensitive: Scalars['Boolean']['output']; - value: Scalars['String']['output']; -}; - -export enum EnvironmentVariablesGroup { - AnalyticsConfig = 'AnalyticsConfig', - BillingConfig = 'BillingConfig', - CaptchaConfig = 'CaptchaConfig', - CloudflareConfig = 'CloudflareConfig', - EmailSettings = 'EmailSettings', - ExceptionHandler = 'ExceptionHandler', - GoogleAuth = 'GoogleAuth', - LLM = 'LLM', - Logging = 'Logging', - Metering = 'Metering', - MicrosoftAuth = 'MicrosoftAuth', - Other = 'Other', - RateLimiting = 'RateLimiting', - SSL = 'SSL', - ServerConfig = 'ServerConfig', - ServerlessConfig = 'ServerlessConfig', - StorageConfig = 'StorageConfig', - SupportChatConfig = 'SupportChatConfig', - TokensDuration = 'TokensDuration' -} - -export type EnvironmentVariablesGroupData = { - __typename?: 'EnvironmentVariablesGroupData'; - description: Scalars['String']['output']; - isHiddenOnLoad: Scalars['Boolean']['output']; - name: EnvironmentVariablesGroup; - variables: Array; -}; - -export type EnvironmentVariablesOutput = { - __typename?: 'EnvironmentVariablesOutput'; - groups: Array; -}; - export type ExecuteServerlessFunctionInput = { /** Id of the serverless function to execute */ id: Scalars['UUID']['input']; @@ -908,6 +948,7 @@ export type Mutation = { editSSOIdentityProvider: EditSsoOutput; emailPasswordResetLink: EmailPasswordResetLink; enablePostgresProxy: PostgresCredentials; + endSubscriptionTrialPeriod: BillingEndTrialPeriodOutput; executeOneServerlessFunction: ServerlessFunctionExecutionResult; generateApiKeyToken: ApiKeyToken; generateTransientToken: TransientToken; @@ -926,11 +967,11 @@ export type Mutation = { signUpInNewWorkspace: SignUpOutput; skipSyncEmailOnboardingStep: OnboardingStepSuccess; submitFormStep: Scalars['Boolean']['output']; + switchToYearlyInterval: BillingUpdateOutput; syncRemoteTable: RemoteTable; syncRemoteTableSchemaChanges: RemoteTable; track: Analytics; unsyncRemoteTable: RemoteTable; - updateBillingSubscription: BillingUpdateOutput; updateLabPublicFeatureFlag: FeatureFlag; updateOneField: Field; updateOneObject: Object; @@ -1524,8 +1565,9 @@ export type Query = { findWorkspaceInvitations: Array; getApprovedAccessDomains: Array; getAvailablePackages: Scalars['JSON']['output']; - getEnvironmentVariablesGrouped: EnvironmentVariablesOutput; + getConfigVariablesGrouped: ConfigVariablesOutput; getIndicatorHealthStatus: AdminPanelHealthServiceData; + getMeteredProductsUsage: Array; getPostgresCredentials?: Maybe; getPublicWorkspaceDataByDomain: PublicWorkspaceDataOutput; getQueueMetrics: QueueMetricsData; @@ -1545,6 +1587,7 @@ export type Query = { relationMetadata: RelationMetadataConnection; search: Array; validatePasswordResetToken: ValidatePasswordResetToken; + versionInfo: VersionInfo; }; @@ -2369,6 +2412,12 @@ export type ValidatePasswordResetToken = { id: Scalars['String']['output']; }; +export type VersionInfo = { + __typename?: 'VersionInfo'; + currentVersion?: Maybe; + latestVersion: Scalars['String']['output']; +}; + export type WorkerQueueMetrics = { __typename?: 'WorkerQueueMetrics'; active: Scalars['Float']['output']; diff --git a/packages/twenty-front/src/generated/graphql.tsx b/packages/twenty-front/src/generated/graphql.tsx index 878e7002be..3379f8e18c 100644 --- a/packages/twenty-front/src/generated/graphql.tsx +++ b/packages/twenty-front/src/generated/graphql.tsx @@ -312,6 +312,49 @@ export type ComputeStepOutputSchemaInput = { step: Scalars['JSON']; }; +export type ConfigVariable = { + __typename?: 'ConfigVariable'; + description: Scalars['String']; + isSensitive: Scalars['Boolean']; + name: Scalars['String']; + value: Scalars['String']; +}; + +export enum ConfigVariablesGroup { + AnalyticsConfig = 'AnalyticsConfig', + BillingConfig = 'BillingConfig', + CaptchaConfig = 'CaptchaConfig', + CloudflareConfig = 'CloudflareConfig', + EmailSettings = 'EmailSettings', + ExceptionHandler = 'ExceptionHandler', + GoogleAuth = 'GoogleAuth', + LLM = 'LLM', + Logging = 'Logging', + Metering = 'Metering', + MicrosoftAuth = 'MicrosoftAuth', + Other = 'Other', + RateLimiting = 'RateLimiting', + SSL = 'SSL', + ServerConfig = 'ServerConfig', + ServerlessConfig = 'ServerlessConfig', + StorageConfig = 'StorageConfig', + SupportChatConfig = 'SupportChatConfig', + TokensDuration = 'TokensDuration' +} + +export type ConfigVariablesGroupData = { + __typename?: 'ConfigVariablesGroupData'; + description: Scalars['String']; + isHiddenOnLoad: Scalars['Boolean']; + name: ConfigVariablesGroup; + variables: Array; +}; + +export type ConfigVariablesOutput = { + __typename?: 'ConfigVariablesOutput'; + groups: Array; +}; + export type CreateApprovedAccessDomainInput = { domain: Scalars['String']; email: Scalars['String']; @@ -469,49 +512,6 @@ export type EmailPasswordResetLink = { success: Scalars['Boolean']; }; -export type EnvironmentVariable = { - __typename?: 'EnvironmentVariable'; - description: Scalars['String']; - name: Scalars['String']; - sensitive: Scalars['Boolean']; - value: Scalars['String']; -}; - -export enum EnvironmentVariablesGroup { - AnalyticsConfig = 'AnalyticsConfig', - BillingConfig = 'BillingConfig', - CaptchaConfig = 'CaptchaConfig', - CloudflareConfig = 'CloudflareConfig', - EmailSettings = 'EmailSettings', - ExceptionHandler = 'ExceptionHandler', - GoogleAuth = 'GoogleAuth', - LLM = 'LLM', - Logging = 'Logging', - Metering = 'Metering', - MicrosoftAuth = 'MicrosoftAuth', - Other = 'Other', - RateLimiting = 'RateLimiting', - SSL = 'SSL', - ServerConfig = 'ServerConfig', - ServerlessConfig = 'ServerlessConfig', - StorageConfig = 'StorageConfig', - SupportChatConfig = 'SupportChatConfig', - TokensDuration = 'TokensDuration' -} - -export type EnvironmentVariablesGroupData = { - __typename?: 'EnvironmentVariablesGroupData'; - description: Scalars['String']; - isHiddenOnLoad: Scalars['Boolean']; - name: EnvironmentVariablesGroup; - variables: Array; -}; - -export type EnvironmentVariablesOutput = { - __typename?: 'EnvironmentVariablesOutput'; - groups: Array; -}; - export type ExecuteServerlessFunctionInput = { /** Id of the serverless function to execute */ id: Scalars['UUID']; @@ -1428,7 +1428,7 @@ export type Query = { findWorkspaceInvitations: Array; getApprovedAccessDomains: Array; getAvailablePackages: Scalars['JSON']; - getEnvironmentVariablesGrouped: EnvironmentVariablesOutput; + getConfigVariablesGrouped: ConfigVariablesOutput; getIndicatorHealthStatus: AdminPanelHealthServiceData; getMeteredProductsUsage: Array; getPostgresCredentials?: Maybe; @@ -2625,10 +2625,10 @@ export type UserLookupAdminPanelMutationVariables = Exact<{ export type UserLookupAdminPanelMutation = { __typename?: 'Mutation', userLookupAdminPanel: { __typename?: 'UserLookup', user: { __typename?: 'UserInfo', id: string, email: string, firstName?: string | null, lastName?: string | null }, workspaces: Array<{ __typename?: 'WorkspaceInfo', id: string, name: string, logo?: string | null, totalUsers: number, allowImpersonation: boolean, users: Array<{ __typename?: 'UserInfo', id: string, email: string, firstName?: string | null, lastName?: string | null }>, featureFlags: Array<{ __typename?: 'FeatureFlag', key: FeatureFlagKey, value: boolean }> }> } }; -export type GetEnvironmentVariablesGroupedQueryVariables = Exact<{ [key: string]: never; }>; +export type GetConfigVariablesGroupedQueryVariables = Exact<{ [key: string]: never; }>; -export type GetEnvironmentVariablesGroupedQuery = { __typename?: 'Query', getEnvironmentVariablesGrouped: { __typename?: 'EnvironmentVariablesOutput', groups: Array<{ __typename?: 'EnvironmentVariablesGroupData', name: EnvironmentVariablesGroup, description: string, isHiddenOnLoad: boolean, variables: Array<{ __typename?: 'EnvironmentVariable', name: string, description: string, value: string, sensitive: boolean }> }> } }; +export type GetConfigVariablesGroupedQuery = { __typename?: 'Query', getConfigVariablesGrouped: { __typename?: 'ConfigVariablesOutput', groups: Array<{ __typename?: 'ConfigVariablesGroupData', name: ConfigVariablesGroup, description: string, isHiddenOnLoad: boolean, variables: Array<{ __typename?: 'ConfigVariable', name: string, description: string, value: string, isSensitive: boolean }> }> } }; export type GetVersionInfoQueryVariables = Exact<{ [key: string]: never; }>; @@ -4578,9 +4578,9 @@ export function useUserLookupAdminPanelMutation(baseOptions?: Apollo.MutationHoo export type UserLookupAdminPanelMutationHookResult = ReturnType; export type UserLookupAdminPanelMutationResult = Apollo.MutationResult; export type UserLookupAdminPanelMutationOptions = Apollo.BaseMutationOptions; -export const GetEnvironmentVariablesGroupedDocument = gql` - query GetEnvironmentVariablesGrouped { - getEnvironmentVariablesGrouped { +export const GetConfigVariablesGroupedDocument = gql` + query GetConfigVariablesGrouped { + getConfigVariablesGrouped { groups { name description @@ -4589,7 +4589,7 @@ export const GetEnvironmentVariablesGroupedDocument = gql` name description value - sensitive + isSensitive } } } @@ -4597,31 +4597,31 @@ export const GetEnvironmentVariablesGroupedDocument = gql` `; /** - * __useGetEnvironmentVariablesGroupedQuery__ + * __useGetConfigVariablesGroupedQuery__ * - * To run a query within a React component, call `useGetEnvironmentVariablesGroupedQuery` and pass it any options that fit your needs. - * When your component renders, `useGetEnvironmentVariablesGroupedQuery` returns an object from Apollo Client that contains loading, error, and data properties + * To run a query within a React component, call `useGetConfigVariablesGroupedQuery` and pass it any options that fit your needs. + * When your component renders, `useGetConfigVariablesGroupedQuery` returns an object from Apollo Client that contains loading, error, and data properties * you can use to render your UI. * * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; * * @example - * const { data, loading, error } = useGetEnvironmentVariablesGroupedQuery({ + * const { data, loading, error } = useGetConfigVariablesGroupedQuery({ * variables: { * }, * }); */ -export function useGetEnvironmentVariablesGroupedQuery(baseOptions?: Apollo.QueryHookOptions) { +export function useGetConfigVariablesGroupedQuery(baseOptions?: Apollo.QueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetEnvironmentVariablesGroupedDocument, options); + return Apollo.useQuery(GetConfigVariablesGroupedDocument, options); } -export function useGetEnvironmentVariablesGroupedLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { +export function useGetConfigVariablesGroupedLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetEnvironmentVariablesGroupedDocument, options); + return Apollo.useLazyQuery(GetConfigVariablesGroupedDocument, options); } -export type GetEnvironmentVariablesGroupedQueryHookResult = ReturnType; -export type GetEnvironmentVariablesGroupedLazyQueryHookResult = ReturnType; -export type GetEnvironmentVariablesGroupedQueryResult = Apollo.QueryResult; +export type GetConfigVariablesGroupedQueryHookResult = ReturnType; +export type GetConfigVariablesGroupedLazyQueryHookResult = ReturnType; +export type GetConfigVariablesGroupedQueryResult = Apollo.QueryResult; export const GetVersionInfoDocument = gql` query GetVersionInfo { versionInfo { diff --git a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariables.tsx b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariables.tsx index 893ebf5efc..7aed808d17 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariables.tsx +++ b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariables.tsx @@ -5,10 +5,10 @@ import { SettingsPath } from '@/types/SettingsPath'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { t } from '@lingui/core/macro'; -import { useGetEnvironmentVariablesGroupedQuery } from '~/generated/graphql'; -import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; -import { Card, Section } from 'twenty-ui/layout'; import { H2Title, IconHeartRateMonitor } from 'twenty-ui/display'; +import { Card, Section } from 'twenty-ui/layout'; +import { useGetConfigVariablesGroupedQuery } from '~/generated/graphql'; +import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; const StyledGroupContainer = styled.div``; @@ -22,17 +22,17 @@ const StyledCard = styled(Card)` export const SettingsAdminEnvVariables = () => { const theme = useTheme(); - const { data: environmentVariables, loading: environmentVariablesLoading } = - useGetEnvironmentVariablesGroupedQuery({ + const { data: configVariables, loading: configVariablesLoading } = + useGetConfigVariablesGroupedQuery({ fetchPolicy: 'network-only', }); const visibleGroups = - environmentVariables?.getEnvironmentVariablesGrouped.groups.filter( + configVariables?.getConfigVariablesGrouped.groups.filter( (group) => !group.isHiddenOnLoad, ) ?? []; - if (environmentVariablesLoading) { + if (configVariablesLoading) { return ; } diff --git a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariablesRow.tsx b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariablesRow.tsx index 94a5754979..27ecee1638 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariablesRow.tsx +++ b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariablesRow.tsx @@ -6,16 +6,16 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { motion } from 'framer-motion'; import { useState } from 'react'; -import { AnimatedExpandableContainer } from 'twenty-ui/layout'; import { IconChevronRight, IconEye, IconEyeOff } from 'twenty-ui/display'; import { LightIconButton } from 'twenty-ui/input'; +import { AnimatedExpandableContainer } from 'twenty-ui/layout'; type SettingsAdminEnvVariablesRowProps = { variable: { name: string; description: string; value: string; - sensitive: boolean; + isSensitive: boolean; }; isExpanded: boolean; onExpandToggle: (name: string) => void; @@ -79,7 +79,7 @@ export const SettingsAdminEnvVariablesRow = ({ const displayValue = variable.value === '' ? 'null' - : variable.sensitive && !showSensitiveValue + : variable.isSensitive && !showSensitiveValue ? '••••••' : variable.value; @@ -112,7 +112,7 @@ export const SettingsAdminEnvVariablesRow = ({ displayText={displayValue} multiline={true} /> - {variable.sensitive && variable.value !== '' && ( + {variable.isSensitive && variable.value !== '' && ( ; }; diff --git a/packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getEnvironmentVariablesGrouped.ts b/packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getConfigVariablesGrouped.ts similarity index 58% rename from packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getEnvironmentVariablesGrouped.ts rename to packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getConfigVariablesGrouped.ts index 7c8f94c25e..3299640252 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getEnvironmentVariablesGrouped.ts +++ b/packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getConfigVariablesGrouped.ts @@ -1,8 +1,8 @@ import { gql } from '@apollo/client'; -export const GET_ENVIRONMENT_VARIABLES_GROUPED = gql` - query GetEnvironmentVariablesGrouped { - getEnvironmentVariablesGrouped { +export const GET_CONFIG_VARIABLES_GROUPED = gql` + query GetConfigVariablesGrouped { + getConfigVariablesGrouped { groups { name description @@ -11,7 +11,7 @@ export const GET_ENVIRONMENT_VARIABLES_GROUPED = gql` name description value - sensitive + isSensitive } } } diff --git a/packages/twenty-front/src/pages/settings/admin-panel/SettingsAdminSecondaryEnvVariables.tsx b/packages/twenty-front/src/pages/settings/admin-panel/SettingsAdminSecondaryEnvVariables.tsx index 735e95f699..ce89803ad5 100644 --- a/packages/twenty-front/src/pages/settings/admin-panel/SettingsAdminSecondaryEnvVariables.tsx +++ b/packages/twenty-front/src/pages/settings/admin-panel/SettingsAdminSecondaryEnvVariables.tsx @@ -5,24 +5,26 @@ import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer'; import styled from '@emotion/styled'; import { t } from '@lingui/core/macro'; -import { useGetEnvironmentVariablesGroupedQuery } from '~/generated/graphql'; -import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; import { H2Title } from 'twenty-ui/display'; +import { useGetConfigVariablesGroupedQuery } from '~/generated/graphql'; +import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; const StyledGroupContainer = styled.div``; export const SettingsAdminSecondaryEnvVariables = () => { - const { data: environmentVariables, loading: environmentVariablesLoading } = - useGetEnvironmentVariablesGroupedQuery({ - fetchPolicy: 'network-only', - }); + const { + data: secondaryConfigVariables, + loading: secondaryConfigVariablesLoading, + } = useGetConfigVariablesGroupedQuery({ + fetchPolicy: 'network-only', + }); const hiddenGroups = - environmentVariables?.getEnvironmentVariablesGrouped.groups.filter( + secondaryConfigVariables?.getConfigVariablesGrouped.groups.filter( (group) => group.isHiddenOnLoad, ) ?? []; - if (environmentVariablesLoading) { + if (secondaryConfigVariablesLoading) { return ; } diff --git a/packages/twenty-server/jest-integration.config.ts b/packages/twenty-server/jest-integration.config.ts index 332e243bff..05b499db56 100644 --- a/packages/twenty-server/jest-integration.config.ts +++ b/packages/twenty-server/jest-integration.config.ts @@ -1,6 +1,6 @@ import { JestConfigWithTsJest, pathsToModuleNameMapper } from 'ts-jest'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; const isBillingEnabled = process.env.IS_BILLING_ENABLED === 'true'; diff --git a/packages/twenty-server/src/database/commands/command-runners/__tests__/upgrade.command-runner.spec.ts b/packages/twenty-server/src/database/commands/command-runners/__tests__/upgrade.command-runner.spec.ts index 82f7854a9f..e3313adcdf 100644 --- a/packages/twenty-server/src/database/commands/command-runners/__tests__/upgrade.command-runner.spec.ts +++ b/packages/twenty-server/src/database/commands/command-runners/__tests__/upgrade.command-runner.spec.ts @@ -6,8 +6,8 @@ import { EachTestingContext } from 'twenty-shared/testing'; import { Repository } from 'typeorm'; import { UpgradeCommandRunner } from 'src/database/commands/command-runners/upgrade.command-runner'; -import { EnvironmentVariables } from 'src/engine/core-modules/environment/environment-variables'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ConfigVariables } from 'src/engine/core-modules/twenty-config/config-variables'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command'; @@ -97,20 +97,18 @@ const buildUpgradeCommandModule = async ({ }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { - get: jest - .fn() - .mockImplementation((key: keyof EnvironmentVariables) => { - switch (key) { - case 'APP_VERSION': { - return appVersion; - } - default: { - return; - } + get: jest.fn().mockImplementation((key: keyof ConfigVariables) => { + switch (key) { + case 'APP_VERSION': { + return appVersion; } - }), + default: { + return; + } + } + }), }, }, { diff --git a/packages/twenty-server/src/database/commands/command-runners/upgrade.command-runner.ts b/packages/twenty-server/src/database/commands/command-runners/upgrade.command-runner.ts index e322284b35..2ae7d26bbd 100644 --- a/packages/twenty-server/src/database/commands/command-runners/upgrade.command-runner.ts +++ b/packages/twenty-server/src/database/commands/command-runners/upgrade.command-runner.ts @@ -9,7 +9,7 @@ import { ActiveOrSuspendedWorkspacesMigrationCommandRunner, RunOnWorkspaceArgs, } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command'; @@ -26,7 +26,7 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi constructor( @InjectRepository(Workspace, 'core') protected readonly workspaceRepository: Repository, - protected readonly environmentService: EnvironmentService, + protected readonly twentyConfigService: TwentyConfigService, protected readonly twentyORMGlobalManager: TwentyORMGlobalManager, protected readonly syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand, ) { @@ -87,7 +87,7 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi } private retrieveToVersionFromAppVersion() { - const appVersion = this.environmentService.get('APP_VERSION'); + const appVersion = this.twentyConfigService.get('APP_VERSION'); if (!isDefined(appVersion)) { throw new Error( diff --git a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts index d3ce4a65fa..e1336ff5d9 100644 --- a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts +++ b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts @@ -2,14 +2,14 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { DataSeedDemoWorkspaceService } from 'src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module'; @Module({ imports: [ WorkspaceManagerModule, - EnvironmentModule, + TwentyConfigModule, TypeOrmModule.forFeature([Workspace], 'core'), ], providers: [DataSeedDemoWorkspaceService], diff --git a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts index d7be191c32..0ca70c13f4 100644 --- a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts +++ b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts @@ -9,7 +9,7 @@ import { rawDataSource } from 'src/database/typeorm/raw/raw.datasource'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service'; @@ -21,7 +21,7 @@ export class DataSeedDemoWorkspaceService { protected readonly workspaceRepository: Repository, @InjectCacheStorage(CacheStorageNamespace.EngineWorkspace) private readonly workspaceSchemaCache: CacheStorageService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async seedDemo(): Promise { @@ -43,7 +43,7 @@ export class DataSeedDemoWorkspaceService { await deleteCoreSchema(rawDataSource, workspaceId); } - const appVersion = this.environmentService.get('APP_VERSION'); + const appVersion = this.twentyConfigService.get('APP_VERSION'); await seedCoreSchema({ workspaceDataSource: rawDataSource, diff --git a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts index 7d0cf6c284..b3832fadba 100644 --- a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts +++ b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts @@ -32,7 +32,7 @@ import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; @@ -68,7 +68,7 @@ export class DataSeedWorkspaceCommand extends CommandRunner { private readonly workspaceSchemaCache: CacheStorageService, private readonly seederService: SeederService, private readonly workspaceManagerService: WorkspaceManagerService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) { super(); } @@ -94,8 +94,8 @@ export class DataSeedWorkspaceCommand extends CommandRunner { await rawDataSource.initialize(); - const isBillingEnabled = this.environmentService.get('IS_BILLING_ENABLED'); - const appVersion = this.environmentService.get('APP_VERSION'); + const isBillingEnabled = this.twentyConfigService.get('IS_BILLING_ENABLED'); + const appVersion = this.twentyConfigService.get('APP_VERSION'); await seedCoreSchema({ workspaceDataSource: rawDataSource, diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts index b0ef99dde2..c247d00cca 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts @@ -17,7 +17,7 @@ import { UpdateDefaultViewRecordOpeningOnWorkflowObjectsCommand } from 'src/data import { InitializePermissionsCommand } from 'src/database/commands/upgrade-version-command/0-44/0-44-initialize-permissions.command'; import { UpdateViewAggregateOperationsCommand } from 'src/database/commands/upgrade-version-command/0-44/0-44-update-view-aggregate-operations.command'; import { UpgradeCreatedByEnumCommand } from 'src/database/commands/upgrade-version-command/0-51/0-51-update-workflow-trigger-type-enum.command'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command'; @@ -37,7 +37,7 @@ export class UpgradeCommand extends UpgradeCommandRunner { constructor( @InjectRepository(Workspace, 'core') protected readonly workspaceRepository: Repository, - protected readonly environmentService: EnvironmentService, + protected readonly twentyConfigService: TwentyConfigService, protected readonly twentyORMGlobalManager: TwentyORMGlobalManager, protected readonly syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand, @@ -57,7 +57,7 @@ export class UpgradeCommand extends UpgradeCommandRunner { ) { super( workspaceRepository, - environmentService, + twentyConfigService, twentyORMGlobalManager, syncWorkspaceMetadataCommand, ); diff --git a/packages/twenty-server/src/database/typeorm/typeorm.module.ts b/packages/twenty-server/src/database/typeorm/typeorm.module.ts index 15733f0c63..88a9b26e39 100644 --- a/packages/twenty-server/src/database/typeorm/typeorm.module.ts +++ b/packages/twenty-server/src/database/typeorm/typeorm.module.ts @@ -2,7 +2,7 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'; import { typeORMCoreModuleOptions } from 'src/database/typeorm/core/core.datasource'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { TypeORMService } from './typeorm.service'; @@ -28,7 +28,7 @@ const coreTypeORMFactory = async (): Promise => ({ useFactory: coreTypeORMFactory, name: 'core', }), - EnvironmentModule, + TwentyConfigModule, ], providers: [TypeORMService], exports: [TypeORMService], diff --git a/packages/twenty-server/src/database/typeorm/typeorm.service.ts b/packages/twenty-server/src/database/typeorm/typeorm.service.ts index f1fe7e0ae1..dcf12bc276 100644 --- a/packages/twenty-server/src/database/typeorm/typeorm.service.ts +++ b/packages/twenty-server/src/database/typeorm/typeorm.service.ts @@ -2,7 +2,7 @@ import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; import { ApprovedAccessDomain } from 'src/engine/core-modules/approved-access-domain/approved-access-domain.entity'; @@ -13,11 +13,11 @@ import { BillingPrice } from 'src/engine/core-modules/billing/entities/billing-p import { BillingProduct } from 'src/engine/core-modules/billing/entities/billing-product.entity'; import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity'; import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity'; import { PostgresCredentials } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.entity'; import { WorkspaceSSOIdentityProvider } from 'src/engine/core-modules/sso/workspace-sso-identity-provider.entity'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { TwoFactorMethod } from 'src/engine/core-modules/two-factor-method/two-factor-method.entity'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -29,12 +29,12 @@ export class TypeORMService implements OnModuleInit, OnModuleDestroy { private dataSources: Map = new Map(); private isDatasourceInitializing: Map = new Map(); - constructor(private readonly environmentService: EnvironmentService) { + constructor(private readonly twentyConfigService: TwentyConfigService) { this.mainDataSource = new DataSource({ - url: environmentService.get('PG_DATABASE_URL'), + url: twentyConfigService.get('PG_DATABASE_URL'), type: 'postgres', logging: - environmentService.get('NODE_ENV') === NodeEnvironment.development + twentyConfigService.get('NODE_ENV') === NodeEnvironment.development ? ['query', 'error'] : ['error'], schema: 'core', @@ -58,7 +58,7 @@ export class TypeORMService implements OnModuleInit, OnModuleDestroy { TwoFactorMethod, ], metadataTableName: '_typeorm_generated_columns_and_materialized_views', - ssl: environmentService.get('PG_SSL_ALLOW_SELF_SIGNED') + ssl: twentyConfigService.get('PG_SSL_ALLOW_SELF_SIGNED') ? { rejectUnauthorized: false, } @@ -111,14 +111,14 @@ export class TypeORMService implements OnModuleInit, OnModuleDestroy { const schema = dataSource.schema; const workspaceDataSource = new DataSource({ - url: dataSource.url ?? this.environmentService.get('PG_DATABASE_URL'), + url: dataSource.url ?? this.twentyConfigService.get('PG_DATABASE_URL'), type: 'postgres', logging: - this.environmentService.get('NODE_ENV') === NodeEnvironment.development + this.twentyConfigService.get('NODE_ENV') === NodeEnvironment.development ? ['query', 'error'] : ['error'], schema, - ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED') + ssl: this.twentyConfigService.get('PG_SSL_ALLOW_SELF_SIGNED') ? { rejectUnauthorized: false, } diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts index 6e85935617..72e5f77576 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts @@ -12,16 +12,16 @@ import GraphQLJSON from 'graphql-type-json'; import { GraphQLSchemaWithContext, YogaInitialContext } from 'graphql-yoga'; import { JsonWebTokenError, TokenExpiredError } from 'jsonwebtoken'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { useThrottler } from 'src/engine/api/graphql/graphql-config/hooks/use-throttler'; import { WorkspaceSchemaFactory } from 'src/engine/api/graphql/workspace-schema.factory'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; import { CoreEngineModule } from 'src/engine/core-modules/core-engine.module'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { useSentryTracing } from 'src/engine/core-modules/exception-handler/hooks/use-sentry-tracing'; import { useGraphQLErrorHandlerHook } from 'src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { handleExceptionAndConvertToGraphQLError } from 'src/engine/utils/global-exception-handler.util'; @@ -38,17 +38,17 @@ export class GraphQLConfigService { constructor( private readonly exceptionHandlerService: ExceptionHandlerService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly moduleRef: ModuleRef, ) {} createGqlOptions(): YogaDriverConfig { const isDebugMode = - this.environmentService.get('NODE_ENV') === NodeEnvironment.development; + this.twentyConfigService.get('NODE_ENV') === NodeEnvironment.development; const plugins = [ useThrottler({ - ttl: this.environmentService.get('API_RATE_LIMITING_TTL'), - limit: this.environmentService.get('API_RATE_LIMITING_LIMIT'), + ttl: this.twentyConfigService.get('API_RATE_LIMITING_TTL'), + limit: this.twentyConfigService.get('API_RATE_LIMITING_LIMIT'), identifyFn: (context) => { return context.req.user?.id ?? context.req.ip ?? 'anonymous'; }, diff --git a/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts b/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts index f7ac4328f2..d9962cdb03 100644 --- a/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts @@ -5,11 +5,11 @@ import { YogaDriver, YogaDriverConfig } from '@graphql-yoga/nestjs'; import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graphql-config.module'; import { metadataModuleFactory } from 'src/engine/api/graphql/metadata.module-factory'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { DataloaderModule } from 'src/engine/dataloaders/dataloader.module'; import { DataloaderService } from 'src/engine/dataloaders/dataloader.service'; -import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module'; import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module'; import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module'; @@ -21,7 +21,7 @@ import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/wor useFactory: metadataModuleFactory, imports: [GraphQLConfigModule, DataloaderModule], inject: [ - EnvironmentService, + TwentyConfigService, ExceptionHandlerService, DataloaderService, CacheStorageNamespace.EngineWorkspace, diff --git a/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts b/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts index eeed12f257..c86eee4d9a 100644 --- a/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts @@ -1,20 +1,20 @@ import { YogaDriverConfig } from '@graphql-yoga/nestjs'; import GraphQLJSON from 'graphql-type-json'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { useCachedMetadata } from 'src/engine/api/graphql/graphql-config/hooks/use-cached-metadata'; import { useThrottler } from 'src/engine/api/graphql/graphql-config/hooks/use-throttler'; import { MetadataGraphQLApiModule } from 'src/engine/api/graphql/metadata-graphql-api.module'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { useGraphQLErrorHandlerHook } from 'src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { DataloaderService } from 'src/engine/dataloaders/dataloader.service'; import { renderApolloPlayground } from 'src/engine/utils/render-apollo-playground.util'; export const metadataModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, exceptionHandlerService: ExceptionHandlerService, dataloaderService: DataloaderService, cacheStorageService: CacheStorageService, @@ -28,8 +28,8 @@ export const metadataModuleFactory = async ( resolvers: { JSON: GraphQLJSON }, plugins: [ useThrottler({ - ttl: environmentService.get('API_RATE_LIMITING_TTL'), - limit: environmentService.get('API_RATE_LIMITING_LIMIT'), + ttl: twentyConfigService.get('API_RATE_LIMITING_TTL'), + limit: twentyConfigService.get('API_RATE_LIMITING_LIMIT'), identifyFn: (context) => { return context.req.user?.id ?? context.req.ip ?? 'anonymous'; }, @@ -49,7 +49,7 @@ export const metadataModuleFactory = async ( }), }; - if (environmentService.get('NODE_ENV') === NodeEnvironment.development) { + if (twentyConfigService.get('NODE_ENV') === NodeEnvironment.development) { config.renderGraphiQL = () => { return renderApolloPlayground({ path: 'metadata' }); }; diff --git a/packages/twenty-server/src/engine/api/rest/rest-api.service.ts b/packages/twenty-server/src/engine/api/rest/rest-api.service.ts index 128df3f96b..d69a01e6af 100644 --- a/packages/twenty-server/src/engine/api/rest/rest-api.service.ts +++ b/packages/twenty-server/src/engine/api/rest/rest-api.service.ts @@ -1,13 +1,13 @@ -import { Injectable } from '@nestjs/common'; import { HttpService } from '@nestjs/axios'; +import { Injectable } from '@nestjs/common'; -import { Request } from 'express'; import { AxiosResponse } from 'axios'; +import { Request } from 'express'; import { Query } from 'src/engine/api/rest/core/types/query.type'; -import { getServerUrl } from 'src/utils/get-server-url'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { RestApiException } from 'src/engine/api/rest/errors/RestApiException'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { getServerUrl } from 'src/utils/get-server-url'; export enum GraphqlApiType { CORE = 'core', @@ -17,14 +17,14 @@ export enum GraphqlApiType { @Injectable() export class RestApiService { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly httpService: HttpService, ) {} async call(graphqlApiType: GraphqlApiType, request: Request, data: Query) { const baseUrl = getServerUrl( request, - this.environmentService.get('SERVER_URL'), + this.twentyConfigService.get('SERVER_URL'), ); let response: AxiosResponse; const url = `${baseUrl}/${ diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel-health.service.spec.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel-health.service.spec.ts index c84a3af955..521e99df19 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel-health.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel-health.service.spec.ts @@ -8,7 +8,6 @@ import { HEALTH_INDICATORS } from 'src/engine/core-modules/admin-panel/constants import { SystemHealth } from 'src/engine/core-modules/admin-panel/dtos/system-health.dto'; import { AdminPanelHealthServiceStatus } from 'src/engine/core-modules/admin-panel/enums/admin-panel-health-service-status.enum'; import { QueueMetricsTimeRange } from 'src/engine/core-modules/admin-panel/enums/queue-metrics-time-range.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { HEALTH_ERROR_MESSAGES } from 'src/engine/core-modules/health/constants/health-error-messages.constants'; import { HealthIndicatorId } from 'src/engine/core-modules/health/enums/health-indicator-id.enum'; import { AppHealthIndicator } from 'src/engine/core-modules/health/indicators/app.health'; @@ -18,6 +17,7 @@ import { RedisHealthIndicator } from 'src/engine/core-modules/health/indicators/ import { WorkerHealthIndicator } from 'src/engine/core-modules/health/indicators/worker.health'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { RedisClientService } from 'src/engine/core-modules/redis-client/redis-client.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; jest.mock('bullmq'); @@ -29,7 +29,7 @@ describe('AdminPanelHealthService', () => { let connectedAccountHealth: jest.Mocked; let appHealth: jest.Mocked; let redisClient: jest.Mocked; - let environmentService: jest.Mocked; + let twentyConfigService: jest.Mocked; let loggerSpy: jest.SpyInstance; beforeEach(async () => { @@ -41,7 +41,7 @@ describe('AdminPanelHealthService', () => { redisClient = { getClient: jest.fn().mockReturnValue({} as Redis), } as any; - environmentService = { get: jest.fn() } as any; + twentyConfigService = { get: jest.fn() } as any; (Queue as unknown as jest.Mock) = jest.fn().mockImplementation(() => ({ getMetrics: jest.fn(), @@ -58,7 +58,7 @@ describe('AdminPanelHealthService', () => { { provide: ConnectedAccountHealth, useValue: connectedAccountHealth }, { provide: AppHealthIndicator, useValue: appHealth }, { provide: RedisClientService, useValue: redisClient }, - { provide: EnvironmentService, useValue: environmentService }, + { provide: TwentyConfigService, useValue: twentyConfigService }, ], }).compile(); diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts index a47d09ad7e..1c0605adac 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts @@ -10,17 +10,17 @@ import { } from 'src/engine/core-modules/auth/auth.exception'; import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; const UserFindOneMock = jest.fn(); const LoginTokenServiceGenerateLoginTokenMock = jest.fn(); -const EnvironmentServiceGetAllMock = jest.fn(); +const TwentyConfigServiceGetAllMock = jest.fn(); jest.mock( - '../../environment/constants/environment-variables-group-metadata', + 'src/engine/core-modules/twenty-config/constants/config-variables-group-metadata', () => ({ - ENVIRONMENT_VARIABLES_GROUP_METADATA: { + CONFIG_VARIABLES_GROUP_METADATA: { SERVER_CONFIG: { position: 100, description: 'Server config description', @@ -69,9 +69,9 @@ describe('AdminPanelService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { - getAll: EnvironmentServiceGetAllMock, + getAll: TwentyConfigServiceGetAllMock, }, }, ], @@ -157,9 +157,9 @@ describe('AdminPanelService', () => { expect(UserFindOneMock).toHaveBeenCalled(); }); - describe('getEnvironmentVariablesGrouped', () => { - it('should correctly group and sort environment variables', () => { - EnvironmentServiceGetAllMock.mockReturnValue({ + describe('getConfigVariablesGrouped', () => { + it('should correctly group and sort config variables', () => { + TwentyConfigServiceGetAllMock.mockReturnValue({ SERVER_URL: { value: 'http://localhost', metadata: { @@ -179,7 +179,7 @@ describe('AdminPanelService', () => { metadata: { group: 'SERVER_CONFIG', description: 'API Key', - sensitive: true, + isSensitive: true, }, }, OTHER_VAR: { @@ -191,7 +191,7 @@ describe('AdminPanelService', () => { }, }); - const result = service.getEnvironmentVariablesGrouped(); + const result = service.getConfigVariablesGrouped(); expect(result).toEqual({ groups: [ @@ -204,13 +204,13 @@ describe('AdminPanelService', () => { name: 'API_KEY', value: 'secret-key', description: 'API Key', - sensitive: true, + isSensitive: true, }, { name: 'SERVER_URL', value: 'http://localhost', description: 'Server URL', - sensitive: false, + isSensitive: false, }, ], }, @@ -223,7 +223,7 @@ describe('AdminPanelService', () => { name: 'RATE_LIMIT_TTL', value: '60', description: 'Rate limit TTL', - sensitive: false, + isSensitive: false, }, ], }, @@ -236,7 +236,7 @@ describe('AdminPanelService', () => { name: 'OTHER_VAR', value: 'other', description: 'Other var', - sensitive: false, + isSensitive: false, }, ], }, @@ -248,10 +248,10 @@ describe('AdminPanelService', () => { expect(result.groups[2].name).toBe('OTHER'); }); - it('should handle empty environment variables', () => { - EnvironmentServiceGetAllMock.mockReturnValue({}); + it('should handle empty config variables', () => { + TwentyConfigServiceGetAllMock.mockReturnValue({}); - const result = service.getEnvironmentVariablesGrouped(); + const result = service.getConfigVariablesGrouped(); expect(result).toEqual({ groups: [], @@ -259,7 +259,7 @@ describe('AdminPanelService', () => { }); it('should handle variables with undefined metadata fields', () => { - EnvironmentServiceGetAllMock.mockReturnValue({ + TwentyConfigServiceGetAllMock.mockReturnValue({ TEST_VAR: { value: 'test', metadata: { @@ -268,13 +268,13 @@ describe('AdminPanelService', () => { }, }); - const result = service.getEnvironmentVariablesGrouped(); + const result = service.getConfigVariablesGrouped(); expect(result.groups[0].variables[0]).toEqual({ name: 'TEST_VAR', value: 'test', description: undefined, - sensitive: false, + isSensitive: false, }); }); }); @@ -287,7 +287,7 @@ describe('AdminPanelService', () => { mockEnvironmentGet.mockReset(); mockAxiosGet.mockReset(); jest.spyOn(axios, 'get').mockImplementation(mockAxiosGet); - service['environmentService'].get = mockEnvironmentGet; + service['twentyConfigService'].get = mockEnvironmentGet; }); it('should return current and latest version when everything works', async () => { diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts index 42a5bfb5bd..976d761cb4 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts @@ -3,7 +3,7 @@ import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; import { AdminPanelHealthService } from 'src/engine/core-modules/admin-panel/admin-panel-health.service'; import { AdminPanelService } from 'src/engine/core-modules/admin-panel/admin-panel.service'; -import { EnvironmentVariablesOutput } from 'src/engine/core-modules/admin-panel/dtos/environment-variables.output'; +import { ConfigVariablesOutput } from 'src/engine/core-modules/admin-panel/dtos/config-variables.output'; import { ImpersonateInput } from 'src/engine/core-modules/admin-panel/dtos/impersonate.input'; import { ImpersonateOutput } from 'src/engine/core-modules/admin-panel/dtos/impersonate.output'; import { SystemHealth } from 'src/engine/core-modules/admin-panel/dtos/system-health.dto'; @@ -17,7 +17,6 @@ import { FeatureFlagException } from 'src/engine/core-modules/feature-flag/featu import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { UserInputError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { HealthIndicatorId } from 'src/engine/core-modules/health/enums/health-indicator-id.enum'; -import { WorkerHealthIndicator } from 'src/engine/core-modules/health/indicators/worker.health'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { AdminPanelGuard } from 'src/engine/guards/admin-panel-guard'; import { ImpersonateGuard } from 'src/engine/guards/impersonate-guard'; @@ -33,7 +32,6 @@ export class AdminPanelResolver { constructor( private adminService: AdminPanelService, private adminPanelHealthService: AdminPanelHealthService, - private workerHealthIndicator: WorkerHealthIndicator, private featureFlagService: FeatureFlagService, ) {} @@ -76,9 +74,9 @@ export class AdminPanelResolver { } @UseGuards(WorkspaceAuthGuard, UserAuthGuard, AdminPanelGuard) - @Query(() => EnvironmentVariablesOutput) - async getEnvironmentVariablesGrouped(): Promise { - return this.adminService.getEnvironmentVariablesGrouped(); + @Query(() => ConfigVariablesOutput) + async getConfigVariablesGrouped(): Promise { + return this.adminService.getConfigVariablesGrouped(); } @UseGuards(WorkspaceAuthGuard, UserAuthGuard, AdminPanelGuard) diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts index 110ea9a3b7..a729d0b662 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts @@ -5,9 +5,9 @@ import axios from 'axios'; import semver from 'semver'; import { Repository } from 'typeorm'; -import { EnvironmentVariable } from 'src/engine/core-modules/admin-panel/dtos/environment-variable.dto'; -import { EnvironmentVariablesGroupData } from 'src/engine/core-modules/admin-panel/dtos/environment-variables-group.dto'; -import { EnvironmentVariablesOutput } from 'src/engine/core-modules/admin-panel/dtos/environment-variables.output'; +import { ConfigVariable } from 'src/engine/core-modules/admin-panel/dtos/config-variable.dto'; +import { ConfigVariablesGroupData } from 'src/engine/core-modules/admin-panel/dtos/config-variables-group.dto'; +import { ConfigVariablesOutput } from 'src/engine/core-modules/admin-panel/dtos/config-variables.output'; import { UserLookup } from 'src/engine/core-modules/admin-panel/dtos/user-lookup.entity'; import { VersionInfo } from 'src/engine/core-modules/admin-panel/dtos/version-info.dto'; import { @@ -16,11 +16,11 @@ import { } from 'src/engine/core-modules/auth/auth.exception'; import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { ENVIRONMENT_VARIABLES_GROUP_METADATA } from 'src/engine/core-modules/environment/constants/environment-variables-group-metadata'; -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { CONFIG_VARIABLES_GROUP_METADATA } from 'src/engine/core-modules/twenty-config/constants/config-variables-group-metadata'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { userValidator } from 'src/engine/core-modules/user/user.validate'; @@ -28,7 +28,7 @@ import { userValidator } from 'src/engine/core-modules/user/user.validate'; export class AdminPanelService { constructor( private readonly loginTokenService: LoginTokenService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, @InjectRepository(User, 'core') private readonly userRepository: Repository, @@ -123,21 +123,18 @@ export class AdminPanelService { }; } - getEnvironmentVariablesGrouped(): EnvironmentVariablesOutput { - const rawEnvVars = this.environmentService.getAll(); - const groupedData = new Map< - EnvironmentVariablesGroup, - EnvironmentVariable[] - >(); + getConfigVariablesGrouped(): ConfigVariablesOutput { + const rawEnvVars = this.twentyConfigService.getAll(); + const groupedData = new Map(); for (const [varName, { value, metadata }] of Object.entries(rawEnvVars)) { const { group, description } = metadata; - const envVar: EnvironmentVariable = { + const envVar: ConfigVariable = { name: varName, description, value: String(value), - sensitive: metadata.sensitive ?? false, + isSensitive: metadata.isSensitive ?? false, }; if (!groupedData.has(group)) { @@ -147,20 +144,17 @@ export class AdminPanelService { groupedData.get(group)?.push(envVar); } - const groups: EnvironmentVariablesGroupData[] = Array.from( - groupedData.entries(), - ) + const groups: ConfigVariablesGroupData[] = Array.from(groupedData.entries()) .sort((a, b) => { - const positionA = ENVIRONMENT_VARIABLES_GROUP_METADATA[a[0]].position; - const positionB = ENVIRONMENT_VARIABLES_GROUP_METADATA[b[0]].position; + const positionA = CONFIG_VARIABLES_GROUP_METADATA[a[0]].position; + const positionB = CONFIG_VARIABLES_GROUP_METADATA[b[0]].position; return positionA - positionB; }) .map(([name, variables]) => ({ name, - description: ENVIRONMENT_VARIABLES_GROUP_METADATA[name].description, - isHiddenOnLoad: - ENVIRONMENT_VARIABLES_GROUP_METADATA[name].isHiddenOnLoad, + description: CONFIG_VARIABLES_GROUP_METADATA[name].description, + isHiddenOnLoad: CONFIG_VARIABLES_GROUP_METADATA[name].isHiddenOnLoad, variables: variables.sort((a, b) => a.name.localeCompare(b.name)), })); @@ -168,7 +162,7 @@ export class AdminPanelService { } async getVersionInfo(): Promise { - const currentVersion = this.environmentService.get('APP_VERSION'); + const currentVersion = this.twentyConfigService.get('APP_VERSION'); try { const response = await axios.get( diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variable.dto.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variable.dto.ts similarity index 75% rename from packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variable.dto.ts rename to packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variable.dto.ts index fa1a7c1e08..290731f3e7 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variable.dto.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variable.dto.ts @@ -1,7 +1,7 @@ import { Field, ObjectType } from '@nestjs/graphql'; @ObjectType() -export class EnvironmentVariable { +export class ConfigVariable { @Field() name: string; @@ -12,5 +12,5 @@ export class EnvironmentVariable { value: string; @Field() - sensitive: boolean; + isSensitive: boolean; } diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables-group.dto.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables-group.dto.ts new file mode 100644 index 0000000000..b2a7f9f84e --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables-group.dto.ts @@ -0,0 +1,23 @@ +import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; + +import { ConfigVariable } from 'src/engine/core-modules/admin-panel/dtos/config-variable.dto'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; + +registerEnumType(ConfigVariablesGroup, { + name: 'ConfigVariablesGroup', +}); + +@ObjectType() +export class ConfigVariablesGroupData { + @Field(() => [ConfigVariable]) + variables: ConfigVariable[]; + + @Field(() => ConfigVariablesGroup) + name: ConfigVariablesGroup; + + @Field(() => String, { defaultValue: '' }) + description: string; + + @Field(() => Boolean, { defaultValue: false }) + isHiddenOnLoad: boolean; +} diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables.output.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables.output.ts new file mode 100644 index 0000000000..8df5acc606 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables.output.ts @@ -0,0 +1,9 @@ +import { Field, ObjectType } from '@nestjs/graphql'; + +import { ConfigVariablesGroupData } from 'src/engine/core-modules/admin-panel/dtos/config-variables-group.dto'; + +@ObjectType() +export class ConfigVariablesOutput { + @Field(() => [ConfigVariablesGroupData]) + groups: ConfigVariablesGroupData[]; +} diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables-group.dto.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables-group.dto.ts deleted file mode 100644 index bc75ceb2cf..0000000000 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables-group.dto.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; - -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; - -import { EnvironmentVariable } from './environment-variable.dto'; - -registerEnumType(EnvironmentVariablesGroup, { - name: 'EnvironmentVariablesGroup', -}); - -@ObjectType() -export class EnvironmentVariablesGroupData { - @Field(() => [EnvironmentVariable]) - variables: EnvironmentVariable[]; - - @Field(() => EnvironmentVariablesGroup) - name: EnvironmentVariablesGroup; - - @Field(() => String, { defaultValue: '' }) - description: string; - - @Field(() => Boolean, { defaultValue: false }) - isHiddenOnLoad: boolean; -} diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables.output.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables.output.ts deleted file mode 100644 index 02e98d388b..0000000000 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables.output.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Field, ObjectType } from '@nestjs/graphql'; - -import { EnvironmentVariablesGroupData } from './environment-variables-group.dto'; - -@ObjectType() -export class EnvironmentVariablesOutput { - @Field(() => [EnvironmentVariablesGroupData]) - groups: EnvironmentVariablesGroupData[]; -} diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts index 36feaed4d4..c4818ff2c3 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts @@ -1,8 +1,8 @@ import { HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { AnalyticsService } from './analytics.service'; @@ -14,7 +14,7 @@ describe('AnalyticsService', () => { providers: [ AnalyticsService, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: {}, }, { diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts index b0cc7788bb..01e3fcebc7 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; type CreateEventInput = { action: string; @@ -9,14 +9,14 @@ type CreateEventInput = { @Injectable() export class AnalyticsService { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} async create( createEventInput: CreateEventInput, userId: string | null | undefined, workspaceId: string | null | undefined, ) { - if (!this.environmentService.get('ANALYTICS_ENABLED')) { + if (!this.twentyConfigService.get('ANALYTICS_ENABLED')) { return { success: true }; } diff --git a/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.service.ts b/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.service.ts index b6bdefde34..b9b57f43f1 100644 --- a/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.service.ts +++ b/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.service.ts @@ -16,7 +16,7 @@ import { import { approvedAccessDomainValidator } from 'src/engine/core-modules/approved-access-domain/approved-access-domain.validate'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { isWorkDomain } from 'src/utils/is-work-email'; @@ -28,7 +28,7 @@ export class ApprovedAccessDomainService { @InjectRepository(ApprovedAccessDomainEntity, 'core') private readonly approvedAccessDomainRepository: Repository, private readonly emailService: EmailService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, ) {} @@ -70,7 +70,7 @@ export class ApprovedAccessDomainService { firstName: sender.firstName, lastName: sender.lastName, }, - serverUrl: this.environmentService.get('SERVER_URL'), + serverUrl: this.twentyConfigService.get('SERVER_URL'), locale: 'en' as keyof typeof APP_LOCALES, }); const html = await render(emailTemplate); @@ -79,7 +79,7 @@ export class ApprovedAccessDomainService { }); await this.emailService.send({ - from: `${sender.firstName} ${sender.lastName} (via Twenty) <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + from: `${sender.firstName} ${sender.lastName} (via Twenty) <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, to, subject: 'Approve your access domain', text, @@ -94,7 +94,7 @@ export class ApprovedAccessDomainService { JSON.stringify({ id: approvedAccessDomain.id, domain: approvedAccessDomain.domain, - key: this.environmentService.get('APP_SECRET'), + key: this.twentyConfigService.get('APP_SECRET'), }), ) .digest('hex'); diff --git a/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.spec.ts b/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.spec.ts index 6914161c43..e18db65b56 100644 --- a/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.spec.ts @@ -3,16 +3,16 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { DeleteResult, Repository } from 'typeorm'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { User } from 'src/engine/core-modules/user/user.entity'; -import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { ApprovedAccessDomain } from 'src/engine/core-modules/approved-access-domain/approved-access-domain.entity'; import { ApprovedAccessDomainException, ApprovedAccessDomainExceptionCode, } from 'src/engine/core-modules/approved-access-domain/approved-access-domain.exception'; +import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { ApprovedAccessDomainService } from './approved-access-domain.service'; @@ -20,7 +20,7 @@ describe('ApprovedAccessDomainService', () => { let service: ApprovedAccessDomainService; let approvedAccessDomainRepository: Repository; let emailService: EmailService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let domainManagerService: DomainManagerService; beforeEach(async () => { @@ -43,7 +43,7 @@ describe('ApprovedAccessDomainService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -64,7 +64,7 @@ describe('ApprovedAccessDomainService', () => { getRepositoryToken(ApprovedAccessDomain, 'core'), ); emailService = module.get(EmailService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); domainManagerService = module.get(DomainManagerService); }); @@ -267,7 +267,7 @@ describe('ApprovedAccessDomainService', () => { .mockReturnValue(new URL('https://sub.twenty.com')); jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { if (key === 'EMAIL_FROM_ADDRESS') return 'no-reply@example.com'; if (key === 'SERVER_URL') return 'https://api.example.com'; diff --git a/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts b/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts index cbac8c65d7..15574a13fe 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts @@ -22,9 +22,9 @@ import { GoogleAPIsService } from 'src/engine/core-modules/auth/services/google- import { TransientTokenService } from 'src/engine/core-modules/auth/token/services/transient-token.service'; import { GoogleAPIsRequest } from 'src/engine/core-modules/auth/types/google-api-request.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Controller('auth/google-apis') @@ -33,7 +33,7 @@ export class GoogleAPIsAuthController { constructor( private readonly googleAPIsService: GoogleAPIsService, private readonly transientTokenService: TransientTokenService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly onboardingService: OnboardingService, private readonly domainManagerService: DomainManagerService, private readonly guardRedirectService: GuardRedirectService, @@ -123,7 +123,7 @@ export class GoogleAPIsAuthController { this.guardRedirectService.getRedirectErrorUrlAndCaptureExceptions( err, workspace ?? { - subdomain: this.environmentService.get('DEFAULT_SUBDOMAIN'), + subdomain: this.twentyConfigService.get('DEFAULT_SUBDOMAIN'), customDomain: null, }, ), diff --git a/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-apis-auth.controller.ts b/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-apis-auth.controller.ts index d7ca0509a6..c0e062804b 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-apis-auth.controller.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-apis-auth.controller.ts @@ -22,9 +22,9 @@ import { MicrosoftAPIsService } from 'src/engine/core-modules/auth/services/micr import { TransientTokenService } from 'src/engine/core-modules/auth/token/services/transient-token.service'; import { MicrosoftAPIsRequest } from 'src/engine/core-modules/auth/types/microsoft-api-request.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Controller('auth/microsoft-apis') @@ -33,7 +33,7 @@ export class MicrosoftAPIsAuthController { constructor( private readonly microsoftAPIsService: MicrosoftAPIsService, private readonly transientTokenService: TransientTokenService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, private readonly onboardingService: OnboardingService, private readonly guardRedirectService: GuardRedirectService, @@ -130,7 +130,7 @@ export class MicrosoftAPIsAuthController { this.guardRedirectService.getRedirectErrorUrlAndCaptureExceptions( err, workspace ?? { - subdomain: this.environmentService.get('DEFAULT_SUBDOMAIN'), + subdomain: this.twentyConfigService.get('DEFAULT_SUBDOMAIN'), customDomain: null, }, ), diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/enterprise-features-enabled.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/enterprise-features-enabled.guard.ts index 2f7e925871..4c547a2696 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/enterprise-features-enabled.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/enterprise-features-enabled.guard.ts @@ -6,19 +6,19 @@ import { AuthException, AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class EnterpriseFeaturesEnabledGuard implements CanActivate { constructor( private readonly guardRedirectService: GuardRedirectService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} canActivate(context: ExecutionContext): boolean { try { - if (!this.environmentService.get('ENTERPRISE_KEY')) { + if (!this.twentyConfigService.get('ENTERPRISE_KEY')) { throw new AuthException( 'Enterprise key missing', AuthExceptionCode.MISSING_ENVIRONMENT_VARIABLE, diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts index 3e6c57fac8..0d32c2fa4b 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts @@ -7,8 +7,8 @@ import { } from 'src/engine/core-modules/auth/auth.exception'; import { GoogleAPIsOauthExchangeCodeForTokenStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy'; import { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class GoogleAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( @@ -16,7 +16,7 @@ export class GoogleAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( ) { constructor( private readonly guardRedirectService: GuardRedirectService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) { super(); } @@ -27,8 +27,8 @@ export class GoogleAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( const state = JSON.parse(request.query.state); if ( - !this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED') && - !this.environmentService.get('CALENDAR_PROVIDER_GOOGLE_ENABLED') + !this.twentyConfigService.get('MESSAGING_PROVIDER_GMAIL_ENABLED') && + !this.twentyConfigService.get('CALENDAR_PROVIDER_GOOGLE_ENABLED') ) { throw new AuthException( 'Google apis auth is not enabled', @@ -36,7 +36,7 @@ export class GoogleAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( ); } - new GoogleAPIsOauthExchangeCodeForTokenStrategy(this.environmentService); + new GoogleAPIsOauthExchangeCodeForTokenStrategy(this.twentyConfigService); setRequestExtraParams(request, { transientToken: state.transientToken, diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts index 834fdd7d8e..038aba1abd 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts @@ -11,15 +11,15 @@ import { import { GoogleAPIsOauthRequestCodeStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy'; import { TransientTokenService } from 'src/engine/core-modules/auth/token/services/transient-token.service'; import { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Injectable() export class GoogleAPIsOauthRequestCodeGuard extends AuthGuard('google-apis') { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly transientTokenService: TransientTokenService, private readonly guardRedirectService: GuardRedirectService, @InjectRepository(Workspace, 'core') @@ -57,8 +57,8 @@ export class GoogleAPIsOauthRequestCodeGuard extends AuthGuard('google-apis') { }); if ( - !this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED') && - !this.environmentService.get('CALENDAR_PROVIDER_GOOGLE_ENABLED') + !this.twentyConfigService.get('MESSAGING_PROVIDER_GMAIL_ENABLED') && + !this.twentyConfigService.get('CALENDAR_PROVIDER_GOOGLE_ENABLED') ) { throw new AuthException( 'Google apis auth is not enabled', @@ -66,7 +66,7 @@ export class GoogleAPIsOauthRequestCodeGuard extends AuthGuard('google-apis') { ); } - new GoogleAPIsOauthRequestCodeStrategy(this.environmentService); + new GoogleAPIsOauthRequestCodeStrategy(this.twentyConfigService); return (await super.canActivate(context)) as boolean; } catch (err) { diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts index 731caf7694..1d57f750e4 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts @@ -5,26 +5,26 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { GoogleStrategy } from 'src/engine/core-modules/auth/strategies/google.auth.strategy'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class GoogleProviderEnabledGuard implements CanActivate { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly guardRedirectService: GuardRedirectService, ) {} canActivate(context: ExecutionContext): boolean { try { - if (!this.environmentService.get('AUTH_GOOGLE_ENABLED')) { + if (!this.twentyConfigService.get('AUTH_GOOGLE_ENABLED')) { throw new AuthException( 'Google auth is not enabled', AuthExceptionCode.GOOGLE_API_AUTH_DISABLED, ); } - new GoogleStrategy(this.environmentService); + new GoogleStrategy(this.twentyConfigService); return true; } catch (err) { diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-exchange-code-for-token.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-exchange-code-for-token.guard.ts index c814fe821b..d26c5fdf2e 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-exchange-code-for-token.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-exchange-code-for-token.guard.ts @@ -7,8 +7,8 @@ import { } from 'src/engine/core-modules/auth/auth.exception'; import { MicrosoftAPIsOauthExchangeCodeForTokenStrategy } from 'src/engine/core-modules/auth/strategies/microsoft-apis-oauth-exchange-code-for-token.auth.strategy'; import { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class MicrosoftAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( @@ -16,7 +16,7 @@ export class MicrosoftAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( ) { constructor( private readonly guardRedirectService: GuardRedirectService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) { super(); } @@ -27,8 +27,8 @@ export class MicrosoftAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( const state = JSON.parse(request.query.state); if ( - !this.environmentService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED') && - !this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') + !this.twentyConfigService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED') && + !this.twentyConfigService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') ) { throw new AuthException( 'Microsoft apis auth is not enabled', @@ -37,7 +37,7 @@ export class MicrosoftAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( } new MicrosoftAPIsOauthExchangeCodeForTokenStrategy( - this.environmentService, + this.twentyConfigService, ); setRequestExtraParams(request, { diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-request-code.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-request-code.guard.ts index 877a1d0074..82504a2a9f 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-request-code.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-request-code.guard.ts @@ -11,17 +11,17 @@ import { import { MicrosoftAPIsOauthRequestCodeStrategy } from 'src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy'; import { TransientTokenService } from 'src/engine/core-modules/auth/token/services/transient-token.service'; import { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Injectable() export class MicrosoftAPIsOauthRequestCodeGuard extends AuthGuard( 'microsoft-apis', ) { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly transientTokenService: TransientTokenService, private readonly guardRedirectService: GuardRedirectService, @InjectRepository(Workspace, 'core') @@ -38,8 +38,8 @@ export class MicrosoftAPIsOauthRequestCodeGuard extends AuthGuard( try { if ( - !this.environmentService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED') && - !this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') + !this.twentyConfigService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED') && + !this.twentyConfigService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') ) { throw new AuthException( 'Microsoft apis auth is not enabled', @@ -58,7 +58,7 @@ export class MicrosoftAPIsOauthRequestCodeGuard extends AuthGuard( id: workspaceId, }); - new MicrosoftAPIsOauthRequestCodeStrategy(this.environmentService); + new MicrosoftAPIsOauthRequestCodeStrategy(this.twentyConfigService); setRequestExtraParams(request, { transientToken: request.query.transientToken, redirectLocation: request.query.redirectLocation, diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts index 9b29bae0ba..fdba7cc317 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts @@ -5,26 +5,26 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { MicrosoftStrategy } from 'src/engine/core-modules/auth/strategies/microsoft.auth.strategy'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class MicrosoftProviderEnabledGuard implements CanActivate { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly guardRedirectService: GuardRedirectService, ) {} canActivate(context: ExecutionContext): boolean { try { - if (!this.environmentService.get('AUTH_MICROSOFT_ENABLED')) { + if (!this.twentyConfigService.get('AUTH_MICROSOFT_ENABLED')) { throw new AuthException( 'Microsoft auth is not enabled', AuthExceptionCode.MICROSOFT_API_AUTH_DISABLED, ); } - new MicrosoftStrategy(this.environmentService); + new MicrosoftStrategy(this.twentyConfigService); return true; } catch (err) { diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.spec.ts index 7159269ec8..bff67b54ed 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.spec.ts @@ -1,14 +1,14 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ApiKeyService } from './api-key.service'; describe('ApiKeyService', () => { let service: ApiKeyService; let jwtWrapperService: JwtWrapperService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -22,7 +22,7 @@ describe('ApiKeyService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -32,7 +32,7 @@ describe('ApiKeyService', () => { service = module.get(ApiKeyService); jwtWrapperService = module.get(JwtWrapperService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); it('should be defined', () => { @@ -51,7 +51,7 @@ describe('ApiKeyService', () => { const apiKeyId = 'api-key-id'; const mockToken = 'mock-token'; - jest.spyOn(environmentService, 'get').mockReturnValue('1h'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('1h'); jest.spyOn(jwtWrapperService, 'sign').mockReturnValue(mockToken); jest .spyOn(jwtWrapperService, 'generateAppSecret') diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.ts index f6bad82221..85c51dcac5 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.ts @@ -1,14 +1,14 @@ import { Injectable } from '@nestjs/common'; import { ApiKeyToken } from 'src/engine/core-modules/auth/dto/token.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class ApiKeyService { constructor( private readonly jwtWrapperService: JwtWrapperService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async generateApiKeyToken( diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.service.ts index 30ef9996a5..a779b8c58b 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.service.ts @@ -3,16 +3,16 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { WorkspaceAuthProvider } from 'src/engine/core-modules/workspace/types/workspace.type'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Injectable() export class AuthSsoService { constructor( @InjectRepository(Workspace, 'core') private readonly workspaceRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} private getAuthProviderColumnNameByProvider( @@ -41,7 +41,7 @@ export class AuthSsoService { workspaceId?: string, ) { if ( - this.environmentService.get('IS_MULTIWORKSPACE_ENABLED') && + this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED') && !workspaceId ) { // Multi-workspace enable mode but on non workspace url. diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.spec.ts index 7f2ff2ecaf..1fbba06ad6 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.spec.ts @@ -4,13 +4,13 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { AuthSsoService } from 'src/engine/core-modules/auth/services/auth-sso.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; describe('AuthSsoService', () => { let authSsoService: AuthSsoService; let workspaceRepository: Repository; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -23,7 +23,7 @@ describe('AuthSsoService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -35,7 +35,7 @@ describe('AuthSsoService', () => { workspaceRepository = module.get>( getRepositoryToken(Workspace, 'core'), ); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); describe('findWorkspaceFromWorkspaceIdOrAuthProvider', () => { @@ -67,7 +67,7 @@ describe('AuthSsoService', () => { const email = 'test@example.com'; const mockWorkspace = { id: 'workspace-id-456' } as Workspace; - jest.spyOn(environmentService, 'get').mockReturnValue(true); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(true); jest .spyOn(workspaceRepository, 'findOne') .mockResolvedValue(mockWorkspace); @@ -97,7 +97,7 @@ describe('AuthSsoService', () => { }); it('should return undefined if no workspace is found when multi-workspace mode is enabled', async () => { - jest.spyOn(environmentService, 'get').mockReturnValue(true); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(true); jest.spyOn(workspaceRepository, 'findOne').mockResolvedValue(null); const result = @@ -110,7 +110,7 @@ describe('AuthSsoService', () => { }); it('should throw an error for an invalid authProvider', async () => { - jest.spyOn(environmentService, 'get').mockReturnValue(true); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(true); await expect( authSsoService.findWorkspaceFromWorkspaceIdOrAuthProvider({ diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts index c18b794aea..3dc84386d6 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts @@ -16,7 +16,7 @@ import { RefreshTokenService } from 'src/engine/core-modules/auth/token/services import { ExistingUserOrNewUser } from 'src/engine/core-modules/auth/types/signInUp.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -35,7 +35,7 @@ const workspaceInvitationGetOneWorkspaceInvitationMock = jest.fn(); const workspaceInvitationValidatePersonalInvitationMock = jest.fn(); const userWorkspaceAddUserToWorkspaceMock = jest.fn(); -const environmentServiceGetMock = jest.fn(); +const twentyConfigServiceGetMock = jest.fn(); describe('AuthService', () => { let service: AuthService; @@ -75,9 +75,9 @@ describe('AuthService', () => { useValue: {}, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { - get: environmentServiceGetMock, + get: twentyConfigServiceGetMock, }, }, { @@ -138,7 +138,7 @@ describe('AuthService', () => { }); beforeEach(() => { - environmentServiceGetMock.mockReturnValue(false); + twentyConfigServiceGetMock.mockReturnValue(false); }); it('should be defined', async () => { diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts index 64d03914a0..9b7117301f 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts @@ -13,7 +13,7 @@ import { APP_LOCALES } from 'twenty-shared/translations'; import { isDefined } from 'twenty-shared/utils'; import { Repository } from 'typeorm'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { AppToken, @@ -51,7 +51,7 @@ import { import { WorkspaceSubdomainCustomDomainAndIsCustomDomainEnabledType } from 'src/engine/core-modules/domain-manager/domain-manager.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -77,7 +77,7 @@ export class AuthService { private readonly workspaceRepository: Repository, @InjectRepository(User, 'core') private readonly userRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly emailService: EmailService, @InjectRepository(AppToken, 'core') private readonly appTokenRepository: Repository, @@ -164,7 +164,7 @@ export class AuthService { ); } - const isEmailVerificationRequired = this.environmentService.get( + const isEmailVerificationRequired = this.twentyConfigService.get( 'IS_EMAIL_VERIFICATION_REQUIRED', ); @@ -323,10 +323,10 @@ export class AuthService { id: 'chrome', name: 'Chrome Extension', redirectUrl: - this.environmentService.get('NODE_ENV') === + this.twentyConfigService.get('NODE_ENV') === NodeEnvironment.development ? authorizeAppInput.redirectUrl - : `https://${this.environmentService.get( + : `https://${this.twentyConfigService.get( 'CHROME_EXTENSION_ID', )}.chromiumapp.org/`, }, @@ -448,9 +448,9 @@ export class AuthService { i18n.activate(locale); this.emailService.send({ - from: `${this.environmentService.get( + from: `${this.twentyConfigService.get( 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + )} <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, to: user.email, subject: t`Your Password Has Been Successfully Changed`, text, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts index 3621f4737b..8baa9a08cc 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts @@ -1,16 +1,16 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { ConnectedAccountProvider } from 'twenty-shared/types'; import { EntityManager, Repository } from 'typeorm'; import { v4 } from 'uuid'; -import { ConnectedAccountProvider } from 'twenty-shared/types'; import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action'; import { getGoogleApisOauthScopes } from 'src/engine/core-modules/auth/utils/get-google-apis-oauth-scopes'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; @@ -45,7 +45,7 @@ export class GoogleAPIsService { private readonly messageQueueService: MessageQueueService, @InjectMessageQueue(MessageQueue.calendarQueue) private readonly calendarQueueService: MessageQueueService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly accountsToReconnectService: AccountsToReconnectService, private readonly workspaceEventEmitter: WorkspaceEventEmitter, @InjectRepository(ObjectMetadataEntity, 'metadata') @@ -69,7 +69,7 @@ export class GoogleAPIsService { messageVisibility, } = input; - const isCalendarEnabled = this.environmentService.get( + const isCalendarEnabled = this.twentyConfigService.get( 'CALENDAR_PROVIDER_GOOGLE_ENABLED', ); @@ -300,7 +300,7 @@ export class GoogleAPIsService { } }); - if (this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) { + if (this.twentyConfigService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) { const messageChannels = await messageChannelRepository.find({ where: { connectedAccountId: newOrExistingConnectedAccountId, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts index 0ca3ed6fd5..de544b3028 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts @@ -1,16 +1,16 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { ConnectedAccountProvider } from 'twenty-shared/types'; import { EntityManager, Repository } from 'typeorm'; import { v4 } from 'uuid'; -import { ConnectedAccountProvider } from 'twenty-shared/types'; import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action'; import { getMicrosoftApisOauthScopes } from 'src/engine/core-modules/auth/utils/get-microsoft-apis-oauth-scopes'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; @@ -51,7 +51,7 @@ export class MicrosoftAPIsService { private readonly workspaceEventEmitter: WorkspaceEventEmitter, @InjectRepository(ObjectMetadataEntity, 'metadata') private readonly objectMetadataRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async refreshMicrosoftRefreshToken(input: { @@ -200,7 +200,7 @@ export class MicrosoftAPIsService { }); if ( - this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') + this.twentyConfigService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') ) { const newCalendarChannel = await calendarChannelRepository.save( { @@ -328,7 +328,7 @@ export class MicrosoftAPIsService { } }); - if (this.environmentService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED')) { + if (this.twentyConfigService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED')) { const messageChannels = await messageChannelRepository.find({ where: { connectedAccountId: newOrExistingConnectedAccountId, @@ -346,7 +346,7 @@ export class MicrosoftAPIsService { } } - if (this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED')) { + if (this.twentyConfigService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED')) { const calendarChannels = await calendarChannelRepository.find({ where: { connectedAccountId: newOrExistingConnectedAccountId, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.spec.ts index 2939b9b3b2..c573a6e81d 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.spec.ts @@ -11,7 +11,7 @@ import { import { AuthException } from 'src/engine/core-modules/auth/auth.exception'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @@ -23,7 +23,7 @@ describe('ResetPasswordService', () => { let workspaceRepository: Repository; let appTokenRepository: Repository; let emailService: EmailService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let domainManagerService: DomainManagerService; beforeEach(async () => { @@ -62,7 +62,7 @@ describe('ResetPasswordService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -81,7 +81,7 @@ describe('ResetPasswordService', () => { getRepositoryToken(AppToken, 'core'), ); emailService = module.get(EmailService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); domainManagerService = module.get(DomainManagerService); }); @@ -99,7 +99,7 @@ describe('ResetPasswordService', () => { .mockResolvedValue(mockUser as User); jest.spyOn(appTokenRepository, 'findOne').mockResolvedValue(null); jest.spyOn(appTokenRepository, 'save').mockResolvedValue({} as AppToken); - jest.spyOn(environmentService, 'get').mockReturnValue('1h'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('1h'); const result = await service.generatePasswordResetToken( 'test@example.com', @@ -165,7 +165,7 @@ describe('ResetPasswordService', () => { .spyOn(workspaceRepository, 'findOneBy') .mockResolvedValue({ id: 'workspace-id' } as Workspace); jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockReturnValue('http://localhost:3000'); jest .spyOn(domainManagerService, 'buildWorkspaceURL') diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.ts index 7a7f567c67..997c0f7c56 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.ts @@ -26,7 +26,7 @@ import { PasswordResetToken } from 'src/engine/core-modules/auth/dto/token.entit import { ValidatePasswordResetToken } from 'src/engine/core-modules/auth/dto/validate-password-reset-token.entity'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate'; @@ -34,7 +34,7 @@ import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace. @Injectable() export class ResetPasswordService { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, @InjectRepository(User, 'core') private readonly userRepository: Repository, @@ -60,7 +60,7 @@ export class ResetPasswordService { ); } - const expiresIn = this.environmentService.get( + const expiresIn = this.twentyConfigService.get( 'PASSWORD_RESET_TOKEN_EXPIRES_IN', ); @@ -164,9 +164,9 @@ export class ResetPasswordService { i18n.activate(locale); this.emailService.send({ - from: `${this.environmentService.get( + from: `${this.twentyConfigService.get( 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + )} <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, to: email, subject: t`Action Needed to Reset Password`, text, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts index d6caff5605..3a079cb718 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts @@ -2,8 +2,8 @@ import { HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; +import { Repository } from 'typeorm'; import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; import { @@ -17,10 +17,10 @@ import { SignInUpBaseParams, } from 'src/engine/core-modules/auth/types/signInUp.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; @@ -42,7 +42,7 @@ describe('SignInUpService', () => { let fileUploadService: FileUploadService; let workspaceInvitationService: WorkspaceInvitationService; let userWorkspaceService: UserWorkspaceService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let domainManagerService: DomainManagerService; beforeEach(async () => { @@ -98,7 +98,7 @@ describe('SignInUpService', () => { useValue: {}, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -143,7 +143,7 @@ describe('SignInUpService', () => { ); userWorkspaceService = module.get(UserWorkspaceService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); domainManagerService = module.get(DomainManagerService); }); @@ -242,7 +242,7 @@ describe('SignInUpService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue(false); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(false); jest.spyOn(WorkspaceRepository, 'count').mockResolvedValue(0); jest.spyOn(WorkspaceRepository, 'create').mockReturnValue({} as Workspace); jest.spyOn(WorkspaceRepository, 'save').mockResolvedValue({ @@ -292,7 +292,7 @@ describe('SignInUpService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue(false); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(false); jest .spyOn(userWorkspaceService, 'addUserToWorkspaceIfUserNotInWorkspace') .mockResolvedValue(undefined); @@ -324,7 +324,7 @@ describe('SignInUpService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue(false); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(false); jest .spyOn(userWorkspaceService, 'checkUserWorkspaceExists') .mockResolvedValue(null); @@ -349,7 +349,7 @@ describe('SignInUpService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue(false); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(false); jest.spyOn(WorkspaceRepository, 'count').mockResolvedValue(0); jest.spyOn(WorkspaceRepository, 'create').mockReturnValue({} as Workspace); jest.spyOn(WorkspaceRepository, 'save').mockResolvedValue({ diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts index 5a59d01a88..beb6715b39 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts @@ -3,10 +3,10 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import FileType from 'file-type'; -import { Repository } from 'typeorm'; -import { v4 } from 'uuid'; import { TWENTY_ICONS_BASE_URL } from 'twenty-shared/constants'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; +import { Repository } from 'typeorm'; +import { v4 } from 'uuid'; import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface'; @@ -28,10 +28,10 @@ import { SignInUpNewUserPayload, } from 'src/engine/core-modules/auth/types/signInUp.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -55,7 +55,7 @@ export class SignInUpService { private readonly userWorkspaceService: UserWorkspaceService, private readonly onboardingService: OnboardingService, private readonly httpService: HttpService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, private readonly userService: UserService, private readonly userRoleService: UserRoleService, @@ -324,7 +324,7 @@ export class SignInUpService { ); } - if (!this.environmentService.get('IS_MULTIWORKSPACE_ENABLED')) { + if (!this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED')) { const workspacesCount = await this.workspaceRepository.count(); // if the workspace doesn't exist it means it's the first user of the workspace diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts index 36351e2a49..de7c1943f5 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts @@ -3,8 +3,8 @@ import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-google-oauth20'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { getGoogleApisOauthScopes } from 'src/engine/core-modules/auth/utils/get-google-apis-oauth-scopes'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type GoogleAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -16,13 +16,13 @@ export class GoogleAPIsOauthCommonStrategy extends PassportStrategy( Strategy, 'google-apis', ) { - constructor(environmentService: EnvironmentService) { + constructor(twentyConfigService: TwentyConfigService) { const scopes = getGoogleApisOauthScopes(); super({ - clientID: environmentService.get('AUTH_GOOGLE_CLIENT_ID'), - clientSecret: environmentService.get('AUTH_GOOGLE_CLIENT_SECRET'), - callbackURL: environmentService.get('AUTH_GOOGLE_APIS_CALLBACK_URL'), + clientID: twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'), + clientSecret: twentyConfigService.get('AUTH_GOOGLE_CLIENT_SECRET'), + callbackURL: twentyConfigService.get('AUTH_GOOGLE_APIS_CALLBACK_URL'), scope: scopes, passReqToCallback: true, }); diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts index 1b89939b62..f10e63f5ad 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts @@ -4,7 +4,7 @@ import { VerifyCallback } from 'passport-google-oauth20'; import { GoogleAPIsOauthCommonStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy'; import { GoogleAPIsRequest } from 'src/engine/core-modules/auth/types/google-api-request.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type GoogleAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -12,8 +12,8 @@ export type GoogleAPIScopeConfig = { @Injectable() export class GoogleAPIsOauthExchangeCodeForTokenStrategy extends GoogleAPIsOauthCommonStrategy { - constructor(environmentService: EnvironmentService) { - super(environmentService); + constructor(twentyConfigService: TwentyConfigService) { + super(twentyConfigService); } async validate( diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts index 0eda93a5b4..b5339f5afb 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { GoogleAPIsOauthCommonStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type GoogleAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -10,8 +10,8 @@ export type GoogleAPIScopeConfig = { @Injectable() export class GoogleAPIsOauthRequestCodeStrategy extends GoogleAPIsOauthCommonStrategy { - constructor(environmentService: EnvironmentService) { - super(environmentService); + constructor(twentyConfigService: TwentyConfigService) { + super(twentyConfigService); } authenticate(req: any, options: any) { diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts index 5a6fe9e094..d2f132eaf2 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts @@ -5,7 +5,7 @@ import { Request } from 'express'; import { Strategy, VerifyCallback } from 'passport-google-oauth20'; import { APP_LOCALES } from 'twenty-shared/translations'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type GoogleRequest = Omit< Request, @@ -26,11 +26,11 @@ export type GoogleRequest = Omit< @Injectable() export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { - constructor(environmentService: EnvironmentService) { + constructor(twentyConfigService: TwentyConfigService) { super({ - clientID: environmentService.get('AUTH_GOOGLE_CLIENT_ID'), - clientSecret: environmentService.get('AUTH_GOOGLE_CLIENT_SECRET'), - callbackURL: environmentService.get('AUTH_GOOGLE_CALLBACK_URL'), + clientID: twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'), + clientSecret: twentyConfigService.get('AUTH_GOOGLE_CLIENT_SECRET'), + callbackURL: twentyConfigService.get('AUTH_GOOGLE_CALLBACK_URL'), scope: ['email', 'profile'], passReqToCallback: true, }); diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts index 8eea41009f..012e448326 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts @@ -14,8 +14,8 @@ import { AuthContext, JwtPayload, } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @@ -25,7 +25,7 @@ import { ApiKeyWorkspaceEntity } from 'src/modules/api-key/standard-objects/api- @Injectable() export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly jwtWrapperService: JwtWrapperService, private readonly typeORMService: TypeORMService, private readonly dataSourceService: DataSourceService, diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy.ts index e0be81b2e0..69d33fc8bb 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy.ts @@ -4,7 +4,7 @@ import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-microsoft'; import { getMicrosoftApisOauthScopes } from 'src/engine/core-modules/auth/utils/get-microsoft-apis-oauth-scopes'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type MicrosoftAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -16,14 +16,14 @@ export class MicrosoftAPIsOauthCommonStrategy extends PassportStrategy( Strategy, 'microsoft-apis', ) { - constructor(environmentService: EnvironmentService) { + constructor(twentyConfigService: TwentyConfigService) { const scopes = getMicrosoftApisOauthScopes(); super({ - clientID: environmentService.get('AUTH_MICROSOFT_CLIENT_ID'), - clientSecret: environmentService.get('AUTH_MICROSOFT_CLIENT_SECRET'), + clientID: twentyConfigService.get('AUTH_MICROSOFT_CLIENT_ID'), + clientSecret: twentyConfigService.get('AUTH_MICROSOFT_CLIENT_SECRET'), tenant: 'common', - callbackURL: environmentService.get('AUTH_MICROSOFT_APIS_CALLBACK_URL'), + callbackURL: twentyConfigService.get('AUTH_MICROSOFT_APIS_CALLBACK_URL'), scope: scopes, passReqToCallback: true, }); diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-exchange-code-for-token.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-exchange-code-for-token.auth.strategy.ts index ef40f33112..c0b9e418fe 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-exchange-code-for-token.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-exchange-code-for-token.auth.strategy.ts @@ -4,7 +4,7 @@ import { VerifyCallback } from 'passport-google-oauth20'; import { MicrosoftAPIsOauthCommonStrategy } from 'src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy'; import { MicrosoftAPIsRequest } from 'src/engine/core-modules/auth/types/microsoft-api-request.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type MicrosoftAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -12,8 +12,8 @@ export type MicrosoftAPIScopeConfig = { @Injectable() export class MicrosoftAPIsOauthExchangeCodeForTokenStrategy extends MicrosoftAPIsOauthCommonStrategy { - constructor(environmentService: EnvironmentService) { - super(environmentService); + constructor(twentyConfigService: TwentyConfigService) { + super(twentyConfigService); } async validate( diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy.ts index c0ddea4d4b..9a48798b64 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; import { MicrosoftAPIsOauthCommonStrategy } from 'src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class MicrosoftAPIsOauthRequestCodeStrategy extends MicrosoftAPIsOauthCommonStrategy { - constructor(environmentService: EnvironmentService) { - super(environmentService); + constructor(twentyConfigService: TwentyConfigService) { + super(twentyConfigService); } authenticate(req: any, options: any) { diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts index 68407499ee..0c48e37d10 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts @@ -9,7 +9,7 @@ import { AuthException, AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type MicrosoftRequest = Omit< Request, @@ -29,11 +29,11 @@ export type MicrosoftRequest = Omit< }; export class MicrosoftStrategy extends PassportStrategy(Strategy, 'microsoft') { - constructor(environmentService: EnvironmentService) { + constructor(twentyConfigService: TwentyConfigService) { super({ - clientID: environmentService.get('AUTH_MICROSOFT_CLIENT_ID'), - clientSecret: environmentService.get('AUTH_MICROSOFT_CLIENT_SECRET'), - callbackURL: environmentService.get('AUTH_MICROSOFT_CALLBACK_URL'), + clientID: twentyConfigService.get('AUTH_MICROSOFT_CLIENT_ID'), + clientSecret: twentyConfigService.get('AUTH_MICROSOFT_CLIENT_SECRET'), + callbackURL: twentyConfigService.get('AUTH_MICROSOFT_CALLBACK_URL'), tenant: 'common', scope: ['user.read'], passReqToCallback: true, diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.spec.ts index 5b09e5e036..2a46f63db9 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.spec.ts @@ -2,16 +2,16 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { Request } from 'express'; -import { Repository } from 'typeorm'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; +import { Repository } from 'typeorm'; import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; import { AuthException } from 'src/engine/core-modules/auth/auth.exception'; import { JwtAuthStrategy } from 'src/engine/core-modules/auth/strategies/jwt.auth.strategy'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; import { SSOService } from 'src/engine/core-modules/sso/services/sso.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @@ -22,7 +22,7 @@ import { AccessTokenService } from './access-token.service'; describe('AccessTokenService', () => { let service: AccessTokenService; let jwtWrapperService: JwtWrapperService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let userRepository: Repository; let workspaceRepository: Repository; let twentyORMGlobalManager: TwentyORMGlobalManager; @@ -49,7 +49,7 @@ describe('AccessTokenService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -89,7 +89,7 @@ describe('AccessTokenService', () => { service = module.get(AccessTokenService); jwtWrapperService = module.get(JwtWrapperService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); userRepository = module.get>( getRepositoryToken(User, 'core'), ); @@ -123,7 +123,7 @@ describe('AccessTokenService', () => { const mockWorkspaceMember = { id: 'workspace-member-id' }; const mockToken = 'mock-token'; - jest.spyOn(environmentService, 'get').mockReturnValue('1h'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('1h'); jest.spyOn(userRepository, 'findOne').mockResolvedValue(mockUser as User); jest .spyOn(workspaceRepository, 'findOne') @@ -155,7 +155,7 @@ describe('AccessTokenService', () => { }); it('should throw an error if user is not found', async () => { - jest.spyOn(environmentService, 'get').mockReturnValue('1h'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('1h'); jest.spyOn(userRepository, 'findOne').mockResolvedValue(null); await expect( diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.ts index 003898b1d3..cd65d2a1f2 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.ts @@ -4,8 +4,8 @@ import { InjectRepository } from '@nestjs/typeorm'; import { addMilliseconds } from 'date-fns'; import { Request } from 'express'; import ms from 'ms'; -import { Repository } from 'typeorm'; import { isWorkspaceActiveOrSuspended } from 'twenty-shared/workspace'; +import { Repository } from 'typeorm'; import { AuthException, @@ -17,8 +17,8 @@ import { AuthContext, JwtPayload, } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { userValidator } from 'src/engine/core-modules/user/user.validate'; @@ -32,7 +32,7 @@ export class AccessTokenService { constructor( private readonly jwtWrapperService: JwtWrapperService, private readonly jwtStrategy: JwtAuthStrategy, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, @InjectRepository(User, 'core') private readonly userRepository: Repository, @InjectRepository(Workspace, 'core') @@ -46,7 +46,7 @@ export class AccessTokenService { userId: string, workspaceId: string, ): Promise { - const expiresIn = this.environmentService.get('ACCESS_TOKEN_EXPIRES_IN'); + const expiresIn = this.twentyConfigService.get('ACCESS_TOKEN_EXPIRES_IN'); const expiresAt = addMilliseconds(new Date().getTime(), ms(expiresIn)); diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.spec.ts index 1ee9e31e94..13a45ab551 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.spec.ts @@ -13,14 +13,14 @@ import { EmailVerificationException, EmailVerificationExceptionCode, } from 'src/engine/core-modules/email-verification/email-verification.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { EmailVerificationTokenService } from './email-verification-token.service'; describe('EmailVerificationTokenService', () => { let service: EmailVerificationTokenService; let appTokenRepository: Repository; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -31,7 +31,7 @@ describe('EmailVerificationTokenService', () => { useClass: Repository, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -45,7 +45,7 @@ describe('EmailVerificationTokenService', () => { appTokenRepository = module.get>( getRepositoryToken(AppToken, 'core'), ); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); describe('generateToken', () => { @@ -54,7 +54,7 @@ describe('EmailVerificationTokenService', () => { const email = 'test@example.com'; const mockExpiresIn = '24h'; - jest.spyOn(environmentService, 'get').mockReturnValue(mockExpiresIn); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(mockExpiresIn); jest.spyOn(appTokenRepository, 'create').mockReturnValue({} as AppToken); jest.spyOn(appTokenRepository, 'save').mockResolvedValue({} as AppToken); diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.ts index 02b6cdb4cd..3e350726e6 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.ts @@ -16,18 +16,18 @@ import { EmailVerificationException, EmailVerificationExceptionCode, } from 'src/engine/core-modules/email-verification/email-verification.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class EmailVerificationTokenService { constructor( @InjectRepository(AppToken, 'core') private readonly appTokenRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async generateToken(userId: string, email: string): Promise { - const expiresIn = this.environmentService.get( + const expiresIn = this.twentyConfigService.get( 'EMAIL_VERIFICATION_TOKEN_EXPIRES_IN', ); const expiresAt = addMilliseconds(new Date().getTime(), ms(expiresIn)); diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.spec.ts index 047958893e..8234319500 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.spec.ts @@ -1,14 +1,14 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { LoginTokenService } from './login-token.service'; describe('LoginTokenService', () => { let service: LoginTokenService; let jwtWrapperService: JwtWrapperService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -24,7 +24,7 @@ describe('LoginTokenService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -34,7 +34,7 @@ describe('LoginTokenService', () => { service = module.get(LoginTokenService); jwtWrapperService = module.get(JwtWrapperService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); it('should be defined', () => { @@ -52,7 +52,7 @@ describe('LoginTokenService', () => { jest .spyOn(jwtWrapperService, 'generateAppSecret') .mockReturnValue(mockSecret); - jest.spyOn(environmentService, 'get').mockReturnValue(mockExpiresIn); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(mockExpiresIn); jest.spyOn(jwtWrapperService, 'sign').mockReturnValue(mockToken); const result = await service.generateLoginToken(email, workspaceId); @@ -65,7 +65,7 @@ describe('LoginTokenService', () => { 'LOGIN', workspaceId, ); - expect(environmentService.get).toHaveBeenCalledWith( + expect(twentyConfigService.get).toHaveBeenCalledWith( 'LOGIN_TOKEN_EXPIRES_IN', ); expect(jwtWrapperService.sign).toHaveBeenCalledWith( diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.ts index a1af3de1ae..b125393c40 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.ts @@ -4,14 +4,14 @@ import { addMilliseconds } from 'date-fns'; import ms from 'ms'; import { AuthToken } from 'src/engine/core-modules/auth/dto/token.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class LoginTokenService { constructor( private readonly jwtWrapperService: JwtWrapperService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async generateLoginToken( @@ -23,7 +23,7 @@ export class LoginTokenService { workspaceId, ); - const expiresIn = this.environmentService.get('LOGIN_TOKEN_EXPIRES_IN'); + const expiresIn = this.twentyConfigService.get('LOGIN_TOKEN_EXPIRES_IN'); const expiresAt = addMilliseconds(new Date().getTime(), ms(expiresIn)); const jwtPayload = { diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.spec.ts index a53238067d..6262d08f82 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.spec.ts @@ -5,8 +5,8 @@ import { Repository } from 'typeorm'; import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; import { AuthException } from 'src/engine/core-modules/auth/auth.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { RefreshTokenService } from './refresh-token.service'; @@ -14,7 +14,7 @@ import { RefreshTokenService } from './refresh-token.service'; describe('RefreshTokenService', () => { let service: RefreshTokenService; let jwtWrapperService: JwtWrapperService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let appTokenRepository: Repository; let userRepository: Repository; @@ -32,7 +32,7 @@ describe('RefreshTokenService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -50,7 +50,7 @@ describe('RefreshTokenService', () => { service = module.get(RefreshTokenService); jwtWrapperService = module.get(JwtWrapperService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); appTokenRepository = module.get>( getRepositoryToken(AppToken, 'core'), ); @@ -91,7 +91,7 @@ describe('RefreshTokenService', () => { .spyOn(appTokenRepository, 'findOneBy') .mockResolvedValue(mockAppToken as AppToken); jest.spyOn(userRepository, 'findOne').mockResolvedValue(mockUser as User); - jest.spyOn(environmentService, 'get').mockReturnValue('1h'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('1h'); const result = await service.verifyRefreshToken(mockToken); @@ -123,7 +123,7 @@ describe('RefreshTokenService', () => { const mockToken = 'mock-refresh-token'; const mockExpiresIn = '7d'; - jest.spyOn(environmentService, 'get').mockReturnValue(mockExpiresIn); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(mockExpiresIn); jest .spyOn(jwtWrapperService, 'generateAppSecret') .mockReturnValue('mock-secret'); @@ -153,7 +153,7 @@ describe('RefreshTokenService', () => { }); it('should throw an error if expiration time is not set', async () => { - jest.spyOn(environmentService, 'get').mockReturnValue(undefined); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(undefined); await expect( service.generateRefreshToken('user-id', 'workspace-id'), diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.ts index ea574709bb..40172c2e34 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.ts @@ -14,15 +14,15 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { AuthToken } from 'src/engine/core-modules/auth/dto/token.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @Injectable() export class RefreshTokenService { constructor( private readonly jwtWrapperService: JwtWrapperService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, @InjectRepository(AppToken, 'core') private readonly appTokenRepository: Repository, @InjectRepository(User, 'core') @@ -30,7 +30,7 @@ export class RefreshTokenService { ) {} async verifyRefreshToken(refreshToken: string) { - const coolDown = this.environmentService.get('REFRESH_TOKEN_COOL_DOWN'); + const coolDown = this.twentyConfigService.get('REFRESH_TOKEN_COOL_DOWN'); await this.jwtWrapperService.verifyWorkspaceToken(refreshToken, 'REFRESH'); const jwtPayload = await this.jwtWrapperService.decode(refreshToken); @@ -109,7 +109,7 @@ export class RefreshTokenService { 'REFRESH', workspaceId, ); - const expiresIn = this.environmentService.get('REFRESH_TOKEN_EXPIRES_IN'); + const expiresIn = this.twentyConfigService.get('REFRESH_TOKEN_EXPIRES_IN'); if (!expiresIn) { throw new AuthException( diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.spec.ts index 6add5757a3..4e774a279d 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.spec.ts @@ -1,14 +1,14 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { TransientTokenService } from './transient-token.service'; describe('TransientTokenService', () => { let service: TransientTokenService; let jwtWrapperService: JwtWrapperService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -24,7 +24,7 @@ describe('TransientTokenService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -34,7 +34,7 @@ describe('TransientTokenService', () => { service = module.get(TransientTokenService); jwtWrapperService = module.get(JwtWrapperService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); it('should be defined', () => { @@ -49,7 +49,7 @@ describe('TransientTokenService', () => { const mockExpiresIn = '15m'; const mockToken = 'mock-token'; - jest.spyOn(environmentService, 'get').mockImplementation((key) => { + jest.spyOn(twentyConfigService, 'get').mockImplementation((key) => { if (key === 'SHORT_TERM_TOKEN_EXPIRES_IN') return mockExpiresIn; return undefined; @@ -66,7 +66,7 @@ describe('TransientTokenService', () => { token: mockToken, expiresAt: expect.any(Date), }); - expect(environmentService.get).toHaveBeenCalledWith( + expect(twentyConfigService.get).toHaveBeenCalledWith( 'SHORT_TERM_TOKEN_EXPIRES_IN', ); expect(jwtWrapperService.sign).toHaveBeenCalledWith( diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.ts index 5446193fe9..075ab84169 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.ts @@ -4,14 +4,14 @@ import { addMilliseconds } from 'date-fns'; import ms from 'ms'; import { AuthToken } from 'src/engine/core-modules/auth/dto/token.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class TransientTokenService { constructor( private readonly jwtWrapperService: JwtWrapperService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async generateTransientToken( @@ -23,7 +23,7 @@ export class TransientTokenService { 'LOGIN', workspaceId, ); - const expiresIn = this.environmentService.get( + const expiresIn = this.twentyConfigService.get( 'SHORT_TERM_TOKEN_EXPIRES_IN', ); diff --git a/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-feature-used.listener.ts b/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-feature-used.listener.ts index 78023175f9..f690682b0d 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-feature-used.listener.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-feature-used.listener.ts @@ -6,21 +6,21 @@ import { OnCustomBatchEvent } from 'src/engine/api/graphql/graphql-query-runner/ import { BILLING_FEATURE_USED } from 'src/engine/core-modules/billing/constants/billing-feature-used.constant'; import { BillingUsageService } from 'src/engine/core-modules/billing/services/billing-usage.service'; import { BillingUsageEvent } from 'src/engine/core-modules/billing/types/billing-usage-event.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type'; @Injectable() export class BillingFeatureUsedListener { constructor( private readonly billingUsageService: BillingUsageService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} @OnCustomBatchEvent(BILLING_FEATURE_USED) async handleBillingFeatureUsedEvent( payload: WorkspaceEventBatch, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } diff --git a/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts b/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts index 28b030fb43..328135c0c3 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts @@ -8,11 +8,11 @@ import { UpdateSubscriptionQuantityJob, UpdateSubscriptionQuantityJobData, } from 'src/engine/core-modules/billing/jobs/update-subscription-quantity.job'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -21,7 +21,7 @@ export class BillingWorkspaceMemberListener { constructor( @InjectMessageQueue(MessageQueue.billingQueue) private readonly messageQueueService: MessageQueueService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} @OnDatabaseBatchEvent('workspaceMember', DatabaseEventAction.CREATED) @@ -31,7 +31,7 @@ export class BillingWorkspaceMemberListener { ObjectRecordCreateEvent >, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } diff --git a/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts b/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts index 0287ee3a96..ece0de3dc4 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts @@ -17,7 +17,7 @@ import { BillingSubscriptionItemService } from 'src/engine/core-modules/billing/ import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service'; import { StripeBillingMeterEventService } from 'src/engine/core-modules/billing/stripe/services/stripe-billing-meter-event.service'; import { BillingUsageEvent } from 'src/engine/core-modules/billing/types/billing-usage-event.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Injectable() @@ -28,12 +28,12 @@ export class BillingUsageService { private readonly billingCustomerRepository: Repository, private readonly billingSubscriptionService: BillingSubscriptionService, private readonly stripeBillingMeterEventService: StripeBillingMeterEventService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly billingSubscriptionItemService: BillingSubscriptionItemService, ) {} async canFeatureBeUsed(workspaceId: string): Promise { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return true; } diff --git a/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts b/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts index 2ec8dc157c..b024edf9d8 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts @@ -13,15 +13,15 @@ import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/billin import { BillingProductService } from 'src/engine/core-modules/billing/services/billing-product.service'; import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service'; import { getPlanKeyFromSubscription } from 'src/engine/core-modules/billing/utils/get-plan-key-from-subscription.util'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class BillingService { protected readonly logger = new Logger(BillingService.name); constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly billingSubscriptionService: BillingSubscriptionService, private readonly billingProductService: BillingProductService, private readonly featureFlagService: FeatureFlagService, @@ -30,7 +30,7 @@ export class BillingService { ) {} isBillingEnabled() { - return this.environmentService.get('IS_BILLING_ENABLED'); + return this.twentyConfigService.get('IS_BILLING_ENABLED'); } async hasWorkspaceAnySubscription(workspaceId: string) { diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter-event.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter-event.service.ts index 1b812b9a0d..90d9f46049 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter-event.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter-event.service.ts @@ -6,7 +6,7 @@ import Stripe from 'stripe'; import { BillingMeterEventName } from 'src/engine/core-modules/billing/enums/billing-meter-event-names'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeBillingMeterEventService { @@ -14,14 +14,14 @@ export class StripeBillingMeterEventService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter.service.ts index 7900db366f..7ed9f1a5e2 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter.service.ts @@ -5,7 +5,7 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeBillingMeterService { @@ -13,14 +13,14 @@ export class StripeBillingMeterService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-portal.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-portal.service.ts index dabd0eaad2..c1302b1f36 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-portal.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-portal.service.ts @@ -6,7 +6,7 @@ import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeBillingPortalService { @@ -14,15 +14,15 @@ export class StripeBillingPortalService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-checkout.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-checkout.service.ts index e143aa43d1..ebe55ef16a 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-checkout.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-checkout.service.ts @@ -6,7 +6,7 @@ import Stripe from 'stripe'; import { BillingPlanKey } from 'src/engine/core-modules/billing/enums/billing-plan-key.enum'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @Injectable() @@ -15,14 +15,14 @@ export class StripeCheckoutService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } @@ -57,7 +57,7 @@ export class StripeCheckoutService { }, ...(withTrialPeriod ? { - trial_period_days: this.environmentService.get( + trial_period_days: this.twentyConfigService.get( requirePaymentMethod ? 'BILLING_FREE_TRIAL_WITH_CREDIT_CARD_DURATION_IN_DAYS' : 'BILLING_FREE_TRIAL_WITHOUT_CREDIT_CARD_DURATION_IN_DAYS', diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-customer.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-customer.service.ts index 0e500862d9..c6c62caa9c 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-customer.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-customer.service.ts @@ -5,7 +5,7 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeCustomerService { @@ -13,14 +13,14 @@ export class StripeCustomerService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-price.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-price.service.ts index 877516913f..a8e889d91b 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-price.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-price.service.ts @@ -5,7 +5,7 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripePriceService { @@ -13,14 +13,14 @@ export class StripePriceService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-product.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-product.service.ts index ff9ee6c449..ca2a4c980b 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-product.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-product.service.ts @@ -5,7 +5,7 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeProductService { @@ -13,14 +13,14 @@ export class StripeProductService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription-item.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription-item.service.ts index 1f7a40b409..403da680f8 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription-item.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription-item.service.ts @@ -5,7 +5,7 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeSubscriptionItemService { @@ -13,14 +13,14 @@ export class StripeSubscriptionItemService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription.service.ts index 60df5eebeb..ae72d1cc50 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription.service.ts @@ -6,7 +6,7 @@ import Stripe from 'stripe'; import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeSubscriptionService { @@ -14,14 +14,14 @@ export class StripeSubscriptionService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-webhook.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-webhook.service.ts index 88e0977b85..23649f366c 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-webhook.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-webhook.service.ts @@ -5,26 +5,26 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeWebhookService { protected readonly logger = new Logger(StripeWebhookService.name); private stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } constructEventFromPayload(signature: string, payload: Buffer) { - const webhookSecret = this.environmentService.get( + const webhookSecret = this.twentyConfigService.get( 'BILLING_STRIPE_WEBHOOK_SECRET', ); diff --git a/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts index 7a84d95c34..afc1f4be72 100644 --- a/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts @@ -3,13 +3,13 @@ import { CacheModuleOptions } from '@nestjs/common'; import { redisStore } from 'cache-manager-redis-yet'; import { CacheStorageType } from 'src/engine/core-modules/cache-storage/types/cache-storage-type.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const cacheStorageModuleFactory = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): CacheModuleOptions => { const cacheStorageType = CacheStorageType.Redis; - const cacheStorageTtl = environmentService.get('CACHE_STORAGE_TTL'); + const cacheStorageTtl = twentyConfigService.get('CACHE_STORAGE_TTL'); const cacheModuleOptions: CacheModuleOptions = { isGlobal: true, ttl: cacheStorageTtl * 1000, @@ -20,7 +20,7 @@ export const cacheStorageModuleFactory = ( return cacheModuleOptions; }*/ case CacheStorageType.Redis: { - const redisUrl = environmentService.get('REDIS_URL'); + const redisUrl = twentyConfigService.get('REDIS_URL'); if (!redisUrl) { throw new Error( diff --git a/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts index 3f12d09e6d..96210df65f 100644 --- a/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts @@ -6,7 +6,7 @@ import { cacheStorageModuleFactory } from 'src/engine/core-modules/cache-storage import { FlushCacheCommand } from 'src/engine/core-modules/cache-storage/commands/flush-cache.command'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Global() @Module({ @@ -15,7 +15,7 @@ import { EnvironmentService } from 'src/engine/core-modules/environment/environm isGlobal: true, imports: [ConfigModule], useFactory: cacheStorageModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), ], providers: [ diff --git a/packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts b/packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts index c6a1e4c23e..622e9c979a 100644 --- a/packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts @@ -2,14 +2,14 @@ import { CaptchaDriverOptions, CaptchaModuleOptions, } from 'src/engine/core-modules/captcha/interfaces'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const captchaModuleFactory = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): CaptchaModuleOptions | undefined => { - const driver = environmentService.get('CAPTCHA_DRIVER'); - const siteKey = environmentService.get('CAPTCHA_SITE_KEY'); - const secretKey = environmentService.get('CAPTCHA_SECRET_KEY'); + const driver = twentyConfigService.get('CAPTCHA_DRIVER'); + const siteKey = twentyConfigService.get('CAPTCHA_SITE_KEY'); + const secretKey = twentyConfigService.get('CAPTCHA_SECRET_KEY'); if (!driver) { return; diff --git a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts index fdca070c87..e67b141c0c 100644 --- a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ClientConfigResolver } from './client-config.resolver'; @@ -13,7 +13,7 @@ describe('ClientConfigResolver', () => { providers: [ ClientConfigResolver, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: {}, }, { diff --git a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts index 30fc67cfb1..b230c550a6 100644 --- a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts @@ -1,17 +1,17 @@ import { Query, Resolver } from '@nestjs/graphql'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { PUBLIC_FEATURE_FLAGS } from 'src/engine/core-modules/feature-flag/constants/public-feature-flag.const'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ClientConfig } from './client-config.entity'; @Resolver() export class ClientConfigResolver { constructor( - private environmentService: EnvironmentService, + private twentyConfigService: TwentyConfigService, private domainManagerService: DomainManagerService, ) {} @@ -19,17 +19,17 @@ export class ClientConfigResolver { async clientConfig(): Promise { const clientConfig: ClientConfig = { billing: { - isBillingEnabled: this.environmentService.get('IS_BILLING_ENABLED'), - billingUrl: this.environmentService.get('BILLING_PLAN_REQUIRED_LINK'), + isBillingEnabled: this.twentyConfigService.get('IS_BILLING_ENABLED'), + billingUrl: this.twentyConfigService.get('BILLING_PLAN_REQUIRED_LINK'), trialPeriods: [ { - duration: this.environmentService.get( + duration: this.twentyConfigService.get( 'BILLING_FREE_TRIAL_WITH_CREDIT_CARD_DURATION_IN_DAYS', ), isCreditCardRequired: true, }, { - duration: this.environmentService.get( + duration: this.twentyConfigService.get( 'BILLING_FREE_TRIAL_WITHOUT_CREDIT_CARD_DURATION_IN_DAYS', ), isCreditCardRequired: false, @@ -37,63 +37,64 @@ export class ClientConfigResolver { ], }, authProviders: { - google: this.environmentService.get('AUTH_GOOGLE_ENABLED'), + google: this.twentyConfigService.get('AUTH_GOOGLE_ENABLED'), magicLink: false, - password: this.environmentService.get('AUTH_PASSWORD_ENABLED'), - microsoft: this.environmentService.get('AUTH_MICROSOFT_ENABLED'), + password: this.twentyConfigService.get('AUTH_PASSWORD_ENABLED'), + microsoft: this.twentyConfigService.get('AUTH_MICROSOFT_ENABLED'), sso: [], }, - signInPrefilled: this.environmentService.get('SIGN_IN_PREFILLED'), - isMultiWorkspaceEnabled: this.environmentService.get( + signInPrefilled: this.twentyConfigService.get('SIGN_IN_PREFILLED'), + isMultiWorkspaceEnabled: this.twentyConfigService.get( 'IS_MULTIWORKSPACE_ENABLED', ), - isEmailVerificationRequired: this.environmentService.get( + isEmailVerificationRequired: this.twentyConfigService.get( 'IS_EMAIL_VERIFICATION_REQUIRED', ), - defaultSubdomain: this.environmentService.get('DEFAULT_SUBDOMAIN'), + defaultSubdomain: this.twentyConfigService.get('DEFAULT_SUBDOMAIN'), frontDomain: this.domainManagerService.getFrontUrl().hostname, debugMode: - this.environmentService.get('NODE_ENV') === NodeEnvironment.development, + this.twentyConfigService.get('NODE_ENV') === + NodeEnvironment.development, support: { - supportDriver: this.environmentService.get('SUPPORT_DRIVER'), - supportFrontChatId: this.environmentService.get( + supportDriver: this.twentyConfigService.get('SUPPORT_DRIVER'), + supportFrontChatId: this.twentyConfigService.get( 'SUPPORT_FRONT_CHAT_ID', ), }, sentry: { - environment: this.environmentService.get('SENTRY_ENVIRONMENT'), - release: this.environmentService.get('SENTRY_RELEASE'), - dsn: this.environmentService.get('SENTRY_FRONT_DSN'), + environment: this.twentyConfigService.get('SENTRY_ENVIRONMENT'), + release: this.twentyConfigService.get('SENTRY_RELEASE'), + dsn: this.twentyConfigService.get('SENTRY_FRONT_DSN'), }, captcha: { - provider: this.environmentService.get('CAPTCHA_DRIVER'), - siteKey: this.environmentService.get('CAPTCHA_SITE_KEY'), + provider: this.twentyConfigService.get('CAPTCHA_DRIVER'), + siteKey: this.twentyConfigService.get('CAPTCHA_SITE_KEY'), }, - chromeExtensionId: this.environmentService.get('CHROME_EXTENSION_ID'), + chromeExtensionId: this.twentyConfigService.get('CHROME_EXTENSION_ID'), api: { - mutationMaximumAffectedRecords: this.environmentService.get( + mutationMaximumAffectedRecords: this.twentyConfigService.get( 'MUTATION_MAXIMUM_AFFECTED_RECORDS', ), }, - isAttachmentPreviewEnabled: this.environmentService.get( + isAttachmentPreviewEnabled: this.twentyConfigService.get( 'IS_ATTACHMENT_PREVIEW_ENABLED', ), - analyticsEnabled: this.environmentService.get('ANALYTICS_ENABLED'), + analyticsEnabled: this.twentyConfigService.get('ANALYTICS_ENABLED'), canManageFeatureFlags: - this.environmentService.get('NODE_ENV') === + this.twentyConfigService.get('NODE_ENV') === NodeEnvironment.development || - this.environmentService.get('IS_BILLING_ENABLED'), + this.twentyConfigService.get('IS_BILLING_ENABLED'), publicFeatureFlags: PUBLIC_FEATURE_FLAGS, - isMicrosoftMessagingEnabled: this.environmentService.get( + isMicrosoftMessagingEnabled: this.twentyConfigService.get( 'MESSAGING_PROVIDER_MICROSOFT_ENABLED', ), - isMicrosoftCalendarEnabled: this.environmentService.get( + isMicrosoftCalendarEnabled: this.twentyConfigService.get( 'CALENDAR_PROVIDER_MICROSOFT_ENABLED', ), - isGoogleMessagingEnabled: this.environmentService.get( + isGoogleMessagingEnabled: this.twentyConfigService.get( 'MESSAGING_PROVIDER_GMAIL_ENABLED', ), - isGoogleCalendarEnabled: this.environmentService.get( + isGoogleCalendarEnabled: this.twentyConfigService.get( 'CALENDAR_PROVIDER_GOOGLE_ENABLED', ), }; diff --git a/packages/twenty-server/src/engine/core-modules/core-engine.module.ts b/packages/twenty-server/src/engine/core-modules/core-engine.module.ts index fcbf7cc19c..15e6160856 100644 --- a/packages/twenty-server/src/engine/core-modules/core-engine.module.ts +++ b/packages/twenty-server/src/engine/core-modules/core-engine.module.ts @@ -14,8 +14,6 @@ import { CaptchaModule } from 'src/engine/core-modules/captcha/captcha.module'; import { captchaModuleFactory } from 'src/engine/core-modules/captcha/captcha.module-factory'; import { EmailModule } from 'src/engine/core-modules/email/email.module'; import { emailModuleFactory } from 'src/engine/core-modules/email/email.module-factory'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerModule } from 'src/engine/core-modules/exception-handler/exception-handler.module'; import { exceptionHandlerModuleFactory } from 'src/engine/core-modules/exception-handler/exception-handler.module-factory'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; @@ -42,6 +40,8 @@ import { serverlessModuleFactory } from 'src/engine/core-modules/serverless/serv import { ServerlessModule } from 'src/engine/core-modules/serverless/serverless.module'; import { WorkspaceSSOModule } from 'src/engine/core-modules/sso/sso.module'; import { TelemetryModule } from 'src/engine/core-modules/telemetry/telemetry.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserModule } from 'src/engine/core-modules/user/user.module'; import { WorkflowApiModule } from 'src/engine/core-modules/workflow/workflow-api.module'; import { WorkspaceInvitationModule } from 'src/engine/core-modules/workspace-invitation/workspace-invitation.module'; @@ -79,31 +79,31 @@ import { FileModule } from './file/file.module'; AdminPanelModule, LabModule, RoleModule, - EnvironmentModule.forRoot({}), + TwentyConfigModule, RedisClientModule, FileStorageModule.forRootAsync({ useFactory: fileStorageModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), LoggerModule.forRootAsync({ useFactory: loggerModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), MessageQueueModule.registerAsync({ useFactory: messageQueueModuleFactory, - inject: [EnvironmentService, RedisClientService], + inject: [TwentyConfigService, RedisClientService], }), ExceptionHandlerModule.forRootAsync({ useFactory: exceptionHandlerModuleFactory, - inject: [EnvironmentService, HttpAdapterHost], + inject: [TwentyConfigService, HttpAdapterHost], }), EmailModule.forRoot({ useFactory: emailModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), CaptchaModule.forRoot({ useFactory: captchaModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), EventEmitterModule.forRoot({ wildcard: true, @@ -111,15 +111,15 @@ import { FileModule } from './file/file.module'; CacheStorageModule, LLMChatModelModule.forRoot({ useFactory: llmChatModelModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), LLMTracingModule.forRoot({ useFactory: llmTracingModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), ServerlessModule.forRootAsync({ useFactory: serverlessModuleFactory, - inject: [EnvironmentService, FileStorageService], + inject: [TwentyConfigService, FileStorageService], }), SearchModule, ], diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/controllers/cloudflare.spec.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/controllers/cloudflare.spec.ts index fe847fb050..9ed483f30b 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/controllers/cloudflare.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/controllers/cloudflare.spec.ts @@ -1,22 +1,22 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; import { Request, Response } from 'express'; +import { Repository } from 'typeorm'; import { CloudflareController } from 'src/engine/core-modules/domain-manager/controllers/cloudflare.controller'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-handler/http-exception-handler.service'; import { CustomDomainValidRecords } from 'src/engine/core-modules/domain-manager/dtos/custom-domain-valid-records'; import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service'; +import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-handler/http-exception-handler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; describe('CloudflareController - customHostnameWebhooks', () => { let controller: CloudflareController; let WorkspaceRepository: Repository; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let domainManagerService: DomainManagerService; let customDomainService: CustomDomainService; @@ -56,7 +56,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -66,7 +66,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { controller = module.get(CloudflareController); WorkspaceRepository = module.get(getRepositoryToken(Workspace, 'core')); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); domainManagerService = module.get(DomainManagerService); customDomainService = module.get(CustomDomainService); @@ -83,7 +83,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { send: sendMock, } as unknown as Response; - jest.spyOn(environmentService, 'get').mockReturnValue('correct-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('correct-secret'); await controller.customHostnameWebhooks(req, res); @@ -102,7 +102,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { send: sendMock, } as unknown as Response; - jest.spyOn(environmentService, 'get').mockReturnValue('correct-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('correct-secret'); jest .spyOn(customDomainService, 'getCustomDomainDetails') .mockResolvedValue({ @@ -147,7 +147,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { send: sendMock, } as unknown as Response; - jest.spyOn(environmentService, 'get').mockReturnValue('correct-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('correct-secret'); jest.spyOn(WorkspaceRepository, 'findOneBy').mockResolvedValue({ customDomain: 'notfound.com', isCustomDomainEnabled: true, @@ -180,7 +180,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { send: sendMock, } as unknown as Response; - jest.spyOn(environmentService, 'get').mockReturnValue('correct-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('correct-secret'); jest.spyOn(WorkspaceRepository, 'findOneBy').mockResolvedValue({ customDomain: 'nothing-change.com', isCustomDomainEnabled: true, diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.guard.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.guard.ts index 62d6b33bd6..f6f88c95e0 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.guard.ts @@ -4,17 +4,17 @@ import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { timingSafeEqual } from 'crypto'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class CloudflareSecretMatchGuard implements CanActivate { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} canActivate(context: ExecutionContext): boolean { try { const request = context.switchToHttp().getRequest(); - const cloudflareWebhookSecret = this.environmentService.get( + const cloudflareWebhookSecret = this.twentyConfigService.get( 'CLOUDFLARE_WEBHOOK_SECRET', ); diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.spec.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.spec.ts index 75c4a5db26..0c2815097c 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.spec.ts @@ -2,25 +2,25 @@ import { ExecutionContext } from '@nestjs/common'; import * as crypto from 'crypto'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { CloudflareSecretMatchGuard } from './cloudflare-secret.guard'; describe('CloudflareSecretMatchGuard.canActivate', () => { let guard: CloudflareSecretMatchGuard; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(() => { - environmentService = { + twentyConfigService = { get: jest.fn(), - } as unknown as EnvironmentService; - guard = new CloudflareSecretMatchGuard(environmentService); + } as unknown as TwentyConfigService; + guard = new CloudflareSecretMatchGuard(twentyConfigService); }); it('should return true when the webhook secret matches', () => { const mockRequest = { headers: { 'cf-webhook-auth': 'valid-secret' } }; - jest.spyOn(environmentService, 'get').mockReturnValue('valid-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('valid-secret'); const mockContext = { switchToHttp: () => ({ @@ -36,7 +36,7 @@ describe('CloudflareSecretMatchGuard.canActivate', () => { it('should return true when env is not set', () => { const mockRequest = { headers: { 'cf-webhook-auth': 'valid-secret' } }; - jest.spyOn(environmentService, 'get').mockReturnValue(undefined); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(undefined); const mockContext = { switchToHttp: () => ({ @@ -52,7 +52,7 @@ describe('CloudflareSecretMatchGuard.canActivate', () => { it('should return false if an error occurs', () => { const mockRequest = { headers: {} }; - jest.spyOn(environmentService, 'get').mockReturnValue('valid-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('valid-secret'); const mockContext = { switchToHttp: () => ({ diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.spec.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.spec.ts index 69b0a16b43..dbfaaa9bce 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.spec.ts @@ -1,18 +1,18 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { CustomHostnameCreateResponse } from 'cloudflare/resources/custom-hostnames/custom-hostnames'; import Cloudflare from 'cloudflare'; +import { CustomHostnameCreateResponse } from 'cloudflare/resources/custom-hostnames/custom-hostnames'; +import { DomainManagerException } from 'src/engine/core-modules/domain-manager/domain-manager.exception'; import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { DomainManagerException } from 'src/engine/core-modules/domain-manager/domain-manager.exception'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; jest.mock('cloudflare'); describe('CustomDomainService', () => { let customDomainService: CustomDomainService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let domainManagerService: DomainManagerService; beforeEach(async () => { @@ -20,7 +20,7 @@ describe('CustomDomainService', () => { providers: [ CustomDomainService, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -35,7 +35,7 @@ describe('CustomDomainService', () => { }).compile(); customDomainService = module.get(CustomDomainService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); domainManagerService = module.get(DomainManagerService); @@ -52,11 +52,11 @@ describe('CustomDomainService', () => { it('should initialize cloudflareClient when CLOUDFLARE_API_KEY is defined', () => { const mockApiKey = 'test-api-key'; - jest.spyOn(environmentService, 'get').mockReturnValue(mockApiKey); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(mockApiKey); - const instance = new CustomDomainService(environmentService, {} as any); + const instance = new CustomDomainService(twentyConfigService, {} as any); - expect(environmentService.get).toHaveBeenCalledWith('CLOUDFLARE_API_KEY'); + expect(twentyConfigService.get).toHaveBeenCalledWith('CLOUDFLARE_API_KEY'); expect(Cloudflare).toHaveBeenCalledWith({ apiToken: mockApiKey }); expect(instance.cloudflareClient).toBeDefined(); }); @@ -89,7 +89,7 @@ describe('CustomDomainService', () => { jest .spyOn(customDomainService, 'getCustomDomainDetails') .mockResolvedValueOnce(undefined); - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); (customDomainService as any).cloudflareClient = cloudflareMock; await customDomainService.registerCustomDomain(customDomain); @@ -111,7 +111,7 @@ describe('CustomDomainService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); (customDomainService as any).cloudflareClient = cloudflareMock; const result = @@ -137,7 +137,7 @@ describe('CustomDomainService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); jest .spyOn(domainManagerService, 'getFrontUrl') @@ -175,7 +175,7 @@ describe('CustomDomainService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); jest .spyOn(domainManagerService, 'getFrontUrl') .mockReturnValue(new URL('https://front.domain')); @@ -199,7 +199,7 @@ describe('CustomDomainService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); (customDomainService as any).cloudflareClient = cloudflareMock; await expect( @@ -249,7 +249,7 @@ describe('CustomDomainService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); (customDomainService as any).cloudflareClient = cloudflareMock; await expect( diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.ts index bca196fa36..56787244ed 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.ts @@ -9,21 +9,21 @@ import { DomainManagerExceptionCode, } from 'src/engine/core-modules/domain-manager/domain-manager.exception'; import { CustomDomainValidRecords } from 'src/engine/core-modules/domain-manager/dtos/custom-domain-valid-records'; -import { domainManagerValidator } from 'src/engine/core-modules/domain-manager/validator/cloudflare.validate'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { domainManagerValidator } from 'src/engine/core-modules/domain-manager/validator/cloudflare.validate'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class CustomDomainService { cloudflareClient?: Cloudflare; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, ) { - if (this.environmentService.get('CLOUDFLARE_API_KEY')) { + if (this.twentyConfigService.get('CLOUDFLARE_API_KEY')) { this.cloudflareClient = new Cloudflare({ - apiToken: this.environmentService.get('CLOUDFLARE_API_KEY'), + apiToken: this.twentyConfigService.get('CLOUDFLARE_API_KEY'), }); } } @@ -39,7 +39,7 @@ export class CustomDomainService { } return await this.cloudflareClient.customHostnames.create({ - zone_id: this.environmentService.get('CLOUDFLARE_ZONE_ID'), + zone_id: this.twentyConfigService.get('CLOUDFLARE_ZONE_ID'), hostname: customDomain, ssl: { method: 'txt', @@ -63,7 +63,7 @@ export class CustomDomainService { domainManagerValidator.isCloudflareInstanceDefined(this.cloudflareClient); const response = await this.cloudflareClient.customHostnames.list({ - zone_id: this.environmentService.get('CLOUDFLARE_ZONE_ID'), + zone_id: this.twentyConfigService.get('CLOUDFLARE_ZONE_ID'), hostname: customDomain, }); @@ -163,7 +163,7 @@ export class CustomDomainService { if (customHostname) { await this.cloudflareClient.customHostnames.delete(customHostname.id, { - zone_id: this.environmentService.get('CLOUDFLARE_ZONE_ID'), + zone_id: this.twentyConfigService.get('CLOUDFLARE_ZONE_ID'), }); } } catch (err) { @@ -175,7 +175,7 @@ export class CustomDomainService { domainManagerValidator.isCloudflareInstanceDefined(this.cloudflareClient); await this.cloudflareClient.customHostnames.delete(customHostnameId, { - zone_id: this.environmentService.get('CLOUDFLARE_ZONE_ID'), + zone_id: this.twentyConfigService.get('CLOUDFLARE_ZONE_ID'), }); } diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.spec.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.spec.ts index d39d05ab75..73c0c1d5e6 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.spec.ts @@ -3,7 +3,7 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DomainManagerService } from './domain-manager.service'; @@ -12,7 +12,7 @@ describe('DomainManagerService', () => { describe('getWorkspaceUrls', () => { it('should return a URL containing the correct customDomain if customDomain is provided', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -35,7 +35,7 @@ describe('DomainManagerService', () => { it('should return a URL containing the correct subdomain if customDomain is not provided but subdomain is', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -58,7 +58,7 @@ describe('DomainManagerService', () => { }); }); let domainManagerService: DomainManagerService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -69,7 +69,7 @@ describe('DomainManagerService', () => { useClass: Repository, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -79,13 +79,13 @@ describe('DomainManagerService', () => { domainManagerService = module.get(DomainManagerService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); describe('buildBaseUrl', () => { it('should build the base URL from environment variables', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -101,7 +101,7 @@ describe('DomainManagerService', () => { it('should append default subdomain if multiworkspace is enabled', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -121,7 +121,7 @@ describe('DomainManagerService', () => { describe('buildWorkspaceURL', () => { it('should build workspace URL with given subdomain', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -145,7 +145,7 @@ describe('DomainManagerService', () => { it('should set the pathname if provided', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -168,7 +168,7 @@ describe('DomainManagerService', () => { it('should set the search parameters if provided', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts index 22b2103eb3..5696b732f0 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts @@ -10,7 +10,7 @@ import { CustomDomainValidRecords } from 'src/engine/core-modules/domain-manager import { generateRandomSubdomain } from 'src/engine/core-modules/domain-manager/utils/generate-random-subdomain'; import { getSubdomainFromEmail } from 'src/engine/core-modules/domain-manager/utils/get-subdomain-from-email'; import { getSubdomainNameFromDisplayName } from 'src/engine/core-modules/domain-manager/utils/get-subdomain-name-from-display-name'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate'; @@ -19,13 +19,13 @@ export class DomainManagerService { constructor( @InjectRepository(Workspace, 'core') private readonly workspaceRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} getFrontUrl() { return new URL( - this.environmentService.get('FRONTEND_URL') ?? - this.environmentService.get('SERVER_URL'), + this.twentyConfigService.get('FRONTEND_URL') ?? + this.twentyConfigService.get('SERVER_URL'), ); } @@ -33,10 +33,10 @@ export class DomainManagerService { const baseUrl = this.getFrontUrl(); if ( - this.environmentService.get('IS_MULTIWORKSPACE_ENABLED') && - this.environmentService.get('DEFAULT_SUBDOMAIN') + this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED') && + this.twentyConfigService.get('DEFAULT_SUBDOMAIN') ) { - baseUrl.hostname = `${this.environmentService.get('DEFAULT_SUBDOMAIN')}.${baseUrl.hostname}`; + baseUrl.hostname = `${this.twentyConfigService.get('DEFAULT_SUBDOMAIN')}.${baseUrl.hostname}`; } return baseUrl; @@ -122,7 +122,7 @@ export class DomainManagerService { } isDefaultSubdomain(subdomain: string) { - return subdomain === this.environmentService.get('DEFAULT_SUBDOMAIN'); + return subdomain === this.twentyConfigService.get('DEFAULT_SUBDOMAIN'); } computeRedirectErrorUrl( @@ -139,7 +139,7 @@ export class DomainManagerService { } private async getDefaultWorkspace() { - if (this.environmentService.get('IS_MULTIWORKSPACE_ENABLED')) { + if (this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED')) { throw new Error( 'Default workspace does not exist when multi-workspace is enabled', ); @@ -171,7 +171,7 @@ export class DomainManagerService { } async getWorkspaceByOriginOrDefaultWorkspace(origin: string) { - if (!this.environmentService.get('IS_MULTIWORKSPACE_ENABLED')) { + if (!this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED')) { return this.getDefaultWorkspace(); } @@ -222,7 +222,7 @@ export class DomainManagerService { private getTwentyWorkspaceUrl(subdomain: string) { const url = this.getFrontUrl(); - url.hostname = this.environmentService.get('IS_MULTIWORKSPACE_ENABLED') + url.hostname = this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED') ? `${subdomain}.${url.hostname}` : url.hostname; @@ -234,7 +234,7 @@ export class DomainManagerService { ) { if (!workspace) { return { - subdomain: this.environmentService.get('DEFAULT_SUBDOMAIN'), + subdomain: this.twentyConfigService.get('DEFAULT_SUBDOMAIN'), customDomain: null, }; } diff --git a/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.module.ts b/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.module.ts index 233dcb1f39..c22faf26cf 100644 --- a/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.module.ts +++ b/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.module.ts @@ -7,7 +7,7 @@ import { DomainManagerModule } from 'src/engine/core-modules/domain-manager/doma import { EmailVerificationResolver } from 'src/engine/core-modules/email-verification/email-verification.resolver'; import { EmailVerificationService } from 'src/engine/core-modules/email-verification/services/email-verification.service'; import { EmailModule } from 'src/engine/core-modules/email/email.module'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module'; import { UserModule } from 'src/engine/core-modules/user/user.module'; @@ -15,7 +15,7 @@ import { UserModule } from 'src/engine/core-modules/user/user.module'; imports: [ TypeOrmModule.forFeature([AppToken], 'core'), EmailModule, - EnvironmentModule, + TwentyConfigModule, DomainManagerModule, UserModule, UserWorkspaceModule, diff --git a/packages/twenty-server/src/engine/core-modules/email-verification/services/email-verification.service.ts b/packages/twenty-server/src/engine/core-modules/email-verification/services/email-verification.service.ts index d94198b783..b849675431 100644 --- a/packages/twenty-server/src/engine/core-modules/email-verification/services/email-verification.service.ts +++ b/packages/twenty-server/src/engine/core-modules/email-verification/services/email-verification.service.ts @@ -22,7 +22,7 @@ import { EmailVerificationExceptionCode, } from 'src/engine/core-modules/email-verification/email-verification.exception'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; @Injectable() @@ -33,7 +33,7 @@ export class EmailVerificationService { private readonly appTokenRepository: Repository, private readonly domainManagerService: DomainManagerService, private readonly emailService: EmailService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly userService: UserService, private readonly emailVerificationTokenService: EmailVerificationTokenService, ) {} @@ -46,7 +46,7 @@ export class EmailVerificationService { | undefined, locale: keyof typeof APP_LOCALES, ) { - if (!this.environmentService.get('IS_EMAIL_VERIFICATION_REQUIRED')) { + if (!this.twentyConfigService.get('IS_EMAIL_VERIFICATION_REQUIRED')) { return { success: false }; } @@ -79,9 +79,9 @@ export class EmailVerificationService { i18n.activate(locale); await this.emailService.send({ - from: `${this.environmentService.get( + from: `${this.twentyConfigService.get( 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + )} <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, to: email, subject: t`Welcome to Twenty: Please Confirm Your Email`, text, @@ -98,7 +98,7 @@ export class EmailVerificationService { | undefined, locale: keyof typeof APP_LOCALES, ) { - if (!this.environmentService.get('IS_EMAIL_VERIFICATION_REQUIRED')) { + if (!this.twentyConfigService.get('IS_EMAIL_VERIFICATION_REQUIRED')) { throw new EmailVerificationException( 'Email verification token cannot be sent because email verification is not required', EmailVerificationExceptionCode.EMAIL_VERIFICATION_NOT_REQUIRED, diff --git a/packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts b/packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts index fba3524711..690433bf22 100644 --- a/packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts @@ -3,12 +3,12 @@ import { EmailModuleOptions, } from 'src/engine/core-modules/email/interfaces/email.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const emailModuleFactory = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): EmailModuleOptions => { - const driver = environmentService.get('EMAIL_DRIVER'); + const driver = twentyConfigService.get('EMAIL_DRIVER'); switch (driver) { case EmailDriver.Logger: @@ -21,11 +21,11 @@ export const emailModuleFactory = ( type: EmailDriver.Smtp, }; - const host = environmentService.get('EMAIL_SMTP_HOST'); - const port = environmentService.get('EMAIL_SMTP_PORT'); - const user = environmentService.get('EMAIL_SMTP_USER'); - const pass = environmentService.get('EMAIL_SMTP_PASSWORD'); - const noTLS = environmentService.get('EMAIL_SMTP_NO_TLS'); + const host = twentyConfigService.get('EMAIL_SMTP_HOST'); + const port = twentyConfigService.get('EMAIL_SMTP_PORT'); + const user = twentyConfigService.get('EMAIL_SMTP_USER'); + const pass = twentyConfigService.get('EMAIL_SMTP_PASSWORD'); + const noTLS = twentyConfigService.get('EMAIL_SMTP_NO_TLS'); if (!host || !port) { throw new Error( diff --git a/packages/twenty-server/src/engine/core-modules/environment/constants/__tests__/environment-variables-group-metadata.spec.ts b/packages/twenty-server/src/engine/core-modules/environment/constants/__tests__/environment-variables-group-metadata.spec.ts deleted file mode 100644 index 121f532611..0000000000 --- a/packages/twenty-server/src/engine/core-modules/environment/constants/__tests__/environment-variables-group-metadata.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ENVIRONMENT_VARIABLES_GROUP_METADATA } from 'src/engine/core-modules/environment/constants/environment-variables-group-metadata'; -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; - -describe('ENVIRONMENT_VARIABLES_GROUP_METADATA', () => { - it('should include all EnvironmentVariablesGroup enum values', () => { - const enumValues = Object.values(EnvironmentVariablesGroup); - const metadataKeys = Object.keys(ENVIRONMENT_VARIABLES_GROUP_METADATA); - - enumValues.forEach((enumValue) => { - expect(metadataKeys).toContain(enumValue); - }); - - metadataKeys.forEach((key) => { - expect(enumValues).toContain(key); - }); - - expect(enumValues.length).toBe(metadataKeys.length); - }); - - it('should have unique position values', () => { - const positions = Object.values(ENVIRONMENT_VARIABLES_GROUP_METADATA).map( - (metadata) => metadata.position, - ); - const uniquePositions = new Set(positions); - - expect(positions.length).toBe(uniquePositions.size); - }); -}); diff --git a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-masking-config.ts b/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-masking-config.ts deleted file mode 100644 index 4b0d9a848d..0000000000 --- a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-masking-config.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { EnvironmentVariablesMaskingStrategies } from 'src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum'; - -type LastNCharsConfig = { - strategy: EnvironmentVariablesMaskingStrategies.LAST_N_CHARS; - chars: number; -}; - -type HidePasswordConfig = { - strategy: EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD; -}; - -type MaskingConfigType = { - APP_SECRET: LastNCharsConfig; - PG_DATABASE_URL: HidePasswordConfig; - REDIS_URL: HidePasswordConfig; -}; - -export const ENVIRONMENT_VARIABLES_MASKING_CONFIG: MaskingConfigType = { - APP_SECRET: { - strategy: EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, - chars: 5, - }, - PG_DATABASE_URL: { - strategy: EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD, - }, - REDIS_URL: { - strategy: EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD, - }, -} as const; diff --git a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-key.ts b/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-key.ts deleted file mode 100644 index a1249e4712..0000000000 --- a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-key.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const ENVIRONMENT_VARIABLES_METADATA_DECORATOR_KEY = - 'environment-variables-metadata' as const; diff --git a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-names-key.ts b/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-names-key.ts deleted file mode 100644 index aa1c0c378e..0000000000 --- a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-names-key.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const ENVIRONMENT_VARIABLES_METADATA_DECORATOR_NAMES_KEY = - 'environment-variable-names' as const; diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment.service.ts b/packages/twenty-server/src/engine/core-modules/environment/environment.service.ts deleted file mode 100644 index c0a9158bf9..0000000000 --- a/packages/twenty-server/src/engine/core-modules/environment/environment.service.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { Injectable } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; - -import { ENVIRONMENT_VARIABLES_MASKING_CONFIG } from 'src/engine/core-modules/environment/constants/environment-variables-masking-config'; -import { EnvironmentVariablesMetadataOptions } from 'src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator'; -import { EnvironmentVariablesMaskingStrategies } from 'src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum'; -import { EnvironmentVariables } from 'src/engine/core-modules/environment/environment-variables'; -import { environmentVariableMaskSensitiveData } from 'src/engine/core-modules/environment/utils/environment-variable-mask-sensitive-data.util'; -import { TypedReflect } from 'src/utils/typed-reflect'; - -@Injectable() -export class EnvironmentService { - constructor(private readonly configService: ConfigService) {} - - get(key: T): EnvironmentVariables[T] { - return this.configService.get( - key, - new EnvironmentVariables()[key], - ); - } - - getAll(): Record< - string, - { - value: EnvironmentVariables[keyof EnvironmentVariables]; - metadata: EnvironmentVariablesMetadataOptions; - } - > { - const result: Record< - string, - { - value: EnvironmentVariables[keyof EnvironmentVariables]; - metadata: EnvironmentVariablesMetadataOptions; - } - > = {}; - - const envVars = new EnvironmentVariables(); - const metadata = - TypedReflect.getMetadata('environment-variables', EnvironmentVariables) ?? - {}; - - Object.entries(metadata).forEach(([key, envMetadata]) => { - let value = - this.configService.get(key) ?? - envVars[key as keyof EnvironmentVariables] ?? - ''; - - if ( - typeof value === 'string' && - key in ENVIRONMENT_VARIABLES_MASKING_CONFIG - ) { - const varMaskingConfig = - ENVIRONMENT_VARIABLES_MASKING_CONFIG[ - key as keyof typeof ENVIRONMENT_VARIABLES_MASKING_CONFIG - ]; - const options = - varMaskingConfig.strategy === - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS - ? { chars: varMaskingConfig.chars } - : undefined; - - value = environmentVariableMaskSensitiveData( - value, - varMaskingConfig.strategy, - { ...options, variableName: key }, - ); - } - - result[key] = { - value, - metadata: envMetadata, - }; - }); - - return result; - } -} diff --git a/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts index 75a2fadfd4..e4aff02709 100644 --- a/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts @@ -1,22 +1,22 @@ import { HttpAdapterHost } from '@nestjs/core'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OPTIONS_TYPE } from 'src/engine/core-modules/exception-handler/exception-handler.module-definition'; import { ExceptionHandlerDriver } from 'src/engine/core-modules/exception-handler/interfaces'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; /** * ExceptionHandler Module factory * @returns ExceptionHandlerModuleOptions - * @param environmentService + * @param twentyConfigService * @param adapterHost */ export const exceptionHandlerModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, adapterHost: HttpAdapterHost, ): Promise => { - const driverType = environmentService.get('EXCEPTION_HANDLER_DRIVER'); + const driverType = twentyConfigService.get('EXCEPTION_HANDLER_DRIVER'); switch (driverType) { case ExceptionHandlerDriver.Console: { @@ -28,12 +28,12 @@ export const exceptionHandlerModuleFactory = async ( return { type: ExceptionHandlerDriver.Sentry, options: { - environment: environmentService.get('SENTRY_ENVIRONMENT'), - release: environmentService.get('SENTRY_RELEASE'), - dsn: environmentService.get('SENTRY_DSN') ?? '', + environment: twentyConfigService.get('SENTRY_ENVIRONMENT'), + release: twentyConfigService.get('SENTRY_RELEASE'), + dsn: twentyConfigService.get('SENTRY_DSN') ?? '', serverInstance: adapterHost.httpAdapter?.getInstance(), debug: - environmentService.get('NODE_ENV') === NodeEnvironment.development, + twentyConfigService.get('NODE_ENV') === NodeEnvironment.development, }, }; } diff --git a/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts index 1683645c6e..edb23a2f2d 100644 --- a/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts @@ -1,25 +1,25 @@ import { fromNodeProviderChain } from '@aws-sdk/credential-providers'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageModuleOptions, StorageDriverType, } from 'src/engine/core-modules/file-storage/interfaces'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { resolveAbsolutePath } from 'src/utils/resolve-absolute-path'; /** * FileStorage Module factory * @returns FileStorageModuleOptions - * @param environmentService + * @param twentyConfigService */ export const fileStorageModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): Promise => { - const driverType = environmentService.get('STORAGE_TYPE'); + const driverType = twentyConfigService.get('STORAGE_TYPE'); switch (driverType) { case StorageDriverType.Local: { - const storagePath = environmentService.get('STORAGE_LOCAL_PATH'); + const storagePath = twentyConfigService.get('STORAGE_LOCAL_PATH'); return { type: StorageDriverType.Local, @@ -29,11 +29,11 @@ export const fileStorageModuleFactory = async ( }; } case StorageDriverType.S3: { - const bucketName = environmentService.get('STORAGE_S3_NAME'); - const endpoint = environmentService.get('STORAGE_S3_ENDPOINT'); - const region = environmentService.get('STORAGE_S3_REGION'); - const accessKeyId = environmentService.get('STORAGE_S3_ACCESS_KEY_ID'); - const secretAccessKey = environmentService.get( + const bucketName = twentyConfigService.get('STORAGE_S3_NAME'); + const endpoint = twentyConfigService.get('STORAGE_S3_ENDPOINT'); + const region = twentyConfigService.get('STORAGE_S3_REGION'); + const accessKeyId = twentyConfigService.get('STORAGE_S3_ACCESS_KEY_ID'); + const secretAccessKey = twentyConfigService.get( 'STORAGE_S3_SECRET_ACCESS_KEY', ); diff --git a/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts b/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts index d0de77e23c..f2d1099314 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts @@ -3,11 +3,11 @@ import { Module } from '@nestjs/common'; import { FileUploadResolver } from 'src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { FileModule } from 'src/engine/core-modules/file/file.module'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Module({ imports: [FileModule], - providers: [FileUploadService, FileUploadResolver, EnvironmentService], + providers: [FileUploadService, FileUploadResolver, TwentyConfigService], exports: [FileUploadService, FileUploadResolver], }) export class FileUploadModule {} diff --git a/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts b/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts index 9633227b3c..850cd9aff8 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { FileUploadResolver } from './file-upload.resolver'; @@ -17,7 +17,7 @@ describe('FileUploadResolver', () => { useValue: {}, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: {}, }, ], diff --git a/packages/twenty-server/src/engine/core-modules/file/file.module.ts b/packages/twenty-server/src/engine/core-modules/file/file.module.ts index c52dc0f92c..b8a3b356bf 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file.module.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file.module.ts @@ -1,12 +1,12 @@ import { Module } from '@nestjs/common'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FilePathGuard } from 'src/engine/core-modules/file/guards/file-path-guard'; import { FileDeletionJob } from 'src/engine/core-modules/file/jobs/file-deletion.job'; import { FileWorkspaceFolderDeletionJob } from 'src/engine/core-modules/file/jobs/file-workspace-folder-deletion.job'; import { FileAttachmentListener } from 'src/engine/core-modules/file/listeners/file-attachment.listener'; import { FileWorkspaceMemberListener } from 'src/engine/core-modules/file/listeners/file-workspace-member.listener'; import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { FileController } from './controllers/file.controller'; import { FileService } from './services/file.service'; @@ -15,7 +15,7 @@ import { FileService } from './services/file.service'; imports: [JwtModule], providers: [ FileService, - EnvironmentService, + TwentyConfigService, FilePathGuard, FileAttachmentListener, FileWorkspaceMemberListener, diff --git a/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts b/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts index ecc5ee5fa4..387b71e2a3 100644 --- a/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts @@ -1,8 +1,8 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; +import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { FileService } from './file.service'; @@ -18,7 +18,7 @@ describe('FileService', () => { useValue: {}, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: {}, }, { diff --git a/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts b/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts index e40f540dbf..e7af3a44c6 100644 --- a/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts +++ b/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts @@ -2,16 +2,16 @@ import { Injectable } from '@nestjs/common'; import { Stream } from 'stream'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class FileService { constructor( private readonly jwtWrapperService: JwtWrapperService, private readonly fileStorageService: FileStorageService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async getFileStream( @@ -28,7 +28,7 @@ export class FileService { } async encodeFileToken(payloadToEncode: Record) { - const fileTokenExpiresIn = this.environmentService.get( + const fileTokenExpiresIn = this.twentyConfigService.get( 'FILE_TOKEN_EXPIRES_IN', ); const secret = this.jwtWrapperService.generateAppSecret( diff --git a/packages/twenty-server/src/engine/core-modules/graphql/utils/generate-graphql-error-from-error.util.ts b/packages/twenty-server/src/engine/core-modules/graphql/utils/generate-graphql-error-from-error.util.ts index 73f857b05d..30296cb2a6 100644 --- a/packages/twenty-server/src/engine/core-modules/graphql/utils/generate-graphql-error-from-error.util.ts +++ b/packages/twenty-server/src/engine/core-modules/graphql/utils/generate-graphql-error-from-error.util.ts @@ -1,4 +1,4 @@ -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { BaseGraphQLError, diff --git a/packages/twenty-server/src/engine/core-modules/guard-redirect/services/guard-redirect.service.ts b/packages/twenty-server/src/engine/core-modules/guard-redirect/services/guard-redirect.service.ts index 26f9555b59..deda56193a 100644 --- a/packages/twenty-server/src/engine/core-modules/guard-redirect/services/guard-redirect.service.ts +++ b/packages/twenty-server/src/engine/core-modules/guard-redirect/services/guard-redirect.service.ts @@ -2,17 +2,17 @@ import { ExecutionContext, Injectable } from '@nestjs/common'; import { Request } from 'express'; -import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { CustomException } from 'src/utils/custom-exception'; import { AuthException } from 'src/engine/core-modules/auth/auth.exception'; +import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { CustomException } from 'src/utils/custom-exception'; @Injectable() export class GuardRedirectService { constructor( private readonly domainManagerService: DomainManagerService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly exceptionHandlerService: ExceptionHandlerService, ) {} @@ -52,7 +52,7 @@ export class GuardRedirectService { customDomain: subdomainAndCustomDomainFromReferer.customDomain, } : { - subdomain: this.environmentService.get('DEFAULT_SUBDOMAIN'), + subdomain: this.twentyConfigService.get('DEFAULT_SUBDOMAIN'), customDomain: null, }; } diff --git a/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts b/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts index 8a689819cb..6a7dd20c67 100644 --- a/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts +++ b/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts @@ -2,24 +2,24 @@ import { Module } from '@nestjs/common'; import { JwtModule as NestJwtModule } from '@nestjs/jwt'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; const InternalJwtModule = NestJwtModule.registerAsync({ - useFactory: async (environmentService: EnvironmentService) => { + useFactory: async (twentyConfigService: TwentyConfigService) => { return { - secret: environmentService.get('APP_SECRET'), + secret: twentyConfigService.get('APP_SECRET'), signOptions: { - expiresIn: environmentService.get('ACCESS_TOKEN_EXPIRES_IN'), + expiresIn: twentyConfigService.get('ACCESS_TOKEN_EXPIRES_IN'), }, }; }, - inject: [EnvironmentService], + inject: [TwentyConfigService], }); @Module({ - imports: [InternalJwtModule, EnvironmentModule], + imports: [InternalJwtModule, TwentyConfigModule], controllers: [], providers: [JwtWrapperService], exports: [JwtWrapperService], diff --git a/packages/twenty-server/src/engine/core-modules/jwt/services/jwt-wrapper.service.ts b/packages/twenty-server/src/engine/core-modules/jwt/services/jwt-wrapper.service.ts index de94bfe878..e5c803cde8 100644 --- a/packages/twenty-server/src/engine/core-modules/jwt/services/jwt-wrapper.service.ts +++ b/packages/twenty-server/src/engine/core-modules/jwt/services/jwt-wrapper.service.ts @@ -12,7 +12,7 @@ import { AuthException, AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type WorkspaceTokenType = | 'ACCESS' @@ -27,7 +27,7 @@ export type WorkspaceTokenType = export class JwtWrapperService { constructor( private readonly jwtService: JwtService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} sign(payload: string | object, options?: JwtSignOptions): string { @@ -102,7 +102,7 @@ export class JwtWrapperService { } generateAppSecret(type: WorkspaceTokenType, workspaceId?: string): string { - const appSecret = this.environmentService.get('APP_SECRET'); + const appSecret = this.twentyConfigService.get('APP_SECRET'); if (!appSecret) { throw new Error('APP_SECRET is not set'); @@ -114,7 +114,7 @@ export class JwtWrapperService { } generateAppSecretLegacy(): string { - const accessTokenSecret = this.environmentService.get( + const accessTokenSecret = this.twentyConfigService.get( 'ACCESS_TOKEN_SECRET', ); diff --git a/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts index e0ea03e54b..ca52375ace 100644 --- a/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts @@ -1,11 +1,11 @@ import { LLMChatModelDriver } from 'src/engine/core-modules/llm-chat-model/interfaces/llm-chat-model.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const llmChatModelModuleFactory = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ) => { - const driver = environmentService.get('LLM_CHAT_MODEL_DRIVER'); + const driver = twentyConfigService.get('LLM_CHAT_MODEL_DRIVER'); switch (driver) { case LLMChatModelDriver.OpenAI: { diff --git a/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts index 94abe251eb..5f716415a8 100644 --- a/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts @@ -1,19 +1,19 @@ import { LLMTracingDriver } from 'src/engine/core-modules/llm-tracing/interfaces/llm-tracing.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const llmTracingModuleFactory = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ) => { - const driver = environmentService.get('LLM_TRACING_DRIVER'); + const driver = twentyConfigService.get('LLM_TRACING_DRIVER'); switch (driver) { case LLMTracingDriver.Console: { return { type: LLMTracingDriver.Console as const }; } case LLMTracingDriver.Langfuse: { - const secretKey = environmentService.get('LANGFUSE_SECRET_KEY'); - const publicKey = environmentService.get('LANGFUSE_PUBLIC_KEY'); + const secretKey = twentyConfigService.get('LANGFUSE_SECRET_KEY'); + const publicKey = twentyConfigService.get('LANGFUSE_PUBLIC_KEY'); if (!(secretKey && publicKey)) { throw new Error( diff --git a/packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts b/packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts index 94b490fdc3..4992061585 100644 --- a/packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts @@ -1,19 +1,19 @@ -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { - LoggerModuleOptions, LoggerDriverType, + LoggerModuleOptions, } from 'src/engine/core-modules/logger/interfaces'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; /** * Logger Module factory * @returns LoggerModuleOptions - * @param environmentService + * @param twentyConfigService */ export const loggerModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): Promise => { - const driverType = environmentService.get('LOGGER_DRIVER'); - const logLevels = environmentService.get('LOG_LEVELS'); + const driverType = twentyConfigService.get('LOGGER_DRIVER'); + const logLevels = twentyConfigService.get('LOG_LEVELS'); switch (driverType) { case LoggerDriverType.Console: { diff --git a/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts index 12fbff397f..6255afa409 100644 --- a/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts @@ -1,18 +1,18 @@ -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { BullMQDriverFactoryOptions, MessageQueueDriverType, MessageQueueModuleOptions, } from 'src/engine/core-modules/message-queue/interfaces'; import { RedisClientService } from 'src/engine/core-modules/redis-client/redis-client.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; /** * MessageQueue Module factory * @returns MessageQueueModuleOptions - * @param environmentService + * @param twentyConfigService */ export const messageQueueModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, redisClientService: RedisClientService, ): Promise => { const driverType = MessageQueueDriverType.BullMQ; @@ -26,7 +26,7 @@ export const messageQueueModuleFactory = async ( } satisfies SyncDriverFactoryOptions; } case MessageQueueDriverType.PgBoss: { - const connectionString = environmentService.get('PG_DATABASE_URL'); + const connectionString = twentyConfigService.get('PG_DATABASE_URL'); return { type: MessageQueueDriverType.PgBoss, diff --git a/packages/twenty-server/src/engine/core-modules/metrics/metrics-cache.service.ts b/packages/twenty-server/src/engine/core-modules/metrics/metrics-cache.service.ts index 9666aef8de..3fb84e1bf4 100644 --- a/packages/twenty-server/src/engine/core-modules/metrics/metrics-cache.service.ts +++ b/packages/twenty-server/src/engine/core-modules/metrics/metrics-cache.service.ts @@ -3,8 +3,8 @@ import { Injectable } from '@nestjs/common'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; const CACHE_BUCKET_DURATION_MS = 15000; // 15 seconds window for each cache bucket @@ -16,9 +16,9 @@ export class MetricsCacheService { constructor( @InjectCacheStorage(CacheStorageNamespace.EngineHealth) private readonly cacheStorage: CacheStorageService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) { - this.healthMetricsTimeWindowInMinutes = this.environmentService.get( + this.healthMetricsTimeWindowInMinutes = this.twentyConfigService.get( 'HEALTH_METRICS_TIME_WINDOW_IN_MINUTES', ); this.healthCacheTtl = this.healthMetricsTimeWindowInMinutes * 60000 * 2; diff --git a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts index 9ac93d6045..3da44988c8 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts @@ -1,8 +1,8 @@ import { Test, TestingModule } from '@nestjs/testing'; import { AccessTokenService } from 'src/engine/core-modules/auth/token/services/access-token.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OpenApiService } from 'src/engine/core-modules/open-api/open-api.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; describe('OpenApiService', () => { @@ -21,7 +21,7 @@ describe('OpenApiService', () => { useValue: {}, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: {}, }, ], diff --git a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts index 980842cd78..5e92412fc5 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts @@ -6,7 +6,6 @@ import { capitalize } from 'twenty-shared/utils'; import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action'; import { AccessTokenService } from 'src/engine/core-modules/auth/token/services/access-token.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { baseSchema } from 'src/engine/core-modules/open-api/utils/base-schema.utils'; import { computeMetadataSchemaComponents, @@ -36,6 +35,7 @@ import { getFindOneResponse200, getUpdateOneResponse200, } from 'src/engine/core-modules/open-api/utils/responses.utils'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; import { getServerUrl } from 'src/utils/get-server-url'; @@ -43,14 +43,14 @@ import { getServerUrl } from 'src/utils/get-server-url'; export class OpenApiService { constructor( private readonly accessTokenService: AccessTokenService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly objectMetadataService: ObjectMetadataService, ) {} async generateCoreSchema(request: Request): Promise { const baseUrl = getServerUrl( request, - this.environmentService.get('SERVER_URL'), + this.twentyConfigService.get('SERVER_URL'), ); const schema = baseSchema('core', baseUrl); @@ -123,7 +123,7 @@ export class OpenApiService { ): Promise { const baseUrl = getServerUrl( request, - this.environmentService.get('SERVER_URL'), + this.twentyConfigService.get('SERVER_URL'), ); const schema = baseSchema('metadata', baseUrl); diff --git a/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.module.ts b/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.module.ts index 8e62a0db73..312c290e2e 100644 --- a/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.module.ts +++ b/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.module.ts @@ -1,11 +1,11 @@ import { Global, Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { RedisClientService } from 'src/engine/core-modules/redis-client/redis-client.service'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; @Global() @Module({ - imports: [EnvironmentModule], + imports: [TwentyConfigModule], providers: [RedisClientService], exports: [RedisClientService], }) diff --git a/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.service.ts b/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.service.ts index 57297323e8..25b9de27ae 100644 --- a/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.service.ts +++ b/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.service.ts @@ -2,17 +2,17 @@ import { Injectable, OnModuleDestroy } from '@nestjs/common'; import IORedis from 'ioredis'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class RedisClientService implements OnModuleDestroy { private redisClient: IORedis | null = null; - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} getClient() { if (!this.redisClient) { - const redisUrl = this.environmentService.get('REDIS_URL'); + const redisUrl = this.twentyConfigService.get('REDIS_URL'); if (!redisUrl) { throw new Error('REDIS_URL must be defined'); diff --git a/packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts b/packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts index 6f6f23da9a..93e4d80ff4 100644 --- a/packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts @@ -1,17 +1,17 @@ import { fromNodeProviderChain } from '@aws-sdk/credential-providers'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { ServerlessDriverType, ServerlessModuleOptions, } from 'src/engine/core-modules/serverless/serverless.interface'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const serverlessModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, fileStorageService: FileStorageService, ): Promise => { - const driverType = environmentService.get('SERVERLESS_TYPE'); + const driverType = twentyConfigService.get('SERVERLESS_TYPE'); const options = { fileStorageService }; switch (driverType) { @@ -22,16 +22,16 @@ export const serverlessModuleFactory = async ( }; } case ServerlessDriverType.Lambda: { - const region = environmentService.get('SERVERLESS_LAMBDA_REGION'); - const accessKeyId = environmentService.get( + const region = twentyConfigService.get('SERVERLESS_LAMBDA_REGION'); + const accessKeyId = twentyConfigService.get( 'SERVERLESS_LAMBDA_ACCESS_KEY_ID', ); - const secretAccessKey = environmentService.get( + const secretAccessKey = twentyConfigService.get( 'SERVERLESS_LAMBDA_SECRET_ACCESS_KEY', ); - const lambdaRole = environmentService.get('SERVERLESS_LAMBDA_ROLE'); + const lambdaRole = twentyConfigService.get('SERVERLESS_LAMBDA_ROLE'); - const subhostingRole = environmentService.get( + const subhostingRole = twentyConfigService.get( 'SERVERLESS_LAMBDA_SUBHOSTING_ROLE', ); diff --git a/packages/twenty-server/src/engine/core-modules/session-storage/session-storage.module-factory.ts b/packages/twenty-server/src/engine/core-modules/session-storage/session-storage.module-factory.ts index 84f7bed903..9ec012f041 100644 --- a/packages/twenty-server/src/engine/core-modules/session-storage/session-storage.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/session-storage/session-storage.module-factory.ts @@ -5,16 +5,16 @@ import session from 'express-session'; import { createClient } from 'redis'; import { CacheStorageType } from 'src/engine/core-modules/cache-storage/types/cache-storage-type.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const getSessionStorageOptions = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): session.SessionOptions => { const cacheStorageType = CacheStorageType.Redis; - const SERVER_URL = environmentService.get('SERVER_URL'); + const SERVER_URL = twentyConfigService.get('SERVER_URL'); - const appSecret = environmentService.get('APP_SECRET'); + const appSecret = twentyConfigService.get('APP_SECRET'); if (!appSecret) { throw new Error('APP_SECRET is not set'); @@ -44,7 +44,7 @@ export const getSessionStorageOptions = ( return sessionStorage; }*/ case CacheStorageType.Redis: { - const connectionString = environmentService.get('REDIS_URL'); + const connectionString = twentyConfigService.get('REDIS_URL'); if (!connectionString) { throw new Error( diff --git a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts index 37a04d4f43..728639de40 100644 --- a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts @@ -3,12 +3,12 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { SSOService } from 'src/engine/core-modules/sso/services/sso.service'; import { BillingService } from 'src/engine/core-modules/billing/services/billing.service'; -import { WorkspaceSSOIdentityProvider } from 'src/engine/core-modules/sso/workspace-sso-identity-provider.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { SSOService } from 'src/engine/core-modules/sso/services/sso.service'; import { SSOException } from 'src/engine/core-modules/sso/sso.exception'; +import { WorkspaceSSOIdentityProvider } from 'src/engine/core-modules/sso/workspace-sso-identity-provider.entity'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; describe('SSOService', () => { let service: SSOService; @@ -30,7 +30,7 @@ describe('SSOService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, diff --git a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts index adb9c49687..5d38b00fd4 100644 --- a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts +++ b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts @@ -8,7 +8,7 @@ import { Repository } from 'typeorm'; import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum'; import { BillingService } from 'src/engine/core-modules/billing/services/billing.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { SSOException, SSOExceptionCode, @@ -23,7 +23,7 @@ import { OIDCResponseType, WorkspaceSSOIdentityProvider, } from 'src/engine/core-modules/sso/workspace-sso-identity-provider.entity'; -import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class SSOService { @@ -31,7 +31,7 @@ export class SSOService { constructor( @InjectRepository(WorkspaceSSOIdentityProvider, 'core') private readonly workspaceSSOIdentityProviderRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly billingService: BillingService, private readonly exceptionHandlerService: ExceptionHandlerService, ) {} @@ -139,7 +139,7 @@ export class SSOService { buildCallbackUrl( identityProvider: Pick, ) { - const callbackURL = new URL(this.environmentService.get('SERVER_URL')); + const callbackURL = new URL(this.twentyConfigService.get('SERVER_URL')); callbackURL.pathname = `/auth/${identityProvider.type.toLowerCase()}/callback`; @@ -154,7 +154,9 @@ export class SSOService { identityProvider: Pick, searchParams?: Record, ) { - const authorizationUrl = new URL(this.environmentService.get('SERVER_URL')); + const authorizationUrl = new URL( + this.twentyConfigService.get('SERVER_URL'), + ); authorizationUrl.pathname = `/auth/${identityProvider.type.toLowerCase()}/login/${identityProvider.id}`; diff --git a/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts b/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts index 6f59f98478..acf3e77bc2 100644 --- a/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts +++ b/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts @@ -1,7 +1,7 @@ import { HttpService } from '@nestjs/axios'; import { Injectable, Logger } from '@nestjs/common'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; type CreateEventInput = { action: string; @@ -13,7 +13,7 @@ export class TelemetryService { private readonly logger = new Logger(TelemetryService.name); constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly httpService: HttpService, ) {} @@ -22,7 +22,7 @@ export class TelemetryService { userId: string | null | undefined, workspaceId: string | null | undefined, ) { - if (!this.environmentService.get('TELEMETRY_ENABLED')) { + if (!this.twentyConfigService.get('TELEMETRY_ENABLED')) { return { success: true }; } diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts similarity index 63% rename from packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts index 2cac00268a..ad9fd467ed 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts @@ -16,33 +16,33 @@ import { import { isDefined } from 'twenty-shared/utils'; import { EmailDriver } from 'src/engine/core-modules/email/interfaces/email.interface'; -import { AwsRegion } from 'src/engine/core-modules/environment/interfaces/aws-region.interface'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; -import { SupportDriver } from 'src/engine/core-modules/environment/interfaces/support.interface'; import { LLMChatModelDriver } from 'src/engine/core-modules/llm-chat-model/interfaces/llm-chat-model.interface'; import { LLMTracingDriver } from 'src/engine/core-modules/llm-tracing/interfaces/llm-tracing.interface'; +import { AwsRegion } from 'src/engine/core-modules/twenty-config/interfaces/aws-region.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; +import { SupportDriver } from 'src/engine/core-modules/twenty-config/interfaces/support.interface'; import { CaptchaDriverType } from 'src/engine/core-modules/captcha/interfaces'; -import { CastToBoolean } from 'src/engine/core-modules/environment/decorators/cast-to-boolean.decorator'; -import { CastToLogLevelArray } from 'src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator'; -import { CastToMeterDriverArray } from 'src/engine/core-modules/environment/decorators/cast-to-meter-driver.decorator'; -import { CastToPositiveNumber } from 'src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator'; -import { EnvironmentVariablesMetadata } from 'src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator'; -import { IsAWSRegion } from 'src/engine/core-modules/environment/decorators/is-aws-region.decorator'; -import { IsDuration } from 'src/engine/core-modules/environment/decorators/is-duration.decorator'; -import { IsOptionalOrEmptyString } from 'src/engine/core-modules/environment/decorators/is-optional-or-empty-string.decorator'; -import { IsStrictlyLowerThan } from 'src/engine/core-modules/environment/decorators/is-strictly-lower-than.decorator'; -import { IsTwentySemVer } from 'src/engine/core-modules/environment/decorators/is-twenty-semver.decorator'; -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; import { ExceptionHandlerDriver } from 'src/engine/core-modules/exception-handler/interfaces'; import { StorageDriverType } from 'src/engine/core-modules/file-storage/interfaces'; import { LoggerDriverType } from 'src/engine/core-modules/logger/interfaces'; import { MeterDriver } from 'src/engine/core-modules/metrics/types/meter-driver.type'; import { ServerlessDriverType } from 'src/engine/core-modules/serverless/serverless.interface'; +import { CastToBoolean } from 'src/engine/core-modules/twenty-config/decorators/cast-to-boolean.decorator'; +import { CastToLogLevelArray } from 'src/engine/core-modules/twenty-config/decorators/cast-to-log-level-array.decorator'; +import { CastToMeterDriverArray } from 'src/engine/core-modules/twenty-config/decorators/cast-to-meter-driver.decorator'; +import { CastToPositiveNumber } from 'src/engine/core-modules/twenty-config/decorators/cast-to-positive-number.decorator'; +import { ConfigVariablesMetadata } from 'src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator'; +import { IsAWSRegion } from 'src/engine/core-modules/twenty-config/decorators/is-aws-region.decorator'; +import { IsDuration } from 'src/engine/core-modules/twenty-config/decorators/is-duration.decorator'; +import { IsOptionalOrEmptyString } from 'src/engine/core-modules/twenty-config/decorators/is-optional-or-empty-string.decorator'; +import { IsStrictlyLowerThan } from 'src/engine/core-modules/twenty-config/decorators/is-strictly-lower-than.decorator'; +import { IsTwentySemVer } from 'src/engine/core-modules/twenty-config/decorators/is-twenty-semver.decorator'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; -export class EnvironmentVariables { - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, +export class ConfigVariables { + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Enable or disable password authentication for users', }) @CastToBoolean() @@ -50,8 +50,8 @@ export class EnvironmentVariables { @IsBoolean() AUTH_PASSWORD_ENABLED = true; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Prefills tim@apple.dev in the login form, used in local development for quicker sign-in', }) @@ -61,8 +61,8 @@ export class EnvironmentVariables { @ValidateIf((env) => env.AUTH_PASSWORD_ENABLED) SIGN_IN_PREFILLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Require email verification for user accounts', }) @CastToBoolean() @@ -70,37 +70,37 @@ export class EnvironmentVariables { @IsBoolean() IS_EMAIL_VERIFICATION_REQUIRED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the email verification token is valid', }) @IsDuration() @IsOptional() EMAIL_VERIFICATION_TOKEN_EXPIRES_IN = '1h'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the password reset token is valid', }) @IsDuration() @IsOptional() PASSWORD_RESET_TOKEN_EXPIRES_IN = '5m'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, description: 'Enable or disable the Google Calendar integration', }) @CastToBoolean() CALENDAR_PROVIDER_GOOGLE_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, description: 'Callback URL for Google Auth APIs', }) AUTH_GOOGLE_APIS_CALLBACK_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, description: 'Enable or disable Google Single Sign-On (SSO)', }) @CastToBoolean() @@ -108,42 +108,42 @@ export class EnvironmentVariables { @IsBoolean() AUTH_GOOGLE_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, + isSensitive: true, description: 'Client ID for Google authentication', }) @IsString() @ValidateIf((env) => env.AUTH_GOOGLE_ENABLED) AUTH_GOOGLE_CLIENT_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, + isSensitive: true, description: 'Client secret for Google authentication', }) @IsString() @ValidateIf((env) => env.AUTH_GOOGLE_ENABLED) AUTH_GOOGLE_CLIENT_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, + isSensitive: true, description: 'Callback URL for Google authentication', }) @IsUrl({ require_tld: false, require_protocol: true }) @ValidateIf((env) => env.AUTH_GOOGLE_ENABLED) AUTH_GOOGLE_CALLBACK_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, description: 'Enable or disable the Gmail messaging integration', }) @CastToBoolean() MESSAGING_PROVIDER_GMAIL_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, description: 'Enable or disable Microsoft authentication', }) @CastToBoolean() @@ -151,59 +151,59 @@ export class EnvironmentVariables { @IsBoolean() AUTH_MICROSOFT_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, + isSensitive: true, description: 'Client ID for Microsoft authentication', }) @IsString() @ValidateIf((env) => env.AUTH_MICROSOFT_ENABLED) AUTH_MICROSOFT_CLIENT_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, + isSensitive: true, description: 'Client secret for Microsoft authentication', }) @IsString() @ValidateIf((env) => env.AUTH_MICROSOFT_ENABLED) AUTH_MICROSOFT_CLIENT_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, + isSensitive: true, description: 'Callback URL for Microsoft authentication', }) @IsUrl({ require_tld: false, require_protocol: true }) @ValidateIf((env) => env.AUTH_MICROSOFT_ENABLED) AUTH_MICROSOFT_CALLBACK_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, + isSensitive: true, description: 'Callback URL for Microsoft APIs', }) @IsUrl({ require_tld: false, require_protocol: true }) @ValidateIf((env) => env.AUTH_MICROSOFT_ENABLED) AUTH_MICROSOFT_APIS_CALLBACK_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, description: 'Enable or disable the Microsoft messaging integration', }) @CastToBoolean() MESSAGING_PROVIDER_MICROSOFT_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, description: 'Enable or disable the Microsoft Calendar integration', }) @CastToBoolean() CALENDAR_PROVIDER_MICROSOFT_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, + isSensitive: true, description: 'Legacy variable to be deprecated when all API Keys expire. Replaced by APP_KEY', }) @@ -211,91 +211,91 @@ export class EnvironmentVariables { @IsString() ACCESS_TOKEN_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the access token is valid', }) @IsDuration() @IsOptional() ACCESS_TOKEN_EXPIRES_IN = '30m'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the refresh token is valid', }) @IsOptional() REFRESH_TOKEN_EXPIRES_IN = '60d'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Cooldown period for refreshing tokens', }) @IsDuration() @IsOptional() REFRESH_TOKEN_COOL_DOWN = '1m'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the login token is valid', }) @IsDuration() @IsOptional() LOGIN_TOKEN_EXPIRES_IN = '15m'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the file token is valid', }) @IsDuration() @IsOptional() FILE_TOKEN_EXPIRES_IN = '1d'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the invitation token is valid', }) @IsDuration() @IsOptional() INVITATION_TOKEN_EXPIRES_IN = '30d'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the short-term token is valid', }) SHORT_TERM_TOKEN_EXPIRES_IN = '5m'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'Email address used as the sender for outgoing emails', }) EMAIL_FROM_ADDRESS = 'noreply@yourdomain.com'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'Email address used for system notifications', }) EMAIL_SYSTEM_ADDRESS = 'system@yourdomain.com'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'Name used in the From header for outgoing emails', }) EMAIL_FROM_NAME = 'Felix from Twenty'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'Email driver to use for sending emails', }) EMAIL_DRIVER: EmailDriver = EmailDriver.Logger; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'SMTP host for sending emails', }) EMAIL_SMTP_HOST: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'Use unsecure connection for SMTP', }) @CastToBoolean() @@ -303,60 +303,60 @@ export class EnvironmentVariables { @IsBoolean() EMAIL_SMTP_NO_TLS = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'SMTP port for sending emails', }) @CastToPositiveNumber() EMAIL_SMTP_PORT = 587; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'SMTP user for authentication', }) EMAIL_SMTP_USER: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, + isSensitive: true, description: 'SMTP password for authentication', }) EMAIL_SMTP_PASSWORD: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, description: 'Type of storage to use (local or S3)', }) @IsEnum(StorageDriverType) @IsOptional() STORAGE_TYPE: StorageDriverType = StorageDriverType.Local; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, description: 'Local path for storage when using local storage type', }) @IsString() @ValidateIf((env) => env.STORAGE_TYPE === StorageDriverType.Local) STORAGE_LOCAL_PATH = '.local-storage'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, description: 'S3 region for storage when using S3 storage type', }) @ValidateIf((env) => env.STORAGE_TYPE === StorageDriverType.S3) @IsAWSRegion() STORAGE_S3_REGION: AwsRegion; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, description: 'S3 bucket name for storage when using S3 storage type', }) @ValidateIf((env) => env.STORAGE_TYPE === StorageDriverType.S3) @IsString() STORAGE_S3_NAME: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, description: 'S3 endpoint for storage when using S3 storage type', }) @ValidateIf((env) => env.STORAGE_TYPE === StorageDriverType.S3) @@ -364,9 +364,9 @@ export class EnvironmentVariables { @IsOptional() STORAGE_S3_ENDPOINT: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, + isSensitive: true, description: 'S3 access key ID for authentication when using S3 storage type', }) @@ -375,9 +375,9 @@ export class EnvironmentVariables { @IsOptional() STORAGE_S3_ACCESS_KEY_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, + isSensitive: true, description: 'S3 secret access key for authentication when using S3 storage type', }) @@ -386,47 +386,47 @@ export class EnvironmentVariables { @IsOptional() STORAGE_S3_SECRET_ACCESS_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'Type of serverless execution (local or Lambda)', }) @IsEnum(ServerlessDriverType) @IsOptional() SERVERLESS_TYPE: ServerlessDriverType = ServerlessDriverType.Local; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'Throttle limit for serverless function execution', }) @CastToPositiveNumber() SERVERLESS_FUNCTION_EXEC_THROTTLE_LIMIT = 10; // milliseconds - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'Time-to-live for serverless function execution throttle', }) @CastToPositiveNumber() SERVERLESS_FUNCTION_EXEC_THROTTLE_TTL = 1000; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'Region for AWS Lambda functions', }) @ValidateIf((env) => env.SERVERLESS_TYPE === ServerlessDriverType.Lambda) @IsAWSRegion() SERVERLESS_LAMBDA_REGION: AwsRegion; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'IAM role for AWS Lambda functions', }) @ValidateIf((env) => env.SERVERLESS_TYPE === ServerlessDriverType.Lambda) @IsString() SERVERLESS_LAMBDA_ROLE: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'Role to assume when hosting lambdas in dedicated AWS account', }) @ValidateIf((env) => env.SERVERLESS_TYPE === ServerlessDriverType.Lambda) @@ -434,9 +434,9 @@ export class EnvironmentVariables { @IsOptional() SERVERLESS_LAMBDA_SUBHOSTING_ROLE?: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, + isSensitive: true, description: 'Access key ID for AWS Lambda functions', }) @ValidateIf((env) => env.SERVERLESS_TYPE === ServerlessDriverType.Lambda) @@ -444,9 +444,9 @@ export class EnvironmentVariables { @IsOptional() SERVERLESS_LAMBDA_ACCESS_KEY_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, + isSensitive: true, description: 'Secret access key for AWS Lambda functions', }) @ValidateIf((env) => env.SERVERLESS_TYPE === ServerlessDriverType.Lambda) @@ -454,8 +454,8 @@ export class EnvironmentVariables { @IsOptional() SERVERLESS_LAMBDA_SECRET_ACCESS_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.AnalyticsConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.AnalyticsConfig, description: 'Enable or disable analytics for telemetry', }) @CastToBoolean() @@ -463,8 +463,8 @@ export class EnvironmentVariables { @IsBoolean() ANALYTICS_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Logging, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Logging, description: 'Enable or disable telemetry logging', }) @CastToBoolean() @@ -472,8 +472,8 @@ export class EnvironmentVariables { @IsBoolean() TELEMETRY_ENABLED = true; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, description: 'Enable or disable billing features', }) @CastToBoolean() @@ -481,16 +481,16 @@ export class EnvironmentVariables { @IsBoolean() IS_BILLING_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, description: 'Link required for billing plan', }) @IsString() @ValidateIf((env) => env.IS_BILLING_ENABLED === true) BILLING_PLAN_REQUIRED_LINK: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, description: 'Duration of free trial with credit card in days', }) @IsNumber() @@ -499,8 +499,8 @@ export class EnvironmentVariables { @ValidateIf((env) => env.IS_BILLING_ENABLED === true) BILLING_FREE_TRIAL_WITH_CREDIT_CARD_DURATION_IN_DAYS = 30; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, description: 'Duration of free trial without credit card in days', }) @IsNumber() @@ -509,34 +509,34 @@ export class EnvironmentVariables { @ValidateIf((env) => env.IS_BILLING_ENABLED === true) BILLING_FREE_TRIAL_WITHOUT_CREDIT_CARD_DURATION_IN_DAYS = 7; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, + isSensitive: true, description: 'Stripe API key for billing', }) @IsString() @ValidateIf((env) => env.IS_BILLING_ENABLED === true) BILLING_STRIPE_API_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, + isSensitive: true, description: 'Stripe webhook secret for billing', }) @IsString() @ValidateIf((env) => env.IS_BILLING_ENABLED === true) BILLING_STRIPE_WEBHOOK_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Url for the frontend application', }) @IsUrl({ require_tld: false, require_protocol: true }) @IsOptional() FRONTEND_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Default subdomain for the frontend when multi-workspace is enabled', }) @@ -544,16 +544,16 @@ export class EnvironmentVariables { @ValidateIf((env) => env.IS_MULTIWORKSPACE_ENABLED) DEFAULT_SUBDOMAIN = 'app'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'ID for the Chrome extension', }) @IsString() @IsOptional() CHROME_EXTENSION_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Logging, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Logging, description: 'Enable or disable buffering for logs before sending', }) @CastToBoolean() @@ -561,8 +561,8 @@ export class EnvironmentVariables { @IsOptional() LOGGER_IS_BUFFER_ENABLED = true; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Logging, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Logging, description: 'Driver used for handling exceptions (Console or Sentry)', }) @IsEnum(ExceptionHandlerDriver) @@ -570,39 +570,39 @@ export class EnvironmentVariables { EXCEPTION_HANDLER_DRIVER: ExceptionHandlerDriver = ExceptionHandlerDriver.Console; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Logging, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Logging, description: 'Levels of logging to be captured', }) @CastToLogLevelArray() @IsOptional() LOG_LEVELS: LogLevel[] = ['log', 'error', 'warn']; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Metering, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Metering, description: 'Driver used for collect metrics (OpenTelemetry or Console)', }) @CastToMeterDriverArray() @IsOptional() METER_DRIVER: MeterDriver[] = []; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Metering, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Metering, description: 'Endpoint URL for the OpenTelemetry collector', }) @IsOptional() OTLP_COLLECTOR_ENDPOINT_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ExceptionHandler, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ExceptionHandler, description: 'Driver used for logging (only console for now)', }) @IsEnum(LoggerDriverType) @IsOptional() LOGGER_DRIVER: LoggerDriverType = LoggerDriverType.Console; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ExceptionHandler, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ExceptionHandler, description: 'Data Source Name (DSN) for Sentry logging', }) @ValidateIf( @@ -611,8 +611,8 @@ export class EnvironmentVariables { @IsString() SENTRY_DSN: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ExceptionHandler, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ExceptionHandler, description: 'Front-end DSN for Sentry logging', }) @ValidateIf( @@ -621,8 +621,8 @@ export class EnvironmentVariables { @IsString() SENTRY_FRONT_DSN: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ExceptionHandler, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ExceptionHandler, description: 'Release version for Sentry logging', }) @ValidateIf( @@ -632,8 +632,8 @@ export class EnvironmentVariables { @IsOptional() SENTRY_RELEASE: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ExceptionHandler, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ExceptionHandler, description: 'Environment name for Sentry logging', }) @ValidateIf( @@ -643,35 +643,35 @@ export class EnvironmentVariables { @IsOptional() SENTRY_ENVIRONMENT: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.SupportChatConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.SupportChatConfig, description: 'Driver used for support chat integration', }) @IsEnum(SupportDriver) @IsOptional() SUPPORT_DRIVER: SupportDriver = SupportDriver.None; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.SupportChatConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.SupportChatConfig, + isSensitive: true, description: 'Chat ID for the support front integration', }) @ValidateIf((env) => env.SUPPORT_DRIVER === SupportDriver.Front) @IsString() SUPPORT_FRONT_CHAT_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.SupportChatConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.SupportChatConfig, + isSensitive: true, description: 'HMAC key for the support front integration', }) @ValidateIf((env) => env.SUPPORT_DRIVER === SupportDriver.Front) @IsString() SUPPORT_FRONT_HMAC_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, + isSensitive: true, description: 'Database connection URL', }) @IsDefined() @@ -683,8 +683,8 @@ export class EnvironmentVariables { }) PG_DATABASE_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Allow connections to a database with self-signed certificates', }) @@ -693,16 +693,16 @@ export class EnvironmentVariables { @IsOptional() PG_SSL_ALLOW_SELF_SIGNED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Time-to-live for cache storage in seconds', }) @CastToPositiveNumber() CACHE_STORAGE_TTL: number = 3600 * 24 * 7; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, + isSensitive: true, description: 'URL for cache storage (e.g., Redis connection URL)', }) @IsOptional() @@ -713,16 +713,16 @@ export class EnvironmentVariables { }) REDIS_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Node environment (development, production, etc.)', }) @IsEnum(NodeEnvironment) @IsString() NODE_ENV: NodeEnvironment = NodeEnvironment.production; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Port for the node server', }) @CastToPositiveNumber() @@ -730,24 +730,24 @@ export class EnvironmentVariables { @IsOptional() NODE_PORT = 3000; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Base URL for the server', }) @IsUrl({ require_tld: false, require_protocol: true }) @IsOptional() SERVER_URL = 'http://localhost:3000'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, + isSensitive: true, description: 'Secret key for the application', }) @IsString() APP_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.RateLimiting, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.RateLimiting, description: 'Maximum number of records affected by mutations', }) @CastToPositiveNumber() @@ -755,31 +755,31 @@ export class EnvironmentVariables { @IsNumber() MUTATION_MAXIMUM_AFFECTED_RECORDS = 100; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.RateLimiting, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.RateLimiting, description: 'Time-to-live for API rate limiting in milliseconds', }) @CastToPositiveNumber() API_RATE_LIMITING_TTL = 100; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.RateLimiting, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.RateLimiting, description: 'Maximum number of requests allowed in the rate limiting window', }) @CastToPositiveNumber() API_RATE_LIMITING_LIMIT = 500; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.SSL, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.SSL, description: 'Path to the SSL key for enabling HTTPS in local development', }) @IsString() @IsOptional() SSL_KEY_PATH: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.SSL, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.SSL, description: 'Path to the SSL certificate for enabling HTTPS in local development', }) @@ -787,65 +787,65 @@ export class EnvironmentVariables { @IsOptional() SSL_CERT_PATH: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.CloudflareConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.CloudflareConfig, + isSensitive: true, description: 'API key for Cloudflare integration', }) @IsString() @ValidateIf((env) => env.CLOUDFLARE_ZONE_ID) CLOUDFLARE_API_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.CloudflareConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.CloudflareConfig, description: 'Zone ID for Cloudflare integration', }) @IsString() @ValidateIf((env) => env.CLOUDFLARE_API_KEY) CLOUDFLARE_ZONE_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Random string to validate queries from Cloudflare', }) @IsString() @IsOptional() CLOUDFLARE_WEBHOOK_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.LLM, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.LLM, description: 'Driver for the LLM chat model', }) LLM_CHAT_MODEL_DRIVER: LLMChatModelDriver; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.LLM, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.LLM, + isSensitive: true, description: 'API key for OpenAI integration', }) OPENAI_API_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.LLM, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.LLM, + isSensitive: true, description: 'Secret key for Langfuse integration', }) LANGFUSE_SECRET_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.LLM, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.LLM, description: 'Public key for Langfuse integration', }) LANGFUSE_PUBLIC_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.LLM, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.LLM, description: 'Driver for LLM tracing', }) LLM_TRACING_DRIVER: LLMTracingDriver = LLMTracingDriver.Console; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Enable or disable multi-workspace support', }) @CastToBoolean() @@ -853,8 +853,8 @@ export class EnvironmentVariables { @IsBoolean() IS_MULTIWORKSPACE_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Number of inactive days before sending a deletion warning for workspaces. Used in the workspace deletion cron job to determine when to send warning emails.', }) @@ -866,8 +866,8 @@ export class EnvironmentVariables { }) WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION = 7; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Number of inactive days before soft deleting workspaces', }) @CastToPositiveNumber() @@ -878,16 +878,16 @@ export class EnvironmentVariables { }) WORKSPACE_INACTIVE_DAYS_BEFORE_SOFT_DELETION = 14; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Number of inactive days before deleting workspaces', }) @CastToPositiveNumber() @IsNumber() WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION = 21; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Maximum number of workspaces that can be deleted in a single execution', }) @@ -896,57 +896,57 @@ export class EnvironmentVariables { @ValidateIf((env) => env.MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION > 0) MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION = 5; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.RateLimiting, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.RateLimiting, description: 'Throttle limit for workflow execution', }) @CastToPositiveNumber() WORKFLOW_EXEC_THROTTLE_LIMIT = 500; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.RateLimiting, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.RateLimiting, description: 'Time-to-live for workflow execution throttle in milliseconds', }) @CastToPositiveNumber() WORKFLOW_EXEC_THROTTLE_TTL = 1000; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.CaptchaConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.CaptchaConfig, description: 'Driver for captcha integration', }) @IsEnum(CaptchaDriverType) @IsOptional() CAPTCHA_DRIVER?: CaptchaDriverType; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.CaptchaConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.CaptchaConfig, + isSensitive: true, description: 'Site key for captcha integration', }) @IsString() @IsOptional() CAPTCHA_SITE_KEY?: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.CaptchaConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.CaptchaConfig, + isSensitive: true, description: 'Secret key for captcha integration', }) @IsString() @IsOptional() CAPTCHA_SECRET_KEY?: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, + isSensitive: true, description: 'License key for the Enterprise version', }) @IsString() @IsOptional() ENTERPRISE_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Health monitoring time window in minutes', }) @IsNumber() @@ -954,8 +954,8 @@ export class EnvironmentVariables { @IsOptional() HEALTH_METRICS_TIME_WINDOW_IN_MINUTES = 5; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Enable or disable the attachment preview feature', }) @CastToBoolean() @@ -963,8 +963,8 @@ export class EnvironmentVariables { @IsBoolean() IS_ATTACHMENT_PREVIEW_ENABLED = true; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Twenty server version', }) @IsOptionalOrEmptyString() @@ -972,10 +972,8 @@ export class EnvironmentVariables { APP_VERSION?: string; } -export const validate = ( - config: Record, -): EnvironmentVariables => { - const validatedConfig = plainToClass(EnvironmentVariables, config); +export const validate = (config: Record): ConfigVariables => { + const validatedConfig = plainToClass(ConfigVariables, config); const validationErrors = validateSync(validatedConfig, { strictGroups: true, @@ -1001,7 +999,7 @@ export const validate = ( if (validationErrors.length > 0) { logValidatonErrors(validationErrors, 'error'); - throw new Error('Environment variables validation failed'); + throw new Error('Config variables validation failed'); } return validatedConfig; diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/constants/__tests__/config-variables-group-metadata.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/__tests__/config-variables-group-metadata.spec.ts new file mode 100644 index 0000000000..fc4eae8b50 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/__tests__/config-variables-group-metadata.spec.ts @@ -0,0 +1,28 @@ +import { CONFIG_VARIABLES_GROUP_METADATA } from 'src/engine/core-modules/twenty-config/constants/config-variables-group-metadata'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; + +describe('CONFIG_VARIABLES_GROUP_METADATA', () => { + it('should include all ConfigVariablesGroup enum values', () => { + const enumValues = Object.values(ConfigVariablesGroup); + const metadataKeys = Object.keys(CONFIG_VARIABLES_GROUP_METADATA); + + enumValues.forEach((enumValue) => { + expect(metadataKeys).toContain(enumValue); + }); + + metadataKeys.forEach((key) => { + expect(enumValues).toContain(key); + }); + + expect(enumValues.length).toBe(metadataKeys.length); + }); + + it('should have unique position values', () => { + const positions = Object.values(CONFIG_VARIABLES_GROUP_METADATA).map( + (metadata) => metadata.position, + ); + const uniquePositions = new Set(positions); + + expect(positions.length).toBe(uniquePositions.size); + }); +}); diff --git a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-group-metadata.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-group-metadata.ts similarity index 77% rename from packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-group-metadata.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-group-metadata.ts index bc60b25531..ed5525c94f 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-group-metadata.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-group-metadata.ts @@ -1,4 +1,4 @@ -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; type GroupMetadata = { position: number; @@ -6,114 +6,114 @@ type GroupMetadata = { isHiddenOnLoad: boolean; }; -export const ENVIRONMENT_VARIABLES_GROUP_METADATA: Record< - EnvironmentVariablesGroup, +export const CONFIG_VARIABLES_GROUP_METADATA: Record< + ConfigVariablesGroup, GroupMetadata > = { - [EnvironmentVariablesGroup.ServerConfig]: { + [ConfigVariablesGroup.ServerConfig]: { position: 100, description: '', isHiddenOnLoad: false, }, - [EnvironmentVariablesGroup.RateLimiting]: { + [ConfigVariablesGroup.RateLimiting]: { position: 200, description: 'We use this to limit the number of requests to the server. This is useful to prevent abuse.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.StorageConfig]: { + [ConfigVariablesGroup.StorageConfig]: { position: 300, description: 'By default, file uploads are stored on the local filesystem, which is suitable for traditional servers. However, for ephemeral deployment servers, it is essential to configure the variables here to set up an S3-compatible file system. This ensures that files remain unaffected by server redeploys.', isHiddenOnLoad: false, }, - [EnvironmentVariablesGroup.GoogleAuth]: { + [ConfigVariablesGroup.GoogleAuth]: { position: 400, description: 'Configure Google integration (login, calendar, email)', isHiddenOnLoad: false, }, - [EnvironmentVariablesGroup.MicrosoftAuth]: { + [ConfigVariablesGroup.MicrosoftAuth]: { position: 500, description: 'Configure Microsoft integration (login, calendar, email)', isHiddenOnLoad: false, }, - [EnvironmentVariablesGroup.EmailSettings]: { + [ConfigVariablesGroup.EmailSettings]: { position: 600, description: 'This is used for emails that are sent by the app such as invitations to join a workspace. This is not used to email CRM contacts.', isHiddenOnLoad: false, }, - [EnvironmentVariablesGroup.Logging]: { + [ConfigVariablesGroup.Logging]: { position: 700, description: '', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.ExceptionHandler]: { + [ConfigVariablesGroup.ExceptionHandler]: { position: 800, description: 'By default, exceptions are sent to the logs. This should be enough for most self-hosting use-cases. For our cloud app we use Sentry.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.Metering]: { + [ConfigVariablesGroup.Metering]: { position: 900, description: 'By default, metrics are sent to the console. OpenTelemetry collector can be set up for self-hosting use-cases.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.Other]: { + [ConfigVariablesGroup.Other]: { position: 1000, description: "The variables in this section are mostly used for internal purposes (running our Cloud offering), but shouldn't usually be required for a simple self-hosted instance", isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.BillingConfig]: { + [ConfigVariablesGroup.BillingConfig]: { position: 1100, description: 'We use Stripe in our Cloud app to charge customers. Not relevant to Self-hosters.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.CaptchaConfig]: { + [ConfigVariablesGroup.CaptchaConfig]: { position: 1200, description: 'This protects critical endpoints like login and signup with a captcha to prevent bot attacks. Likely unnecessary for self-hosting scenarios.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.CloudflareConfig]: { + [ConfigVariablesGroup.CloudflareConfig]: { position: 1300, description: '', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.LLM]: { + [ConfigVariablesGroup.LLM]: { position: 1400, description: 'Configure the LLM provider and model to use for the app. This is experimental and not linked to any public feature.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.ServerlessConfig]: { + [ConfigVariablesGroup.ServerlessConfig]: { position: 1500, description: 'In our multi-tenant cloud app, we offload untrusted custom code from workflows to a serverless system (Lambda) for enhanced security and scalability. Self-hosters with a single tenant can typically ignore this configuration.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.SSL]: { + [ConfigVariablesGroup.SSL]: { position: 1600, description: 'Configure this if you want to setup SSL on your server or full end-to-end encryption. If you just want basic HTTPS, a simple setup like Cloudflare in flexible mode might be easier.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.SupportChatConfig]: { + [ConfigVariablesGroup.SupportChatConfig]: { position: 1700, description: 'We use this to setup a small support chat on the bottom left. Currently powered by Front.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.AnalyticsConfig]: { + [ConfigVariablesGroup.AnalyticsConfig]: { position: 1800, description: 'We’re running a test to perform analytics within the app. This will evolve.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.TokensDuration]: { + [ConfigVariablesGroup.TokensDuration]: { position: 1900, description: 'These have been set to sensible default so you probably don’t need to change them unless you have a specific use-case.', diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-masking-config.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-masking-config.ts new file mode 100644 index 0000000000..8be50ecca3 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-masking-config.ts @@ -0,0 +1,29 @@ +import { ConfigVariablesMaskingStrategies } from 'src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum'; + +type LastNCharsConfig = { + strategy: ConfigVariablesMaskingStrategies.LAST_N_CHARS; + chars: number; +}; + +type HidePasswordConfig = { + strategy: ConfigVariablesMaskingStrategies.HIDE_PASSWORD; +}; + +type MaskingConfigType = { + APP_SECRET: LastNCharsConfig; + PG_DATABASE_URL: HidePasswordConfig; + REDIS_URL: HidePasswordConfig; +}; + +export const CONFIG_VARIABLES_MASKING_CONFIG: MaskingConfigType = { + APP_SECRET: { + strategy: ConfigVariablesMaskingStrategies.LAST_N_CHARS, + chars: 5, + }, + PG_DATABASE_URL: { + strategy: ConfigVariablesMaskingStrategies.HIDE_PASSWORD, + }, + REDIS_URL: { + strategy: ConfigVariablesMaskingStrategies.HIDE_PASSWORD, + }, +} as const; diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-key.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-key.ts new file mode 100644 index 0000000000..921f6f786d --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-key.ts @@ -0,0 +1,2 @@ +export const CONFIG_VARIABLES_METADATA_DECORATOR_KEY = + 'config-variables-metadata' as const; diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-names-key.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-names-key.ts new file mode 100644 index 0000000000..a84065b43d --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-names-key.ts @@ -0,0 +1,2 @@ +export const CONFIG_VARIABLES_METADATA_DECORATOR_NAMES_KEY = + 'config-variable-names' as const; diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/assert-or-warn.decorator.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/assert-or-warn.decorator.spec.ts similarity index 81% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/assert-or-warn.decorator.spec.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/assert-or-warn.decorator.spec.ts index 7479e0237a..c123aea872 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/assert-or-warn.decorator.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/assert-or-warn.decorator.spec.ts @@ -1,19 +1,19 @@ -import 'reflect-metadata'; -import { IsString, validateSync } from 'class-validator'; import { plainToClass } from 'class-transformer'; +import { IsString, validateSync } from 'class-validator'; +import 'reflect-metadata'; -import { AssertOrWarn } from 'src/engine/core-modules/environment/decorators/assert-or-warn.decorator'; +import { AssertOrWarn } from 'src/engine/core-modules/twenty-config/decorators/assert-or-warn.decorator'; describe('AssertOrWarn Decorator', () => { it('should pass validation if the condition is met', () => { - class EnvironmentVariables { + class ConfigVariables { @AssertOrWarn((object, value) => value > 10, { message: 'Value should be higher than 10', }) someProperty!: number; } - const validatedConfig = plainToClass(EnvironmentVariables, { + const validatedConfig = plainToClass(ConfigVariables, { someProperty: 15, }); @@ -23,14 +23,14 @@ describe('AssertOrWarn Decorator', () => { }); it('should provide a warning message if the condition is not met', () => { - class EnvironmentVariables { + class ConfigVariables { @AssertOrWarn((object, value) => value > 10, { message: 'Value should be higher than 10', }) someProperty!: number; } - const validatedConfig = plainToClass(EnvironmentVariables, { + const validatedConfig = plainToClass(ConfigVariables, { someProperty: 9, }); @@ -43,7 +43,7 @@ describe('AssertOrWarn Decorator', () => { }); it('should not impact errors if the condition is not met', () => { - class EnvironmentVariables { + class ConfigVariables { @IsString() unit: string; @@ -56,7 +56,7 @@ describe('AssertOrWarn Decorator', () => { duration!: number; } - const validatedConfig = plainToClass(EnvironmentVariables, { + const validatedConfig = plainToClass(ConfigVariables, { duration: 1731944140876000, unit: 's', }); diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts similarity index 93% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts index a35e03676e..4cd656dff4 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts @@ -1,6 +1,6 @@ import { plainToClass } from 'class-transformer'; -import { CastToLogLevelArray } from 'src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator'; +import { CastToLogLevelArray } from 'src/engine/core-modules/twenty-config/decorators/cast-to-log-level-array.decorator'; class TestClass { @CastToLogLevelArray() diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-positive-number.decorator.spec.ts similarity index 92% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-positive-number.decorator.spec.ts index cf302e0fd7..12a0914dc5 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-positive-number.decorator.spec.ts @@ -1,6 +1,6 @@ import { plainToClass } from 'class-transformer'; -import { CastToPositiveNumber } from 'src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator'; +import { CastToPositiveNumber } from 'src/engine/core-modules/twenty-config/decorators/cast-to-positive-number.decorator'; class TestClass { @CastToPositiveNumber() diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/assert-or-warn.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/assert-or-warn.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/assert-or-warn.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/assert-or-warn.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-boolean.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-boolean.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-boolean.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-boolean.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-log-level-array.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-log-level-array.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-meter-driver.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-meter-driver.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-meter-driver.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-meter-driver.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-positive-number.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-positive-number.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-string-array.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-string-array.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-string-array.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-string-array.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator.ts similarity index 58% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator.ts index 3297df9c26..5f84c9da83 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator.ts @@ -1,29 +1,28 @@ import { registerDecorator, ValidationOptions } from 'class-validator'; -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; import { TypedReflect } from 'src/utils/typed-reflect'; -export interface EnvironmentVariablesMetadataOptions { - group: EnvironmentVariablesGroup; +export interface ConfigVariablesMetadataOptions { + group: ConfigVariablesGroup; description: string; - sensitive?: boolean; + isSensitive?: boolean; } -export type EnvironmentVariablesMetadataMap = { - [key: string]: EnvironmentVariablesMetadataOptions; +export type ConfigVariablesMetadataMap = { + [key: string]: ConfigVariablesMetadataOptions; }; -export function EnvironmentVariablesMetadata( - options: EnvironmentVariablesMetadataOptions, +export function ConfigVariablesMetadata( + options: ConfigVariablesMetadataOptions, validationOptions?: ValidationOptions, ): PropertyDecorator { return (target: object, propertyKey: string | symbol) => { - const existingMetadata: EnvironmentVariablesMetadataMap = - TypedReflect.getMetadata('environment-variables', target.constructor) ?? - {}; + const existingMetadata: ConfigVariablesMetadataMap = + TypedReflect.getMetadata('config-variables', target.constructor) ?? {}; TypedReflect.defineMetadata( - 'environment-variables', + 'config-variables', { ...existingMetadata, [propertyKey.toString()]: options, diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/is-aws-region.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-aws-region.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/is-aws-region.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-aws-region.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/is-duration.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-duration.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/is-duration.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-duration.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/is-optional-or-empty-string.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-optional-or-empty-string.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/is-optional-or-empty-string.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-optional-or-empty-string.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/is-strictly-lower-than.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-strictly-lower-than.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/is-strictly-lower-than.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-strictly-lower-than.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/is-twenty-semver.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-twenty-semver.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/is-twenty-semver.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-twenty-semver.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-group.enum.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-group.enum.ts similarity index 93% rename from packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-group.enum.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-group.enum.ts index 1019031a66..d356499e45 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-group.enum.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-group.enum.ts @@ -1,4 +1,4 @@ -export enum EnvironmentVariablesGroup { +export enum ConfigVariablesGroup { ServerConfig = 'server-config', RateLimiting = 'rate-limiting', StorageConfig = 'storage-config', diff --git a/packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum.ts similarity index 57% rename from packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum.ts index cbbeb6ccaa..93dba5863a 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum.ts @@ -1,4 +1,4 @@ -export enum EnvironmentVariablesMaskingStrategies { +export enum ConfigVariablesMaskingStrategies { LAST_N_CHARS = 'LAST_N_CHARS', HIDE_PASSWORD = 'HIDE_PASSWORD', } diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment.service.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/environment.service.spec.ts similarity index 65% rename from packages/twenty-server/src/engine/core-modules/environment/environment.service.spec.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/environment.service.spec.ts index 1fa526b582..977c67c781 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/environment.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/environment.service.spec.ts @@ -1,17 +1,17 @@ import { ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentVariables } from 'src/engine/core-modules/environment/environment-variables'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ConfigVariables } from 'src/engine/core-modules/twenty-config/config-variables'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; -describe('EnvironmentService', () => { - let service: EnvironmentService; +describe('TwentyConfigService', () => { + let service: TwentyConfigService; let configService: ConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ - EnvironmentService, + TwentyConfigService, { provide: ConfigService, useValue: { @@ -21,10 +21,10 @@ describe('EnvironmentService', () => { ], }).compile(); - service = module.get(EnvironmentService); + service = module.get(TwentyConfigService); configService = module.get(ConfigService); - Reflect.defineMetadata('environment-variables', {}, EnvironmentVariables); + Reflect.defineMetadata('config-variables', {}, ConfigVariables); }); it('should be defined', () => { @@ -32,13 +32,13 @@ describe('EnvironmentService', () => { }); describe('getAll()', () => { - it('should return empty object when no environment variables are defined', () => { + it('should return empty object when no config variables are defined', () => { const result = service.getAll(); expect(result).toEqual({}); }); - it('should return environment variables with their metadata', () => { + it('should return config variables with their metadata', () => { const mockMetadata = { TEST_VAR: { title: 'Test Var', @@ -46,11 +46,7 @@ describe('EnvironmentService', () => { }, }; - Reflect.defineMetadata( - 'environment-variables', - mockMetadata, - EnvironmentVariables, - ); + Reflect.defineMetadata('config-variables', mockMetadata, ConfigVariables); jest.spyOn(configService, 'get').mockReturnValue('test-value'); @@ -73,11 +69,7 @@ describe('EnvironmentService', () => { }, }; - Reflect.defineMetadata( - 'environment-variables', - mockMetadata, - EnvironmentVariables, - ); + Reflect.defineMetadata('config-variables', mockMetadata, ConfigVariables); jest.spyOn(configService, 'get').mockReturnValue('super-secret-value'); diff --git a/packages/twenty-server/src/engine/core-modules/environment/interfaces/aws-region.interface.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/aws-region.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/interfaces/aws-region.interface.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/aws-region.interface.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/interfaces/node-environment.interface.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/node-environment.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/interfaces/node-environment.interface.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/node-environment.interface.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/interfaces/support.interface.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/support.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/interfaces/support.interface.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/support.interface.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment.module-definition.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module-definition.ts similarity index 86% rename from packages/twenty-server/src/engine/core-modules/environment/environment.module-definition.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module-definition.ts index 242e2ef3cd..fd8a52c510 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/environment.module-definition.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module-definition.ts @@ -2,7 +2,7 @@ import { ConfigurableModuleBuilder } from '@nestjs/common'; export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder({ - moduleName: 'Environment', + moduleName: 'TwentyConfig', }) .setClassMethodName('forRoot') .build(); diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment.module.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module.ts similarity index 50% rename from packages/twenty-server/src/engine/core-modules/environment/environment.module.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module.ts index 841f2b0bbf..2083625d83 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/environment.module.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module.ts @@ -1,9 +1,9 @@ import { Global, Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; -import { validate } from 'src/engine/core-modules/environment/environment-variables'; -import { ConfigurableModuleClass } from 'src/engine/core-modules/environment/environment.module-definition'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { validate } from 'src/engine/core-modules/twenty-config/config-variables'; +import { ConfigurableModuleClass } from 'src/engine/core-modules/twenty-config/twenty-config.module-definition'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Global() @Module({ @@ -15,7 +15,7 @@ import { EnvironmentService } from 'src/engine/core-modules/environment/environm envFilePath: process.env.NODE_ENV === 'test' ? '.env.test' : '.env', }), ], - providers: [EnvironmentService], - exports: [EnvironmentService], + providers: [TwentyConfigService], + exports: [TwentyConfigService], }) -export class EnvironmentModule extends ConfigurableModuleClass {} +export class TwentyConfigModule extends ConfigurableModuleClass {} diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.service.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.service.ts new file mode 100644 index 0000000000..6dd527991c --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.service.ts @@ -0,0 +1,73 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; + +import { ConfigVariables } from 'src/engine/core-modules/twenty-config/config-variables'; +import { CONFIG_VARIABLES_MASKING_CONFIG } from 'src/engine/core-modules/twenty-config/constants/config-variables-masking-config'; +import { ConfigVariablesMetadataOptions } from 'src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator'; +import { ConfigVariablesMaskingStrategies } from 'src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum'; +import { configVariableMaskSensitiveData } from 'src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util'; +import { TypedReflect } from 'src/utils/typed-reflect'; + +@Injectable() +export class TwentyConfigService { + constructor(private readonly configService: ConfigService) {} + + get(key: T): ConfigVariables[T] { + return this.configService.get( + key, + new ConfigVariables()[key], + ); + } + + getAll(): Record< + string, + { + value: ConfigVariables[keyof ConfigVariables]; + metadata: ConfigVariablesMetadataOptions; + } + > { + const result: Record< + string, + { + value: ConfigVariables[keyof ConfigVariables]; + metadata: ConfigVariablesMetadataOptions; + } + > = {}; + + const configVars = new ConfigVariables(); + const metadata = + TypedReflect.getMetadata('config-variables', ConfigVariables) ?? {}; + + Object.entries(metadata).forEach(([key, envMetadata]) => { + let value = + this.configService.get(key) ?? + configVars[key as keyof ConfigVariables] ?? + ''; + + if (typeof value === 'string' && key in CONFIG_VARIABLES_MASKING_CONFIG) { + const varMaskingConfig = + CONFIG_VARIABLES_MASKING_CONFIG[ + key as keyof typeof CONFIG_VARIABLES_MASKING_CONFIG + ]; + const options = + varMaskingConfig.strategy === + ConfigVariablesMaskingStrategies.LAST_N_CHARS + ? { chars: varMaskingConfig.chars } + : undefined; + + value = configVariableMaskSensitiveData( + value, + varMaskingConfig.strategy, + { ...options, variableName: key }, + ); + } + + result[key] = { + value, + metadata: envMetadata, + }; + }); + + return result; + } +} diff --git a/packages/twenty-server/src/engine/core-modules/environment/utils/__tests__/environment-variable-mask-sensitive-data.util.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/utils/__tests__/config-variable-mask-sensitive-data.util.spec.ts similarity index 53% rename from packages/twenty-server/src/engine/core-modules/environment/utils/__tests__/environment-variable-mask-sensitive-data.util.spec.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/utils/__tests__/config-variable-mask-sensitive-data.util.spec.ts index 9d84c25e34..28c0427b09 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/utils/__tests__/environment-variable-mask-sensitive-data.util.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/utils/__tests__/config-variable-mask-sensitive-data.util.spec.ts @@ -1,21 +1,21 @@ -import { EnvironmentVariablesMaskingStrategies } from 'src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum'; -import { environmentVariableMaskSensitiveData } from 'src/engine/core-modules/environment/utils/environment-variable-mask-sensitive-data.util'; +import { ConfigVariablesMaskingStrategies } from 'src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum'; +import { configVariableMaskSensitiveData } from 'src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util'; -describe('environmentVariableMaskSensitiveData', () => { +describe('configVariableMaskSensitiveData', () => { describe('LAST_N_CHARS strategy', () => { it('should mask all but the last 5 characters by default', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( 'mysecretvalue123', - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, ); expect(result).toBe('********ue123'); }); it('should mask all but the specified number of characters', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( 'mysecretvalue123', - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, { chars: 3 }, ); @@ -23,9 +23,9 @@ describe('environmentVariableMaskSensitiveData', () => { }); it('should return all asterisks if value is shorter than mask length', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( '123', - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, { chars: 5 }, ); @@ -33,9 +33,9 @@ describe('environmentVariableMaskSensitiveData', () => { }); it('should handle empty string', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( '', - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, ); expect(result).toBe(''); @@ -44,18 +44,18 @@ describe('environmentVariableMaskSensitiveData', () => { describe('HIDE_PASSWORD strategy', () => { it('should mask password in URL', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( 'postgresql://user:password123@localhost:5432/db', - EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD, + ConfigVariablesMaskingStrategies.HIDE_PASSWORD, ); expect(result).toBe('postgresql://********:********@localhost:5432/db'); }); it('should handle URL without password', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( 'postgresql://localhost:5432/db', - EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD, + ConfigVariablesMaskingStrategies.HIDE_PASSWORD, ); expect(result).toBe('postgresql://localhost:5432/db'); @@ -63,9 +63,9 @@ describe('environmentVariableMaskSensitiveData', () => { it('should throw error for invalid URLs', () => { expect(() => - environmentVariableMaskSensitiveData( + configVariableMaskSensitiveData( 'not-a-url', - EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD, + ConfigVariablesMaskingStrategies.HIDE_PASSWORD, { variableName: 'TEST_URL' }, ), ).toThrow( @@ -76,27 +76,27 @@ describe('environmentVariableMaskSensitiveData', () => { describe('edge cases', () => { it('should handle null value', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( null as any, - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, ); expect(result).toBeNull(); }); it('should handle undefined value', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( undefined as any, - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, ); expect(result).toBeUndefined(); }); it('should handle non-string value', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( 123 as any, - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, ); expect(result).toBe(123); diff --git a/packages/twenty-server/src/engine/core-modules/environment/utils/environment-variable-mask-sensitive-data.util.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util.ts similarity index 56% rename from packages/twenty-server/src/engine/core-modules/environment/utils/environment-variable-mask-sensitive-data.util.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util.ts index 4497d55e5c..4f60a2de1b 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/utils/environment-variable-mask-sensitive-data.util.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util.ts @@ -1,19 +1,19 @@ -import { EnvironmentVariablesMaskingStrategies } from 'src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum'; +import { ConfigVariablesMaskingStrategies } from 'src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum'; -export const environmentVariableMaskSensitiveData = ( +export const configVariableMaskSensitiveData = ( value: string, - strategy: EnvironmentVariablesMaskingStrategies, + strategy: ConfigVariablesMaskingStrategies, options?: { chars?: number; variableName?: string }, ): string => { if (!value || typeof value !== 'string') return value; switch (strategy) { - case EnvironmentVariablesMaskingStrategies.LAST_N_CHARS: { + case ConfigVariablesMaskingStrategies.LAST_N_CHARS: { const n = Math.max(1, options?.chars ?? 5); return value.length > n ? `********${value.slice(-n)}` : '********'; } - case EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD: { + case ConfigVariablesMaskingStrategies.HIDE_PASSWORD: { try { const url = new URL(value); @@ -27,7 +27,7 @@ export const environmentVariableMaskSensitiveData = ( return url.toString(); } catch { throw new Error( - `Invalid URL format for ${options?.variableName || 'environment variable'} in HIDE_PASSWORD masking strategy`, + `Invalid URL format for ${options?.variableName || 'config variable'} in HIDE_PASSWORD masking strategy`, ); } } diff --git a/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts b/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts index 9ee22996e2..3a07d51906 100644 --- a/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts @@ -17,8 +17,8 @@ import { PermissionsOnAllObjectRecords } from 'twenty-shared/constants'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; import { In, Repository } from 'typeorm'; -import { SupportDriver } from 'src/engine/core-modules/environment/interfaces/support.interface'; import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface'; +import { SupportDriver } from 'src/engine/core-modules/twenty-config/interfaces/support.interface'; import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service'; import { @@ -26,7 +26,6 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { FileService } from 'src/engine/core-modules/file/services/file.service'; import { OnboardingStatus } from 'src/engine/core-modules/onboarding/enums/onboarding-status.enum'; @@ -34,6 +33,7 @@ import { OnboardingService, OnboardingStepKeys, } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; @@ -70,7 +70,7 @@ export class UserResolver { @InjectRepository(User, 'core') private readonly userRepository: Repository, private readonly userService: UserService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly fileUploadService: FileUploadService, private readonly onboardingService: OnboardingService, private readonly userVarService: UserVarsService, @@ -285,10 +285,12 @@ export class UserResolver { nullable: true, }) supportUserHash(@Parent() parent: User): string | null { - if (this.environmentService.get('SUPPORT_DRIVER') !== SupportDriver.Front) { + if ( + this.twentyConfigService.get('SUPPORT_DRIVER') !== SupportDriver.Front + ) { return null; } - const key = this.environmentService.get('SUPPORT_FRONT_HMAC_KEY'); + const key = this.twentyConfigService.get('SUPPORT_FRONT_HMAC_KEY'); return getHMACKey(parent.email, key); } diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts index 7c176c618f..ef1dcd315e 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts @@ -7,15 +7,15 @@ import { AppToken, AppTokenType, } from 'src/engine/core-modules/app-token/app-token.entity'; +import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { WorkspaceInvitationException } from 'src/engine/core-modules/workspace-invitation/workspace-invitation.exception'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceInvitationService } from './workspace-invitation.service'; @@ -26,7 +26,7 @@ describe('WorkspaceInvitationService', () => { let service: WorkspaceInvitationService; let appTokenRepository: Repository; let userWorkspaceRepository: Repository; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let emailService: EmailService; let onboardingService: OnboardingService; @@ -55,7 +55,7 @@ describe('WorkspaceInvitationService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -94,7 +94,7 @@ describe('WorkspaceInvitationService', () => { userWorkspaceRepository = module.get>( getRepositoryToken(UserWorkspace, 'core'), ); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); emailService = module.get(EmailService); onboardingService = module.get(OnboardingService); }); @@ -156,7 +156,7 @@ describe('WorkspaceInvitationService', () => { type: AppTokenType.InvitationToken, } as AppToken); jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockReturnValue('http://localhost:3000'); jest.spyOn(emailService, 'send').mockResolvedValue({} as any); jest diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts index 1d3f67f84b..c361bd4738 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts @@ -22,8 +22,8 @@ import { } from 'src/engine/core-modules/auth/auth.exception'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { SendInvitationsOutput } from 'src/engine/core-modules/workspace-invitation/dtos/send-invitations.output'; @@ -42,7 +42,7 @@ export class WorkspaceInvitationService { private readonly appTokenRepository: Repository, @InjectRepository(UserWorkspace, 'core') private readonly userWorkspaceRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly emailService: EmailService, private readonly onboardingService: OnboardingService, private readonly domainManagerService: DomainManagerService, @@ -300,7 +300,7 @@ export class WorkspaceInvitationService { firstName: sender.firstName, lastName: sender.lastName, }, - serverUrl: this.environmentService.get('SERVER_URL'), + serverUrl: this.twentyConfigService.get('SERVER_URL'), locale: sender.locale as keyof typeof APP_LOCALES, }; @@ -313,7 +313,7 @@ export class WorkspaceInvitationService { i18n.activate(sender.locale); await this.emailService.send({ - from: `${sender.firstName} ${sender.lastName} (via Twenty) <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + from: `${sender.firstName} ${sender.lastName} (via Twenty) <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, to: invitation.value.email, subject: t`Join your team on Twenty`, text, @@ -360,7 +360,7 @@ export class WorkspaceInvitationService { } async generateInvitationToken(workspaceId: string, email: string) { - const expiresIn = this.environmentService.get( + const expiresIn = this.twentyConfigService.get( 'INVITATION_TOKEN_EXPIRES_IN', ); diff --git a/packages/twenty-server/src/engine/core-modules/workspace/__tests__/workspace.service.spec.ts b/packages/twenty-server/src/engine/core-modules/workspace/__tests__/workspace.service.spec.ts index 46cbb3343d..b1ce5d021f 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/__tests__/workspace.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/__tests__/workspace.service.spec.ts @@ -8,13 +8,13 @@ import { BillingService } from 'src/engine/core-modules/billing/services/billing import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { getQueueToken } from 'src/engine/core-modules/message-queue/utils/get-queue-token.util'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; @@ -81,7 +81,7 @@ describe('WorkspaceService', () => { UserService, DomainManagerService, CustomDomainService, - EnvironmentService, + TwentyConfigService, EmailService, OnboardingService, WorkspaceInvitationService, diff --git a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts index 1fb1cb8cc4..84b1dc9e3e 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts @@ -13,7 +13,6 @@ import { BillingSubscriptionService } from 'src/engine/core-modules/billing/serv import { BillingService } from 'src/engine/core-modules/billing/services/billing.service'; import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { @@ -23,6 +22,7 @@ import { import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -63,7 +63,7 @@ export class WorkspaceService extends TypeOrmQueryService { private readonly billingSubscriptionService: BillingSubscriptionService, private readonly billingService: BillingService, private readonly userWorkspaceService: UserWorkspaceService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, private readonly exceptionHandlerService: ExceptionHandlerService, private readonly permissionsService: PermissionsService, @@ -95,7 +95,7 @@ export class WorkspaceService extends TypeOrmQueryService { if ( !subdomainAvailable || - this.environmentService.get('DEFAULT_SUBDOMAIN') === newSubdomain + this.twentyConfigService.get('DEFAULT_SUBDOMAIN') === newSubdomain ) { throw new WorkspaceException( 'Subdomain already taken', @@ -189,9 +189,9 @@ export class WorkspaceService extends TypeOrmQueryService { } const authProvidersBySystem = { - google: this.environmentService.get('AUTH_GOOGLE_ENABLED'), - password: this.environmentService.get('AUTH_PASSWORD_ENABLED'), - microsoft: this.environmentService.get('AUTH_MICROSOFT_ENABLED'), + google: this.twentyConfigService.get('AUTH_GOOGLE_ENABLED'), + password: this.twentyConfigService.get('AUTH_PASSWORD_ENABLED'), + microsoft: this.twentyConfigService.get('AUTH_MICROSOFT_ENABLED'), }; if (payload.isGoogleAuthEnabled && !authProvidersBySystem.google) { @@ -267,7 +267,7 @@ export class WorkspaceService extends TypeOrmQueryService { }); await this.userWorkspaceService.createWorkspaceMember(workspace.id, user); - const appVersion = this.environmentService.get('APP_VERSION'); + const appVersion = this.twentyConfigService.get('APP_VERSION'); await this.workspaceRepository.update(workspace.id, { displayName: data.displayName, diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts index ac6388fd9f..3aa5c9c7f6 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts @@ -21,12 +21,12 @@ import { BillingSubscription } from 'src/engine/core-modules/billing/entities/bi import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service'; import { CustomDomainValidRecords } from 'src/engine/core-modules/domain-manager/dtos/custom-domain-valid-records'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { FileService } from 'src/engine/core-modules/file/services/file.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/activate-workspace-input'; @@ -68,7 +68,7 @@ export class WorkspaceResolver { private readonly workspaceService: WorkspaceService, private readonly domainManagerService: DomainManagerService, private readonly userWorkspaceService: UserWorkspaceService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly fileUploadService: FileUploadService, private readonly fileService: FileService, private readonly billingSubscriptionService: BillingSubscriptionService, @@ -184,7 +184,7 @@ export class WorkspaceResolver { async billingSubscriptions( @Parent() workspace: Workspace, ): Promise { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return []; } @@ -213,7 +213,7 @@ export class WorkspaceResolver { async currentBillingSubscription( @Parent() workspace: Workspace, ): Promise { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } @@ -248,7 +248,7 @@ export class WorkspaceResolver { @ResolveField(() => Boolean) hasValidEnterpriseKey(): boolean { - return isDefined(this.environmentService.get('ENTERPRISE_KEY')); + return isDefined(this.twentyConfigService.get('ENTERPRISE_KEY')); } @ResolveField(() => WorkspaceUrls) @@ -260,7 +260,7 @@ export class WorkspaceResolver { isGoogleAuthEnabled(@Parent() workspace: Workspace) { return ( workspace.isGoogleAuthEnabled && - this.environmentService.get('AUTH_GOOGLE_ENABLED') + this.twentyConfigService.get('AUTH_GOOGLE_ENABLED') ); } @@ -268,7 +268,7 @@ export class WorkspaceResolver { isMicrosoftAuthEnabled(@Parent() workspace: Workspace) { return ( workspace.isMicrosoftAuthEnabled && - this.environmentService.get('AUTH_MICROSOFT_ENABLED') + this.twentyConfigService.get('AUTH_MICROSOFT_ENABLED') ); } @@ -276,7 +276,7 @@ export class WorkspaceResolver { isPasswordAuthEnabled(@Parent() workspace: Workspace) { return ( workspace.isPasswordAuthEnabled && - this.environmentService.get('AUTH_PASSWORD_ENABLED') + this.twentyConfigService.get('AUTH_PASSWORD_ENABLED') ); } @@ -315,10 +315,10 @@ export class WorkspaceResolver { } const systemEnabledProviders: AuthProviders = { - google: this.environmentService.get('AUTH_GOOGLE_ENABLED'), + google: this.twentyConfigService.get('AUTH_GOOGLE_ENABLED'), magicLink: false, - password: this.environmentService.get('AUTH_PASSWORD_ENABLED'), - microsoft: this.environmentService.get('AUTH_MICROSOFT_ENABLED'), + password: this.twentyConfigService.get('AUTH_PASSWORD_ENABLED'), + microsoft: this.twentyConfigService.get('AUTH_MICROSOFT_ENABLED'), sso: [], }; diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts index 9fa5d96a3d..682cc0ddee 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts @@ -4,14 +4,13 @@ import { InjectRepository } from '@nestjs/typeorm'; import { basename, dirname, join } from 'path'; import deepEqual from 'deep-equal'; -import { IsNull, Not, Repository } from 'typeorm'; import { isDefined } from 'twenty-shared/utils'; +import { IsNull, Not, Repository } from 'typeorm'; import { FileStorageExceptionCode } from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception'; import { ServerlessExecuteResult } from 'src/engine/core-modules/serverless/drivers/interfaces/serverless-driver.interface'; import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { readFileContent } from 'src/engine/core-modules/file-storage/utils/read-file-content'; import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; @@ -25,6 +24,7 @@ import { getLayerDependencies } from 'src/engine/core-modules/serverless/drivers import { ServerlessService } from 'src/engine/core-modules/serverless/serverless.service'; import { getServerlessFolder } from 'src/engine/core-modules/serverless/utils/serverless-get-folder.utils'; import { ThrottlerService } from 'src/engine/core-modules/throttler/throttler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { CreateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/create-serverless-function.input'; import { UpdateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/update-serverless-function.input'; import { @@ -44,7 +44,7 @@ export class ServerlessFunctionService { @InjectRepository(ServerlessFunctionEntity, 'metadata') private readonly serverlessFunctionRepository: Repository, private readonly throttlerService: ThrottlerService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly analyticsService: AnalyticsService, @InjectMessageQueue(MessageQueue.serverlessFunctionQueue) private readonly messageQueueService: MessageQueueService, @@ -392,8 +392,8 @@ export class ServerlessFunctionService { try { await this.throttlerService.throttle( `${workspaceId}-serverless-function-execution`, - this.environmentService.get('SERVERLESS_FUNCTION_EXEC_THROTTLE_LIMIT'), - this.environmentService.get('SERVERLESS_FUNCTION_EXEC_THROTTLE_TTL'), + this.twentyConfigService.get('SERVERLESS_FUNCTION_EXEC_THROTTLE_LIMIT'), + this.twentyConfigService.get('SERVERLESS_FUNCTION_EXEC_THROTTLE_TTL'), ); } catch (error) { throw new ServerlessFunctionException( diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts index 2260994fec..baf4808e96 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts @@ -2,9 +2,9 @@ import { Injectable, Logger } from '@nestjs/common'; import { EntitySchema } from 'typeorm'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service'; import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource'; @@ -24,7 +24,7 @@ export class WorkspaceDatasourceFactory { constructor( private readonly dataSourceService: DataSourceService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, private readonly workspaceMetadataCacheService: WorkspaceMetadataCacheService, private readonly entitySchemaFactory: EntitySchemaFactory, @@ -124,16 +124,16 @@ export class WorkspaceDatasourceFactory { { url: dataSourceMetadata.url ?? - this.environmentService.get('PG_DATABASE_URL'), + this.twentyConfigService.get('PG_DATABASE_URL'), type: 'postgres', logging: - this.environmentService.get('NODE_ENV') === + this.twentyConfigService.get('NODE_ENV') === NodeEnvironment.development ? ['query', 'error'] : ['error'], schema: dataSourceMetadata.schema, entities: cachedEntitySchemas, - ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED') + ssl: this.twentyConfigService.get('PG_SSL_ALLOW_SELF_SIGNED') ? { rejectUnauthorized: false, } diff --git a/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts b/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts index 613b0b3810..3276051721 100644 --- a/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts +++ b/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts @@ -2,9 +2,9 @@ import { HttpException } from '@nestjs/common'; import { GraphQLError } from 'graphql'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface'; import { ExceptionHandlerWorkspace } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-workspace.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/services/cleaner.workspace-service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/services/cleaner.workspace-service.ts index db5c638e03..4afccef653 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/services/cleaner.workspace-service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/services/cleaner.workspace-service.ts @@ -15,7 +15,7 @@ import { In, Repository } from 'typeorm'; import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { UserVarsService } from 'src/engine/core-modules/user/user-vars/services/user-vars.service'; @@ -39,7 +39,7 @@ export class CleanerWorkspaceService { constructor( private readonly workspaceService: WorkspaceService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly userVarsService: UserVarsService, private readonly userService: UserService, private readonly emailService: EmailService, @@ -51,18 +51,19 @@ export class CleanerWorkspaceService { @InjectRepository(UserWorkspace, 'core') private readonly userWorkspaceRepository: Repository, ) { - this.inactiveDaysBeforeSoftDelete = this.environmentService.get( + this.inactiveDaysBeforeSoftDelete = this.twentyConfigService.get( 'WORKSPACE_INACTIVE_DAYS_BEFORE_SOFT_DELETION', ); - this.inactiveDaysBeforeDelete = this.environmentService.get( + this.inactiveDaysBeforeDelete = this.twentyConfigService.get( 'WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION', ); - this.inactiveDaysBeforeWarn = this.environmentService.get( + this.inactiveDaysBeforeWarn = this.twentyConfigService.get( 'WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION', ); - this.maxNumberOfWorkspacesDeletedPerExecution = this.environmentService.get( - 'MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION', - ); + this.maxNumberOfWorkspacesDeletedPerExecution = + this.twentyConfigService.get( + 'MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION', + ); } async computeWorkspaceBillingInactivity( @@ -128,9 +129,9 @@ export class CleanerWorkspaceService { this.emailService.send({ to: workspaceMember.userEmail, - from: `${this.environmentService.get( + from: `${this.twentyConfigService.get( 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + )} <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, subject: t`Action needed to prevent workspace deletion`, html, text, @@ -202,9 +203,9 @@ export class CleanerWorkspaceService { this.emailService.send({ to: workspaceMember.userEmail, - from: `${this.environmentService.get( + from: `${this.twentyConfigService.get( 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + )} <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, subject: 'Your workspace has been deleted', html, text, diff --git a/packages/twenty-server/src/instrument.ts b/packages/twenty-server/src/instrument.ts index 3ec3f692ba..e2f542e0aa 100644 --- a/packages/twenty-server/src/instrument.ts +++ b/packages/twenty-server/src/instrument.ts @@ -10,7 +10,7 @@ import { import * as Sentry from '@sentry/node'; import { nodeProfilingIntegration } from '@sentry/profiling-node'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { ExceptionHandlerDriver } from 'src/engine/core-modules/exception-handler/interfaces'; import { MeterDriver } from 'src/engine/core-modules/metrics/types/meter-driver.type'; diff --git a/packages/twenty-server/src/main.ts b/packages/twenty-server/src/main.ts index f884512429..d52856e8bc 100644 --- a/packages/twenty-server/src/main.ts +++ b/packages/twenty-server/src/main.ts @@ -9,11 +9,11 @@ import { useContainer, ValidationError } from 'class-validator'; import session from 'express-session'; import { graphqlUploadExpress } from 'graphql-upload'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { LoggerService } from 'src/engine/core-modules/logger/logger.service'; import { getSessionStorageOptions } from 'src/engine/core-modules/session-storage/session-storage.module-factory'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UnhandledExceptionFilter } from 'src/filters/unhandled-exception.filter'; import { AppModule } from './app.module'; @@ -38,9 +38,9 @@ const bootstrap = async () => { : {}), }); const logger = app.get(LoggerService); - const environmentService = app.get(EnvironmentService); + const twentyConfigService = app.get(TwentyConfigService); - app.use(session(getSessionStorageOptions(environmentService))); + app.use(session(getSessionStorageOptions(twentyConfigService))); // TODO: Double check this as it's not working for now, it's going to be helpful for durable trees in twenty "orm" // // Apply context id strategy for durable trees @@ -87,7 +87,7 @@ const bootstrap = async () => { // Inject the server url in the frontend page generateFrontConfig(); - await app.listen(environmentService.get('NODE_PORT')); + await app.listen(twentyConfigService.get('NODE_PORT')); }; bootstrap(); diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts index d76a6642df..5150ef3f8d 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts @@ -1,12 +1,12 @@ import { Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { GoogleCalendarClientProvider } from 'src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/providers/google-calendar.provider'; import { GoogleCalendarGetEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/services/google-calendar-get-events.service'; import { OAuth2ClientManagerModule } from 'src/modules/connected-account/oauth2-client-manager/oauth2-client-manager.module'; @Module({ - imports: [EnvironmentModule, OAuth2ClientManagerModule], + imports: [TwentyConfigModule, OAuth2ClientManagerModule], providers: [GoogleCalendarClientProvider, GoogleCalendarGetEventsService], exports: [GoogleCalendarGetEventsService], }) diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/microsoft-calendar-driver.module.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/microsoft-calendar-driver.module.ts index def97bfb69..d6635421e3 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/microsoft-calendar-driver.module.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/microsoft-calendar-driver.module.ts @@ -1,12 +1,12 @@ import { Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { MicrosoftCalendarGetEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/services/microsoft-calendar-get-events.service'; import { MicrosoftCalendarImportEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/services/microsoft-calendar-import-events.service'; import { MicrosoftOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service'; @Module({ - imports: [EnvironmentModule], + imports: [TwentyConfigModule], providers: [ MicrosoftCalendarGetEventsService, MicrosoftCalendarImportEventsService, diff --git a/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts b/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts index e5020f2542..d5c7cb89ce 100644 --- a/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts +++ b/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts @@ -3,15 +3,15 @@ import { Injectable } from '@nestjs/common'; import { OAuth2Client } from 'google-auth-library'; import { google } from 'googleapis'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class GoogleOAuth2ClientManagerService { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} public async getOAuth2Client(refreshToken: string): Promise { - const gmailClientId = this.environmentService.get('AUTH_GOOGLE_CLIENT_ID'); - const gmailClientSecret = this.environmentService.get( + const gmailClientId = this.twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'); + const gmailClientSecret = this.twentyConfigService.get( 'AUTH_GOOGLE_CLIENT_SECRET', ); diff --git a/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service.ts b/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service.ts index 7f4d263345..1a1c24b0ad 100644 --- a/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service.ts +++ b/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service.ts @@ -6,11 +6,11 @@ import { Client, } from '@microsoft/microsoft-graph-client'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class MicrosoftOAuth2ClientManagerService { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} public async getOAuth2Client(refreshToken: string): Promise { const authProvider: AuthProvider = async ( @@ -21,13 +21,13 @@ export class MicrosoftOAuth2ClientManagerService { urlData.append( 'client_id', - this.environmentService.get('AUTH_MICROSOFT_CLIENT_ID'), + this.twentyConfigService.get('AUTH_MICROSOFT_CLIENT_ID'), ); urlData.append('scope', 'https://graph.microsoft.com/.default'); urlData.append('refresh_token', refreshToken); urlData.append( 'client_secret', - this.environmentService.get('AUTH_MICROSOFT_CLIENT_SECRET'), + this.twentyConfigService.get('AUTH_MICROSOFT_CLIENT_SECRET'), ); urlData.append('grant_type', 'refresh_token'); diff --git a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-access-token.service.ts b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-access-token.service.ts index 7de5f4b00c..2843ce491a 100644 --- a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-access-token.service.ts +++ b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-access-token.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import axios from 'axios'; import { z } from 'zod'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type GoogleTokens = { accessToken: string; @@ -18,14 +18,16 @@ interface GoogleRefreshTokenResponse { } @Injectable() export class GoogleAPIRefreshAccessTokenService { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} async refreshAccessToken(refreshToken: string): Promise { const response = await axios.post( 'https://oauth2.googleapis.com/token', { - client_id: this.environmentService.get('AUTH_GOOGLE_CLIENT_ID'), - client_secret: this.environmentService.get('AUTH_GOOGLE_CLIENT_SECRET'), + client_id: this.twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'), + client_secret: this.twentyConfigService.get( + 'AUTH_GOOGLE_CLIENT_SECRET', + ), refresh_token: refreshToken, grant_type: 'refresh_token', }, diff --git a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/microsoft-api-refresh-access-token.module.ts b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/microsoft-api-refresh-access-token.module.ts index 241aa8435f..b560ab406f 100644 --- a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/microsoft-api-refresh-access-token.module.ts +++ b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/microsoft-api-refresh-access-token.module.ts @@ -1,10 +1,10 @@ import { Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { MicrosoftAPIRefreshAccessTokenService } from 'src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service'; @Module({ - imports: [EnvironmentModule], + imports: [TwentyConfigModule], providers: [MicrosoftAPIRefreshAccessTokenService], exports: [MicrosoftAPIRefreshAccessTokenService], }) diff --git a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service.ts b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service.ts index 0d71161274..64054b23b0 100644 --- a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service.ts +++ b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import axios from 'axios'; import { z } from 'zod'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type MicrosoftTokens = { accessToken: string; @@ -20,14 +20,14 @@ interface MicrosoftRefreshTokenResponse { } @Injectable() export class MicrosoftAPIRefreshAccessTokenService { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} async refreshTokens(refreshToken: string): Promise { const response = await axios.post( 'https://login.microsoftonline.com/common/oauth2/v2.0/token', new URLSearchParams({ - client_id: this.environmentService.get('AUTH_MICROSOFT_CLIENT_ID'), - client_secret: this.environmentService.get( + client_id: this.twentyConfigService.get('AUTH_MICROSOFT_CLIENT_ID'), + client_secret: this.twentyConfigService.get( 'AUTH_MICROSOFT_CLIENT_SECRET', ), refresh_token: refreshToken, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts index 100db9787d..f54c4c2e60 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts @@ -2,9 +2,9 @@ import { HttpModule } from '@nestjs/axios'; import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; @@ -24,7 +24,7 @@ import { MessageParticipantManagerModule } from 'src/modules/messaging/message-p HttpModule.register({ baseURL: 'https://www.googleapis.com/batch/gmail/v1', }), - EnvironmentModule, + TwentyConfigModule, ObjectMetadataRepositoryModule.forFeature([BlocklistWorkspaceEntity]), MessagingCommonModule, TypeOrmModule.forFeature([FeatureFlag], 'core'), diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/messaging-microsoft-driver.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/messaging-microsoft-driver.module.ts index 2c19db33f0..8835d9a1f3 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/messaging-microsoft-driver.module.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/messaging-microsoft-driver.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { MicrosoftOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service'; @@ -16,7 +16,7 @@ import { MicrosoftGetMessageListService } from './services/microsoft-get-message @Module({ imports: [ - EnvironmentModule, + TwentyConfigModule, MessagingCommonModule, FeatureFlagModule, OAuth2ClientManagerModule, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-message-list.service.dev.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-message-list.service.dev.spec.ts index f95d9947a0..88bfa5a53e 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-message-list.service.dev.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-message-list.service.dev.spec.ts @@ -3,7 +3,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ConnectedAccountProvider } from 'twenty-shared/types'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { MicrosoftOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { MessageFolderWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-folder.workspace-entity'; @@ -28,7 +28,7 @@ xdescribe('Microsoft dev tests : get message list service', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [EnvironmentModule.forRoot({})], + imports: [TwentyConfigModule.forRoot({})], providers: [ MicrosoftGetMessageListService, MicrosoftClientProvider, @@ -118,7 +118,7 @@ xdescribe('Microsoft dev tests : get full message list service for folders', () beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [EnvironmentModule.forRoot({})], + imports: [TwentyConfigModule.forRoot({})], providers: [ MicrosoftGetMessageListService, MicrosoftClientProvider, @@ -207,7 +207,7 @@ xdescribe('Microsoft dev tests : get partial message list service for folders', beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [EnvironmentModule.forRoot({})], + imports: [TwentyConfigModule.forRoot({})], providers: [ MicrosoftGetMessageListService, MicrosoftClientProvider, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.dev.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.dev.spec.ts index 28b0a8cd04..1010eb3f76 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.dev.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.dev.spec.ts @@ -3,7 +3,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ConnectedAccountProvider } from 'twenty-shared/types'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { MicrosoftOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service'; import { MicrosoftClientProvider } from 'src/modules/messaging/message-import-manager/drivers/microsoft/providers/microsoft-client.provider'; import { MicrosoftFetchByBatchService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-fetch-by-batch.service'; @@ -23,7 +23,7 @@ xdescribe('Microsoft dev tests : get messages service', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [EnvironmentModule.forRoot({})], + imports: [TwentyConfigModule.forRoot({})], providers: [ MicrosoftGetMessagesService, MicrosoftHandleErrorService, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.spec.ts index a7c9774ad9..afe372e39b 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.spec.ts @@ -3,7 +3,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ConnectedAccountProvider } from 'twenty-shared/types'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { MicrosoftOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service'; import { microsoftGraphBatchWithHtmlMessagesResponse, @@ -21,7 +21,7 @@ describe('Microsoft get messages service', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [EnvironmentModule.forRoot({})], + imports: [TwentyConfigModule.forRoot({})], providers: [ MicrosoftGetMessagesService, MicrosoftHandleErrorService, diff --git a/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts b/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts index d9455ed17b..7200734907 100644 --- a/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts +++ b/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; type MessagingTelemetryTrackInput = { eventName: string; @@ -16,7 +16,7 @@ type MessagingTelemetryTrackInput = { export class MessagingTelemetryService { constructor( private readonly analyticsService: AnalyticsService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} public async track({ diff --git a/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts b/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts index 75ae7eb2ca..0ebffda5bf 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts @@ -1,10 +1,10 @@ import { Scope } from '@nestjs/common'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { ThrottlerService } from 'src/engine/core-modules/throttler/throttler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { WorkflowRunStatus } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; @@ -30,7 +30,7 @@ export class RunWorkflowJob { private readonly workflowExecutorWorkspaceService: WorkflowExecutorWorkspaceService, private readonly workflowRunWorkspaceService: WorkflowRunWorkspaceService, private readonly throttlerService: ThrottlerService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly twentyORMManager: TwentyORMManager, ) {} @@ -182,8 +182,8 @@ export class RunWorkflowJob { try { await this.throttlerService.throttle( `${workflowId}-workflow-execution`, - this.environmentService.get('WORKFLOW_EXEC_THROTTLE_LIMIT'), - this.environmentService.get('WORKFLOW_EXEC_THROTTLE_TTL'), + this.twentyConfigService.get('WORKFLOW_EXEC_THROTTLE_LIMIT'), + this.twentyConfigService.get('WORKFLOW_EXEC_THROTTLE_TTL'), ); } catch (error) { throw new WorkflowRunException( diff --git a/packages/twenty-server/src/utils/typed-reflect.ts b/packages/twenty-server/src/utils/typed-reflect.ts index 0e8f8e99fe..a871540f90 100644 --- a/packages/twenty-server/src/utils/typed-reflect.ts +++ b/packages/twenty-server/src/utils/typed-reflect.ts @@ -3,7 +3,7 @@ import 'reflect-metadata'; import { Gate } from 'src/engine/twenty-orm/interfaces/gate.interface'; import { WorkspaceEntityDuplicateCriteria } from 'src/engine/api/graphql/workspace-query-builder/types/workspace-entity-duplicate-criteria.type'; -import { EnvironmentVariablesMetadataMap } from 'src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator'; +import { ConfigVariablesMetadataMap } from 'src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator'; export interface ReflectMetadataTypeMap { ['workspace:is-nullable-metadata-args']: true; @@ -14,7 +14,7 @@ export interface ReflectMetadataTypeMap { ['workspace:is-deprecated-field-metadata-args']: true; ['workspace:is-unique-metadata-args']: true; ['workspace:duplicate-criteria-metadata-args']: WorkspaceEntityDuplicateCriteria[]; - ['environment-variables']: EnvironmentVariablesMetadataMap; + ['config-variables']: ConfigVariablesMetadataMap; ['workspace:is-searchable-metadata-args']: boolean; } diff --git a/packages/twenty-utils/dangerfile.ts b/packages/twenty-utils/dangerfile.ts index 424fff73fd..df7a785319 100644 --- a/packages/twenty-utils/dangerfile.ts +++ b/packages/twenty-utils/dangerfile.ts @@ -18,14 +18,14 @@ if (packageChanged && !lockfileChanged) { warn(`${message} - ${idea}`); } -// Check if .env.example was changed, but not environment variable documentation +// Check if .env.example was changed, but not config variable documentation const envChanged = danger.git.modified_files.find((x) => x.includes('.env.example')) || - danger.git.modified_files.find((x) => x.includes('environment.service.ts')); + danger.git.modified_files.find((x) => x.includes('twenty-config.service.ts')); const envDocsChanged = danger.git.modified_files.includes('self-hosting.mdx'); if (envChanged && !envDocsChanged) { const message = - 'Changes were made to the environment variables, but not to the documentation'; + 'Changes were made to the config variables, but not to the documentation'; const idea = 'Please review your changes and check if a change needs to be documented!'; warn(`${message} - ${idea}`);