From bd3ec6d5e398813c771685f7593a1bf751a7aa94 Mon Sep 17 00:00:00 2001 From: nitin <142569587+ehconitin@users.noreply.github.com> Date: Wed, 9 Apr 2025 17:41:26 +0530 Subject: [PATCH] rename core-module environment to twenty-config (#11445) closes https://github.com/twentyhq/core-team-issues/issues/759 --- .../src/generated-metadata/graphql.ts | 153 +++-- .../twenty-front/src/generated/graphql.tsx | 122 ++-- .../components/SettingsAdminEnvVariables.tsx | 14 +- .../SettingsAdminEnvVariablesRow.tsx | 8 +- .../SettingsAdminEnvVariablesTable.tsx | 2 +- ...rouped.ts => getConfigVariablesGrouped.ts} | 8 +- .../SettingsAdminSecondaryEnvVariables.tsx | 18 +- .../twenty-server/jest-integration.config.ts | 2 +- .../__tests__/upgrade.command-runner.spec.ts | 26 +- .../command-runners/upgrade.command-runner.ts | 6 +- .../data-seed-demo-workspace.module.ts | 4 +- .../data-seed-demo-workspace.service.ts | 6 +- .../data-seed-dev-workspace.command.ts | 8 +- .../upgrade.command.ts | 6 +- .../src/database/typeorm/typeorm.module.ts | 4 +- .../src/database/typeorm/typeorm.service.ts | 18 +- .../graphql-config/graphql-config.service.ts | 12 +- .../graphql/metadata-graphql-api.module.ts | 8 +- .../api/graphql/metadata.module-factory.ts | 12 +- .../src/engine/api/rest/rest-api.service.ts | 12 +- .../admin-panel-health.service.spec.ts | 8 +- .../__tests__/admin-panel.service.spec.ts | 44 +- .../admin-panel/admin-panel.resolver.ts | 10 +- .../admin-panel/admin-panel.service.ts | 42 +- ...variable.dto.ts => config-variable.dto.ts} | 4 +- .../dtos/config-variables-group.dto.ts | 23 + .../dtos/config-variables.output.ts | 9 + .../dtos/environment-variables-group.dto.ts | 24 - .../dtos/environment-variables.output.ts | 9 - .../analytics/analytics.service.spec.ts | 4 +- .../analytics/analytics.service.ts | 6 +- .../approved-access-domain.service.ts | 10 +- .../services/approved-access-domain.spec.ts | 18 +- .../google-apis-auth.controller.ts | 6 +- .../microsoft-apis-auth.controller.ts | 6 +- .../enterprise-features-enabled.guard.ts | 6 +- ...pis-oauth-exchange-code-for-token.guard.ts | 10 +- .../google-apis-oauth-request-code.guard.ts | 14 +- .../guards/google-provider-enabled.guard.ts | 8 +- ...pis-oauth-exchange-code-for-token.guard.ts | 10 +- ...microsoft-apis-oauth-request-code.guard.ts | 14 +- .../microsoft-provider-enabled.guard.ts | 8 +- .../auth/services/api-key.service.spec.ts | 10 +- .../auth/services/api-key.service.ts | 4 +- .../auth/services/auth-sso.service.ts | 8 +- .../auth/services/auth-sso.spec.ts | 14 +- .../auth/services/auth.service.spec.ts | 10 +- .../auth/services/auth.service.ts | 16 +- .../auth/services/google-apis.service.ts | 10 +- .../auth/services/microsoft-apis.service.ts | 12 +- .../services/reset-password.service.spec.ts | 12 +- .../auth/services/reset-password.service.ts | 10 +- .../auth/services/sign-in-up.service.spec.ts | 18 +- .../auth/services/sign-in-up.service.ts | 10 +- .../google-apis-oauth-common.auth.strategy.ts | 10 +- ...h-exchange-code-for-token.auth.strategy.ts | 6 +- ...e-apis-oauth-request-code.auth.strategy.ts | 6 +- .../auth/strategies/google.auth.strategy.ts | 10 +- .../auth/strategies/jwt.auth.strategy.ts | 4 +- ...crosoft-apis-oauth-common.auth.strategy.ts | 10 +- ...h-exchange-code-for-token.auth.strategy.ts | 6 +- ...t-apis-oauth-request-code.auth.strategy.ts | 6 +- .../strategies/microsoft.auth.strategy.ts | 10 +- .../services/access-token.service.spec.ts | 14 +- .../token/services/access-token.service.ts | 8 +- .../email-verification-token.service.spec.ts | 10 +- .../email-verification-token.service.ts | 6 +- .../services/login-token.service.spec.ts | 12 +- .../token/services/login-token.service.ts | 6 +- .../services/refresh-token.service.spec.ts | 14 +- .../token/services/refresh-token.service.ts | 8 +- .../services/transient-token.service.spec.ts | 12 +- .../token/services/transient-token.service.ts | 6 +- .../billing-feature-used.listener.ts | 6 +- .../billing-workspace-member.listener.ts | 6 +- .../billing/services/billing-usage.service.ts | 6 +- .../billing/services/billing.service.ts | 6 +- .../stripe-billing-meter-event.service.ts | 8 +- .../services/stripe-billing-meter.service.ts | 8 +- .../services/stripe-billing-portal.service.ts | 8 +- .../services/stripe-checkout.service.ts | 10 +- .../services/stripe-customer.service.ts | 8 +- .../stripe/services/stripe-price.service.ts | 8 +- .../stripe/services/stripe-product.service.ts | 8 +- .../stripe-subscription-item.service.ts | 8 +- .../services/stripe-subscription.service.ts | 8 +- .../stripe/services/stripe-webhook.service.ts | 10 +- .../cache-storage.module-factory.ts | 8 +- .../cache-storage/cache-storage.module.ts | 4 +- .../captcha/captcha.module-factory.ts | 10 +- .../client-config.resolver.spec.ts | 4 +- .../client-config/client-config.resolver.ts | 65 +-- .../engine/core-modules/core-engine.module.ts | 24 +- .../controllers/cloudflare.spec.ts | 26 +- .../guards/cloudflare-secret.guard.ts | 6 +- .../guards/cloudflare-secret.spec.ts | 16 +- .../services/custom-domain.service.spec.ts | 30 +- .../services/custom-domain.service.ts | 18 +- .../services/domain-manager.service.spec.ts | 22 +- .../services/domain-manager.service.ts | 24 +- .../email-verification.module.ts | 4 +- .../services/email-verification.service.ts | 12 +- .../email/email.module-factory.ts | 16 +- ...vironment-variables-group-metadata.spec.ts | 28 - .../environment-variables-masking-config.ts | 29 - ...onment-variables-metadata-decorator-key.ts | 2 - ...-variables-metadata-decorator-names-key.ts | 2 - .../environment/environment.service.ts | 78 --- .../exception-handler.module-factory.ts | 18 +- .../file-storage.module-factory.ts | 20 +- .../file/file-upload/file-upload.module.ts | 4 +- .../resolvers/file-upload.resolver.spec.ts | 4 +- .../engine/core-modules/file/file.module.ts | 4 +- .../file/services/file.service.spec.ts | 6 +- .../file/services/file.service.ts | 6 +- .../generate-graphql-error-from-error.util.ts | 2 +- .../services/guard-redirect.service.ts | 10 +- .../src/engine/core-modules/jwt/jwt.module.ts | 14 +- .../jwt/services/jwt-wrapper.service.ts | 8 +- .../llm-chat-model.module-factory.ts | 6 +- .../llm-tracing/llm-tracing.module-factory.ts | 10 +- .../logger/logger.module-factory.ts | 12 +- .../message-queue.module-factory.ts | 8 +- .../metrics/metrics-cache.service.ts | 6 +- .../open-api/open-api.service.spec.ts | 4 +- .../core-modules/open-api/open-api.service.ts | 8 +- .../redis-client/redis-client.module.ts | 4 +- .../redis-client/redis-client.service.ts | 6 +- .../serverless/serverless-module.factory.ts | 16 +- .../session-storage.module-factory.ts | 10 +- .../sso/services/sso.service.spec.ts | 8 +- .../core-modules/sso/services/sso.service.ts | 12 +- .../telemetry/telemetry.service.ts | 6 +- .../config-variables.ts} | 530 +++++++++--------- .../config-variables-group-metadata.spec.ts | 28 + .../config-variables-group-metadata.ts} | 44 +- .../config-variables-masking-config.ts | 29 + ...config-variables-metadata-decorator-key.ts | 2 + ...-variables-metadata-decorator-names-key.ts | 2 + .../assert-or-warn.decorator.spec.ts | 18 +- .../cast-to-log-level-array.decorator.spec.ts | 2 +- .../cast-to-positive-number.decorator.spec.ts | 2 +- .../decorators/assert-or-warn.decorator.ts | 0 .../decorators/cast-to-boolean.decorator.ts | 0 .../cast-to-log-level-array.decorator.ts | 0 .../cast-to-meter-driver.decorator.ts | 0 .../cast-to-positive-number.decorator.ts | 0 .../cast-to-string-array.decorator.ts | 0 .../config-variables-metadata.decorator.ts} | 23 +- .../decorators/is-aws-region.decorator.ts | 0 .../decorators/is-duration.decorator.ts | 0 .../is-optional-or-empty-string.decorator.ts | 0 .../is-strictly-lower-than.decorator.ts | 0 .../decorators/is-twenty-semver.decorator.ts | 0 .../enums/config-variables-group.enum.ts} | 2 +- ...nfig-variables-masking-strategies.enum.ts} | 2 +- .../environment.service.spec.ts | 30 +- .../interfaces/aws-region.interface.ts | 0 .../interfaces/node-environment.interface.ts | 0 .../interfaces/support.interface.ts | 0 .../twenty-config.module-definition.ts} | 2 +- .../twenty-config.module.ts} | 12 +- .../twenty-config/twenty-config.service.ts | 73 +++ ...variable-mask-sensitive-data.util.spec.ts} | 46 +- ...nfig-variable-mask-sensitive-data.util.ts} | 12 +- .../engine/core-modules/user/user.resolver.ts | 12 +- .../workspace-invitation.service.spec.ts | 14 +- .../services/workspace-invitation.service.ts | 10 +- .../__tests__/workspace.service.spec.ts | 4 +- .../workspace/services/workspace.service.ts | 14 +- .../workspace/workspace.resolver.ts | 22 +- .../serverless-function.service.ts | 10 +- .../factories/workspace-datasource.factory.ts | 12 +- .../utils/global-exception-handler.util.ts | 2 +- .../services/cleaner.workspace-service.ts | 25 +- packages/twenty-server/src/instrument.ts | 2 +- packages/twenty-server/src/main.ts | 10 +- .../google-calendar-driver.module.ts | 4 +- .../microsoft-calendar-driver.module.ts | 4 +- .../google-oauth2-client-manager.service.ts | 8 +- ...microsoft-oauth2-client-manager.service.ts | 8 +- ...google-api-refresh-access-token.service.ts | 10 +- ...crosoft-api-refresh-access-token.module.ts | 4 +- .../microsoft-api-refresh-tokens.service.ts | 8 +- .../gmail/messaging-gmail-driver.module.ts | 4 +- .../messaging-microsoft-driver.module.ts | 4 +- ...osoft-get-message-list.service.dev.spec.ts | 8 +- ...microsoft-get-messages.service.dev.spec.ts | 4 +- .../microsoft-get-messages.service.spec.ts | 4 +- .../services/messaging-telemetry.service.ts | 4 +- .../workflow-runner/jobs/run-workflow.job.ts | 8 +- .../twenty-server/src/utils/typed-reflect.ts | 4 +- packages/twenty-utils/dangerfile.ts | 6 +- 193 files changed, 1454 insertions(+), 1422 deletions(-) rename packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/{getEnvironmentVariablesGrouped.ts => getConfigVariablesGrouped.ts} (58%) rename packages/twenty-server/src/engine/core-modules/admin-panel/dtos/{environment-variable.dto.ts => config-variable.dto.ts} (75%) create mode 100644 packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables-group.dto.ts create mode 100644 packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables.output.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables-group.dto.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables.output.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/__tests__/environment-variables-group-metadata.spec.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-masking-config.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-key.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-names-key.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/environment.service.ts rename packages/twenty-server/src/engine/core-modules/{environment/environment-variables.ts => twenty-config/config-variables.ts} (63%) create mode 100644 packages/twenty-server/src/engine/core-modules/twenty-config/constants/__tests__/config-variables-group-metadata.spec.ts rename packages/twenty-server/src/engine/core-modules/{environment/constants/environment-variables-group-metadata.ts => twenty-config/constants/config-variables-group-metadata.ts} (77%) create mode 100644 packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-masking-config.ts create mode 100644 packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-key.ts create mode 100644 packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-names-key.ts rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/__tests__/assert-or-warn.decorator.spec.ts (81%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts (93%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/__tests__/cast-to-positive-number.decorator.spec.ts (92%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/assert-or-warn.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/cast-to-boolean.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/cast-to-log-level-array.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/cast-to-meter-driver.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/cast-to-positive-number.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/cast-to-string-array.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment/decorators/environment-variables-metadata.decorator.ts => twenty-config/decorators/config-variables-metadata.decorator.ts} (58%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/is-aws-region.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/is-duration.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/is-optional-or-empty-string.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/is-strictly-lower-than.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/is-twenty-semver.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment/enums/environment-variables-group.enum.ts => twenty-config/enums/config-variables-group.enum.ts} (93%) rename packages/twenty-server/src/engine/core-modules/{environment/enums/environment-variables-masking-strategies.enum.ts => twenty-config/enums/config-variables-masking-strategies.enum.ts} (57%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/environment.service.spec.ts (65%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/interfaces/aws-region.interface.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/interfaces/node-environment.interface.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/interfaces/support.interface.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment/environment.module-definition.ts => twenty-config/twenty-config.module-definition.ts} (86%) rename packages/twenty-server/src/engine/core-modules/{environment/environment.module.ts => twenty-config/twenty-config.module.ts} (50%) create mode 100644 packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.service.ts rename packages/twenty-server/src/engine/core-modules/{environment/utils/__tests__/environment-variable-mask-sensitive-data.util.spec.ts => twenty-config/utils/__tests__/config-variable-mask-sensitive-data.util.spec.ts} (53%) rename packages/twenty-server/src/engine/core-modules/{environment/utils/environment-variable-mask-sensitive-data.util.ts => twenty-config/utils/config-variable-mask-sensitive-data.util.ts} (56%) diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index dedafd5f4..d71c26ea2 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 878e7002b..3379f8e18 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 893ebf5ef..7aed808d1 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 94a575497..27ecee163 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 7c8f94c25..329964025 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 735e95f69..ce89803ad 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 332e243bf..05b499db5 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 82f7854a9..e3313adcd 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 e322284b3..2ae7d26bb 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 d3ce4a65f..e1336ff5d 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 d7be191c3..0ca70c13f 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 7d0cf6c28..b3832fadb 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 b0ef99dde..c247d00cc 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 15733f0c6..88a9b26e3 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 f1fe7e0ae..dcf12bc27 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 6e8593561..72e5f7757 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 f7ac4328f..d9962cdb0 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 eeed12f25..c86eee4d9 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 128df3f96..d69a01e6a 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 c84a3af95..521e99df1 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 a47d09ad7..1c0605ada 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 42a5bfb5b..976d761cb 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 110ea9a3b..a729d0b66 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 fa1a7c1e0..290731f3e 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 000000000..b2a7f9f84 --- /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 000000000..8df5acc60 --- /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 bc75ceb2c..000000000 --- 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 02e98d388..000000000 --- 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 36feaed4d..c4818ff2c 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 b0cc7788b..01e3fcebc 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 b6bdefde3..b9b57f43f 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 6914161c4..e18db65b5 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 cbac8c65d..15574a13f 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 d7ca0509a..c0e062804 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 2f7e92587..4c547a269 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 3e6c57fac..0d32c2fa4 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 834fdd7d8..038aba1ab 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 731caf769..1d57f750e 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 c814fe821..d26c5fdf2 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 877a1d007..82504a2a9 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 9b29bae0b..fdba7cc31 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 7159269ec..bff67b54e 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 f6bad8222..85c51dcac 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 30ef9996a..a779b8c58 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 7f2ff2eca..1fbba06ad 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 c18b794ae..3dc84386d 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 64d03914a..9b7117301 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 3621f4737..8baa9a08c 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 0ca3ed6fd..de544b302 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 2939b9b3b..c573a6e81 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 7a7f567c6..997c0f7c5 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 d6caff560..3a079cb71 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 5a59d01a8..beb6715b3 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 36351e2a4..de7c1943f 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 1b89939b6..f10e63f5a 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 0eda93a5b..b5339f5af 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 5a6fe9e09..d2f132eaf 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 8eea41009..012e44832 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 e0be81b2e..69d33fc8b 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 ef40f3311..c0b9e418f 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 c0ddea4d4..9a48798b6 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 68407499e..0c48e37d1 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 5b09e5e03..2a46f63db 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 003898b1d..cd65d2a1f 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 1ee9e31e9..13a45ab55 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 02b6cdb4c..3e350726e 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 047958893..823431950 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 a1af3de1a..b125393c4 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 a53238067..6262d08f8 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 ea574709b..40172c2e3 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 6add5757a..4e774a279 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 5446193fe..075ab8416 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 78023175f..f690682b0 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 28b030fb4..328135c0c 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 0287ee3a9..ece0de3dc 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 2ec8dc157..b024edf9d 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 1b812b9a0..90d9f4604 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 7900db366..7ed9f1a5e 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 dabd0eaad..c1302b1f3 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 e143aa43d..ebe55ef16 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 0e500862d..c6c62caa9 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 877516913..a8e889d91 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 ff9ee6c44..ca2a4c980 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 1f7a40b40..403da680f 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 60df5eebe..ae72d1cc5 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 88e0977b8..23649f366 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 7a84d95c3..afc1f4be7 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 3f12d09e6..96210df65 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 c6a1e4c23..622e9c979 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 fdca070c8..e67b141c0 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 30fc67cfb..b230c550a 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 fcbf7cc19..15e616085 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 fe847fb05..9ed483f30 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 62d6b33bd..f6f88c95e 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 75c4a5db2..0c2815097 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 69b0a16b4..dbfaaa9bc 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 bca196fa3..56787244e 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 d39d05ab7..73c0c1d5e 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 22b2103eb..5696b732f 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 233dcb1f3..c22faf26c 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 d94198b78..b84967543 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 fba352471..690433bf2 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 121f53261..000000000 --- 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 4b0d9a848..000000000 --- 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 a1249e471..000000000 --- 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 aa1c0c378..000000000 --- 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 c0a9158bf..000000000 --- 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 75a2fadfd..e4aff0270 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 1683645c6..edb23a2f2 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 d0de77e23..f2d109931 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 9633227b3..850cd9aff 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 c52dc0f92..b8a3b356b 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 ecc5ee5fa..387b71e2a 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 e40f540db..e7af3a44c 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 73f857b05..30296cb2a 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 26f9555b5..deda56193 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 8a689819c..6a7dd20c6 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 de94bfe87..e5c803cde 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 e0ea03e54..ca52375ac 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 94abe251e..5f716415a 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 94b490fdc..499206158 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 12fbff397..6255afa40 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 9666aef8d..3fb84e1bf 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 9ac93d604..3da44988c 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 980842cd7..5e92412fc 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 8e62a0db7..312c290e2 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 57297323e..25b9de27a 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 6f6f23da9..93e4d80ff 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 84f7bed90..9ec012f04 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 37a04d4f4..728639de4 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 adb9c4968..5d38b00fd 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 6f59f9847..acf3e77bc 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 2cac00268..ad9fd467e 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 000000000..fc4eae8b5 --- /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 bc60b2553..ed5525c94 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 000000000..8be50ecca --- /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 000000000..921f6f786 --- /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 000000000..a84065b43 --- /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 7479e0237..c123aea87 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 a35e03676..4cd656dff 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 cf302e0fd..12a0914dc 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 3297df9c2..5f84c9da8 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 1019031a6..d356499e4 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 cbbeb6cca..93dba5863 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 1fa526b58..977c67c78 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 242e2ef3c..fd8a52c51 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 841f2b0bb..2083625d8 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 000000000..6dd527991 --- /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 9d84c25e3..28c0427b0 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 4497d55e5..4f60a2de1 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 9ee22996e..3a07d5190 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 7c176c618..ef1dcd315 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 1d3f67f84..c361bd473 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 46cbb3343..b1ce5d021 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 1fb1cb8cc..84b1dc9e3 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 ac6388fd9..3aa5c9c7f 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 9fa5d96a3..682cc0dde 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 2260994fe..baf4808e9 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 613b0b381..327605172 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 db5c638e0..4afccef65 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 3ec3f692b..e2f542e0a 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 f88451242..d52856e8b 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 d76a6642d..5150ef3f8 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 def97bfb6..d6635421e 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 e5020f254..d5c7cb89c 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 7f4d26334..1a1c24b0a 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 7de5f4b00..2843ce491 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 241aa8435..b560ab406 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 0d7116127..64054b23b 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 100db9787..f54c4c2e6 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 2c19db33f..8835d9a1f 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 f95d9947a..88bfa5a53 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 28b0a8cd0..1010eb3f7 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 a7c9774ad..afe372e39 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 d9455ed17..720073490 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 75ae7eb2c..0ebffda5b 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 0e8f8e99f..a871540f9 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 424fff73f..df7a78531 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}`);