From 1b150e1da69cbe3b40ce072b0529dd5b912d06ad Mon Sep 17 00:00:00 2001 From: nitin <142569587+ehconitin@users.noreply.github.com> Date: Thu, 6 Feb 2025 21:38:44 +0530 Subject: [PATCH] Environment variables in admin panel (read only) - front (#10011) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Frontend for https://github.com/twentyhq/core-team-issues/issues/293 POC - https://github.com/twentyhq/twenty/pull/9903 --------- Co-authored-by: Félix Malfait Co-authored-by: Félix Malfait --- .../src/generated-metadata/graphql.ts | 35 +- .../twenty-front/src/generated/graphql.tsx | 44 +- .../components/SettingsAdminContent.tsx | 272 +--------- .../components/SettingsAdminEnvVariables.tsx | 113 ++++ .../SettingsAdminEnvVariablesRow.tsx | 130 +++++ .../SettingsAdminEnvVariablesTable.tsx | 35 ++ .../components/SettingsAdminGeneral.tsx | 192 +++++++ .../components/SettingsAdminTabContent.tsx | 18 + .../SettingsAdminWorkspaceContent.tsx | 97 ++++ .../SettingsAdminFeatureFlagsTabs.ts | 2 - .../constants/SettingsAdminTabs.ts | 4 + .../constants/SettingsAdminTabsId.ts | 1 + .../SettingsAdminUserLookupWorkspaceTabsId.ts | 2 + .../queries/getEnvironmentVariablesGrouped.ts | 7 +- ...reFlagsManagement.ts => useFeatureFlag.ts} | 43 +- .../admin-panel/hooks/useUserLookup.ts | 42 ++ .../states/adminPanelErrorState.ts | 6 + .../states/userLookupResultState.ts | 7 + packages/twenty-server/.env.example | 2 - packages/twenty-server/.env.test | 2 - .../data-seed-demo-workspace.service.ts | 9 +- .../src/database/typeorm-seeds/core/users.ts | 4 + .../admin-panel/__tests__/admin-panel.spec.ts | 80 ++- .../admin-panel/admin-panel.service.ts | 25 +- .../dtos/environment-variables-group.dto.ts | 8 +- .../environment-variables-subgroup.dto.ts | 5 +- .../google-apis-auth.controller.ts | 14 +- .../microsoft-apis-auth.controller.ts | 12 +- ...ironment-variables-group-metadata.spec.ts} | 16 +- .../environment-variables-group-metadata.ts | 44 ++ .../environment-variables-group-position.ts | 44 +- .../environment-variables-hidden-groups.ts | 4 - ...nvironment-variables-sub-group-metadata.ts | 71 +++ .../enums/environment-variables-group.enum.ts | 12 +- .../environment-variables-sub-group.enum.ts | 15 +- .../environment/environment-variables.ts | 491 +++++++++--------- .../environment/environment.service.spec.ts | 21 - .../resolvers/file-upload.resolver.ts | 3 +- .../message-queue/drivers/bullmq.driver.ts | 2 +- .../engine/core-modules/user/user.resolver.ts | 2 - .../workspace/workspace.resolver.ts | 5 +- .../src/engine/guards/demo.env.guard.ts | 36 -- .../display/icon/components/TablerIcons.ts | 5 +- 43 files changed, 1224 insertions(+), 758 deletions(-) create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariables.tsx create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariablesRow.tsx create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariablesTable.tsx create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminGeneral.tsx create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminTabContent.tsx create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminWorkspaceContent.tsx delete mode 100644 packages/twenty-front/src/modules/settings/admin-panel/constants/SettingsAdminFeatureFlagsTabs.ts create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/constants/SettingsAdminTabs.ts create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/constants/SettingsAdminTabsId.ts create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/constants/SettingsAdminUserLookupWorkspaceTabsId.ts rename packages/twenty-front/src/modules/settings/admin-panel/hooks/{useFeatureFlagsManagement.ts => useFeatureFlag.ts} (54%) create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/hooks/useUserLookup.ts create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/states/adminPanelErrorState.ts create mode 100644 packages/twenty-front/src/modules/settings/admin-panel/states/userLookupResultState.ts rename packages/twenty-server/src/engine/core-modules/environment/constants/__tests__/{environment-variables-group-position.spec.ts => environment-variables-group-metadata.spec.ts} (61%) create mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-group-metadata.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-hidden-groups.ts create mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-sub-group-metadata.ts delete mode 100644 packages/twenty-server/src/engine/guards/demo.env.guard.ts diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 68eb319d0..cd728ef0e 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -482,12 +482,10 @@ export enum EnvironmentVariablesGroup { Database = 'Database', Email = 'Email', Frontend = 'Frontend', - LLM = 'LLM', Logging = 'Logging', + Other = 'Other', QueueConfig = 'QueueConfig', - Security = 'Security', ServerConfig = 'ServerConfig', - Serverless = 'Serverless', Storage = 'Storage', Support = 'Support', Workspace = 'Workspace' @@ -495,7 +493,9 @@ export enum EnvironmentVariablesGroup { export type EnvironmentVariablesGroupData = { __typename?: 'EnvironmentVariablesGroupData'; - groupName: EnvironmentVariablesGroup; + description: Scalars['String']['output']; + isHiddenOnLoad: Scalars['Boolean']['output']; + name: EnvironmentVariablesGroup; subgroups: Array; variables: Array; }; @@ -506,26 +506,28 @@ export type EnvironmentVariablesOutput = { }; export enum EnvironmentVariablesSubGroup { + BillingConfig = 'BillingConfig', + CaptchaConfig = 'CaptchaConfig', CloudflareConfig = 'CloudflareConfig', EmailSettings = 'EmailSettings', - FrontSupportConfig = 'FrontSupportConfig', + ExceptionHandler = 'ExceptionHandler', GoogleAuth = 'GoogleAuth', - LambdaConfig = 'LambdaConfig', + LLM = 'LLM', MicrosoftAuth = 'MicrosoftAuth', PasswordAuth = 'PasswordAuth', RateLimiting = 'RateLimiting', - S3Config = 'S3Config', SSL = 'SSL', - SentryConfig = 'SentryConfig', - SmtpConfig = 'SmtpConfig', - StripeConfig = 'StripeConfig', + ServerlessConfig = 'ServerlessConfig', + StorageConfig = 'StorageConfig', + SupportChatConfig = 'SupportChatConfig', TinybirdConfig = 'TinybirdConfig', - Tokens = 'Tokens' + TokensDuration = 'TokensDuration' } export type EnvironmentVariablesSubgroupData = { __typename?: 'EnvironmentVariablesSubgroupData'; - subgroupName: EnvironmentVariablesSubGroup; + description: Scalars['String']['output']; + name: EnvironmentVariablesSubGroup; variables: Array; }; @@ -895,6 +897,7 @@ export type Mutation = { updateWorkflowVersionStep: WorkflowAction; updateWorkspace: Workspace; updateWorkspaceFeatureFlag: Scalars['Boolean']['output']; + updateWorkspaceMemberRole: WorkspaceMember; uploadFile: Scalars['String']['output']; uploadImage: Scalars['String']['output']; uploadProfilePicture: Scalars['String']['output']; @@ -1192,6 +1195,12 @@ export type MutationUpdateWorkspaceFeatureFlagArgs = { }; +export type MutationUpdateWorkspaceMemberRoleArgs = { + roleId?: InputMaybe; + workspaceMemberId: Scalars['String']['input']; +}; + + export type MutationUploadFileArgs = { file: Scalars['Upload']['input']; fileFolder?: InputMaybe; @@ -2166,8 +2175,10 @@ export type WorkspaceMember = { id: Scalars['UUID']['output']; locale?: Maybe; name: FullName; + roles?: Maybe>; timeFormat?: Maybe; timeZone?: Maybe; + userWorkspaceId?: Maybe; }; /** Date format as Month first, Day first, Year first or system as default */ diff --git a/packages/twenty-front/src/generated/graphql.tsx b/packages/twenty-front/src/generated/graphql.tsx index 33e2a6d22..253bd54f4 100644 --- a/packages/twenty-front/src/generated/graphql.tsx +++ b/packages/twenty-front/src/generated/graphql.tsx @@ -414,12 +414,10 @@ export enum EnvironmentVariablesGroup { Database = 'Database', Email = 'Email', Frontend = 'Frontend', - LLM = 'LLM', Logging = 'Logging', + Other = 'Other', QueueConfig = 'QueueConfig', - Security = 'Security', ServerConfig = 'ServerConfig', - Serverless = 'Serverless', Storage = 'Storage', Support = 'Support', Workspace = 'Workspace' @@ -427,7 +425,9 @@ export enum EnvironmentVariablesGroup { export type EnvironmentVariablesGroupData = { __typename?: 'EnvironmentVariablesGroupData'; - groupName: EnvironmentVariablesGroup; + description: Scalars['String']; + isHiddenOnLoad: Scalars['Boolean']; + name: EnvironmentVariablesGroup; subgroups: Array; variables: Array; }; @@ -438,26 +438,28 @@ export type EnvironmentVariablesOutput = { }; export enum EnvironmentVariablesSubGroup { + BillingConfig = 'BillingConfig', + CaptchaConfig = 'CaptchaConfig', CloudflareConfig = 'CloudflareConfig', EmailSettings = 'EmailSettings', - FrontSupportConfig = 'FrontSupportConfig', + ExceptionHandler = 'ExceptionHandler', GoogleAuth = 'GoogleAuth', - LambdaConfig = 'LambdaConfig', + LLM = 'LLM', MicrosoftAuth = 'MicrosoftAuth', PasswordAuth = 'PasswordAuth', RateLimiting = 'RateLimiting', - S3Config = 'S3Config', SSL = 'SSL', - SentryConfig = 'SentryConfig', - SmtpConfig = 'SmtpConfig', - StripeConfig = 'StripeConfig', + ServerlessConfig = 'ServerlessConfig', + StorageConfig = 'StorageConfig', + SupportChatConfig = 'SupportChatConfig', TinybirdConfig = 'TinybirdConfig', - Tokens = 'Tokens' + TokensDuration = 'TokensDuration' } export type EnvironmentVariablesSubgroupData = { __typename?: 'EnvironmentVariablesSubgroupData'; - subgroupName: EnvironmentVariablesSubGroup; + description: Scalars['String']; + name: EnvironmentVariablesSubGroup; variables: Array; }; @@ -812,6 +814,7 @@ export type Mutation = { updateWorkflowVersionStep: WorkflowAction; updateWorkspace: Workspace; updateWorkspaceFeatureFlag: Scalars['Boolean']; + updateWorkspaceMemberRole: WorkspaceMember; uploadFile: Scalars['String']; uploadImage: Scalars['String']; uploadProfilePicture: Scalars['String']; @@ -1059,6 +1062,12 @@ export type MutationUpdateWorkspaceFeatureFlagArgs = { }; +export type MutationUpdateWorkspaceMemberRoleArgs = { + roleId?: InputMaybe; + workspaceMemberId: Scalars['String']; +}; + + export type MutationUploadFileArgs = { file: Scalars['Upload']; fileFolder?: InputMaybe; @@ -1944,8 +1953,10 @@ export type WorkspaceMember = { id: Scalars['UUID']; locale?: Maybe; name: FullName; + roles?: Maybe>; timeFormat?: Maybe; timeZone?: Maybe; + userWorkspaceId?: Maybe; }; /** Date format as Month first, Day first, Year first or system as default */ @@ -2233,7 +2244,7 @@ export type UserLookupAdminPanelMutation = { __typename?: 'Mutation', userLookup export type GetEnvironmentVariablesGroupedQueryVariables = Exact<{ [key: string]: never; }>; -export type GetEnvironmentVariablesGroupedQuery = { __typename?: 'Query', getEnvironmentVariablesGrouped: { __typename?: 'EnvironmentVariablesOutput', groups: Array<{ __typename?: 'EnvironmentVariablesGroupData', groupName: EnvironmentVariablesGroup, variables: Array<{ __typename?: 'EnvironmentVariable', name: string, description: string, value: string, sensitive: boolean }>, subgroups: Array<{ __typename?: 'EnvironmentVariablesSubgroupData', subgroupName: EnvironmentVariablesSubGroup, variables: Array<{ __typename?: 'EnvironmentVariable', name: string, description: string, value: string, sensitive: boolean }> }> }> } }; +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 }>, subgroups: Array<{ __typename?: 'EnvironmentVariablesSubgroupData', name: EnvironmentVariablesSubGroup, description: string, variables: Array<{ __typename?: 'EnvironmentVariable', name: string, description: string, value: string, sensitive: boolean }> }> }> } }; export type UpdateLabPublicFeatureFlagMutationVariables = Exact<{ input: UpdateLabPublicFeatureFlagInput; @@ -3859,7 +3870,9 @@ export const GetEnvironmentVariablesGroupedDocument = gql` query GetEnvironmentVariablesGrouped { getEnvironmentVariablesGrouped { groups { - groupName + name + description + isHiddenOnLoad variables { name description @@ -3867,7 +3880,8 @@ export const GetEnvironmentVariablesGroupedDocument = gql` sensitive } subgroups { - subgroupName + name + description variables { name description diff --git a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminContent.tsx b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminContent.tsx index 2620ec8a3..ff4118fcd 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminContent.tsx +++ b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminContent.tsx @@ -1,55 +1,9 @@ -import { canManageFeatureFlagsState } from '@/client-config/states/canManageFeatureFlagsState'; -import { SETTINGS_ADMIN_FEATURE_FLAGS_TAB_ID } from '@/settings/admin-panel/constants/SettingsAdminFeatureFlagsTabs'; -import { useFeatureFlagsManagement } from '@/settings/admin-panel/hooks/useFeatureFlagsManagement'; -import { useImpersonate } from '@/settings/admin-panel/hooks/useImpersonate'; -import { TextInput } from '@/ui/input/components/TextInput'; +import { SettingsAdminTabContent } from '@/settings/admin-panel/components/SettingsAdminTabContent'; +import { SETTINGS_ADMIN_TABS } from '@/settings/admin-panel/constants/SettingsAdminTabs'; +import { SETTINGS_ADMIN_TABS_ID } from '@/settings/admin-panel/constants/SettingsAdminTabsId'; import { TabList } from '@/ui/layout/tab/components/TabList'; -import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; -import { Table } from '@/ui/layout/table/components/Table'; -import { TableCell } from '@/ui/layout/table/components/TableCell'; -import { TableHeader } from '@/ui/layout/table/components/TableHeader'; -import { TableRow } from '@/ui/layout/table/components/TableRow'; -import { DEFAULT_WORKSPACE_LOGO } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo'; import styled from '@emotion/styled'; -import { isNonEmptyString } from '@sniptt/guards'; -import { useState } from 'react'; -import { useRecoilValue } from 'recoil'; -import { getImageAbsoluteURI, isDefined } from 'twenty-shared'; -import { - Button, - H1Title, - H1TitleFontColor, - H2Title, - IconSearch, - IconUser, - Section, - Toggle, -} from 'twenty-ui'; -import { REACT_APP_SERVER_BASE_URL } from '~/config'; - -const StyledLinkContainer = styled.div` - margin-right: ${({ theme }) => theme.spacing(2)}; - width: 100%; -`; - -const StyledContainer = styled.div` - align-items: center; - display: flex; - flex-direction: row; -`; - -const StyledErrorSection = styled.div` - color: ${({ theme }) => theme.font.color.danger}; - margin-top: ${({ theme }) => theme.spacing(2)}; -`; - -const StyledUserInfo = styled.div` - margin-bottom: ${({ theme }) => theme.spacing(5)}; -`; - -const StyledTable = styled(Table)` - margin-top: ${({ theme }) => theme.spacing(3)}; -`; +import { IconSettings2, IconVariable } from 'twenty-ui'; const StyledTabListContainer = styled.div` align-items: center; @@ -59,210 +13,30 @@ const StyledTabListContainer = styled.div` gap: ${({ theme }) => theme.spacing(2)}; `; -const StyledContentContainer = styled.div` - flex: 1; - width: 100%; - padding: ${({ theme }) => theme.spacing(4)} 0; -`; - export const SettingsAdminContent = () => { - const [userIdentifier, setUserIdentifier] = useState(''); - const [userId, setUserId] = useState(''); - - const { - handleImpersonate, - isLoading: isImpersonateLoading, - error: impersonateError, - canImpersonate, - } = useImpersonate(); - - const { activeTabId, setActiveTabId } = useTabList( - SETTINGS_ADMIN_FEATURE_FLAGS_TAB_ID, - ); - - const { - userLookupResult, - handleUserLookup, - handleFeatureFlagUpdate, - isLoading, - error, - } = useFeatureFlagsManagement(); - - const canManageFeatureFlags = useRecoilValue(canManageFeatureFlagsState); - - const handleSearch = async () => { - setActiveTabId(''); - - const result = await handleUserLookup(userIdentifier); - - if (isDefined(result?.user?.id) && !error) { - setUserId(result.user.id.trim()); - } - - if ( - isDefined(result?.workspaces) && - result.workspaces.length > 0 && - !error - ) { - setActiveTabId(result.workspaces[0].id); - } - }; - - const shouldShowUserData = userLookupResult && !error; - - const activeWorkspace = userLookupResult?.workspaces.find( - (workspace) => workspace.id === activeTabId, - ); - - const tabs = - userLookupResult?.workspaces.map((workspace) => ({ - id: workspace.id, - title: workspace.name, - logo: - getImageAbsoluteURI({ - imageUrl: isNonEmptyString(workspace.logo) - ? workspace.logo - : DEFAULT_WORKSPACE_LOGO, - baseUrl: REACT_APP_SERVER_BASE_URL, - }) ?? '', - })) ?? []; - - const renderWorkspaceContent = () => { - if (!activeWorkspace) return null; - - return ( - <> - - 1 ? 'Users' : 'User' - }`} - description={'Total Users'} - /> - {canImpersonate && ( -