From 53b51c8bbac2961c61bb7dfda803d5c975307d15 Mon Sep 17 00:00:00 2001 From: Guillim Date: Tue, 4 Feb 2025 15:20:35 +0100 Subject: [PATCH] Fix-issue-370 (#9996) Fixes the issue from introduced when alowing gmail and outlook. fixes https://github.com/twentyhq/core-team-issues/issues/370 --- .../src/generated-metadata/graphql.ts | 82 +++++++++++- .../twenty-front/src/generated/graphql.tsx | 21 ++- .../components/ClientConfigProviderEffect.tsx | 30 +++++ .../graphql/queries/getClientConfig.ts | 4 + .../states/isGoogleCalendarEnabledState.ts | 6 + .../states/isGoogleMessagingEnabledState.ts | 6 + .../states/isMicrosoftCalendarEnabledState.ts | 6 + .../isMicrosoftMessagingEnabledState.ts | 6 + .../SettingsAccountsListEmptyStateCard.tsx | 46 +++++-- .../src/testing/mock-data/config.ts | 4 + packages/twenty-server/.env.example | 2 + packages/twenty-server/.env.test | 6 + ...pis-oauth-exchange-code-for-token.guard.ts | 10 ++ ...microsoft-apis-oauth-request-code.guard.ts | 14 ++ .../auth/services/microsoft-apis.service.ts | 121 ++++++++++-------- .../client-config/client-config.entity.ts | 12 ++ .../client-config/client-config.resolver.ts | 12 ++ .../environment/environment-variables.ts | 16 +++ .../content/developers/self-hosting/setup.mdx | 4 + 19 files changed, 338 insertions(+), 70 deletions(-) create mode 100644 packages/twenty-front/src/modules/client-config/states/isGoogleCalendarEnabledState.ts create mode 100644 packages/twenty-front/src/modules/client-config/states/isGoogleMessagingEnabledState.ts create mode 100644 packages/twenty-front/src/modules/client-config/states/isMicrosoftCalendarEnabledState.ts create mode 100644 packages/twenty-front/src/modules/client-config/states/isMicrosoftMessagingEnabledState.ts diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index a0a2e2b97..9dc6134b0 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -258,6 +258,10 @@ export type ClientConfig = { defaultSubdomain?: Maybe; frontDomain: Scalars['String']['output']; isEmailVerificationRequired: Scalars['Boolean']['output']; + isGoogleCalendarEnabled: Scalars['Boolean']['output']; + isGoogleMessagingEnabled: Scalars['Boolean']['output']; + isMicrosoftCalendarEnabled: Scalars['Boolean']['output']; + isMicrosoftMessagingEnabled: Scalars['Boolean']['output']; isMultiWorkspaceEnabled: Scalars['Boolean']['output']; publicFeatureFlags: Array; sentry: Sentry; @@ -462,6 +466,69 @@ 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 { + Analytics = 'Analytics', + Authentication = 'Authentication', + Billing = 'Billing', + Cache = 'Cache', + Database = 'Database', + Email = 'Email', + Frontend = 'Frontend', + LLM = 'LLM', + Logging = 'Logging', + QueueConfig = 'QueueConfig', + Security = 'Security', + ServerConfig = 'ServerConfig', + Serverless = 'Serverless', + Storage = 'Storage', + Support = 'Support', + Workspace = 'Workspace' +} + +export type EnvironmentVariablesGroupData = { + __typename?: 'EnvironmentVariablesGroupData'; + groupName: EnvironmentVariablesGroup; + subgroups: Array; + variables: Array; +}; + +export type EnvironmentVariablesOutput = { + __typename?: 'EnvironmentVariablesOutput'; + groups: Array; +}; + +export enum EnvironmentVariablesSubGroup { + CloudflareConfig = 'CloudflareConfig', + EmailSettings = 'EmailSettings', + FrontSupportConfig = 'FrontSupportConfig', + GoogleAuth = 'GoogleAuth', + LambdaConfig = 'LambdaConfig', + MicrosoftAuth = 'MicrosoftAuth', + PasswordAuth = 'PasswordAuth', + RateLimiting = 'RateLimiting', + S3Config = 'S3Config', + SSL = 'SSL', + SentryConfig = 'SentryConfig', + SmtpConfig = 'SmtpConfig', + StripeConfig = 'StripeConfig', + TinybirdConfig = 'TinybirdConfig', + Tokens = 'Tokens' +} + +export type EnvironmentVariablesSubgroupData = { + __typename?: 'EnvironmentVariablesSubgroupData'; + subgroupName: EnvironmentVariablesSubGroup; + variables: Array; +}; + export type ExecuteServerlessFunctionInput = { /** Id of the serverless function to execute */ id: Scalars['UUID']['input']; @@ -819,7 +886,7 @@ export type Mutation = { track: Analytics; unsyncRemoteTable: RemoteTable; updateBillingSubscription: BillingUpdateOutput; - updateLabPublicFeatureFlag: Scalars['Boolean']['output']; + updateLabPublicFeatureFlag: FeatureFlag; updateOneField: Field; updateOneObject: Object; updateOneRemoteServer: RemoteServer; @@ -1314,10 +1381,12 @@ export type Query = { findWorkspaceFromInviteHash: Workspace; findWorkspaceInvitations: Array; getAvailablePackages: Scalars['JSON']['output']; + getEnvironmentVariablesGrouped: EnvironmentVariablesOutput; getHostnameDetails?: Maybe; getPostgresCredentials?: Maybe; getProductPrices: BillingProductPricesOutput; getPublicWorkspaceDataBySubdomain: PublicWorkspaceDataOutput; + getRoles: Array; getServerlessFunctionSourceCode?: Maybe; getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal; getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal; @@ -1584,6 +1653,16 @@ export type ResendEmailVerificationTokenOutput = { success: Scalars['Boolean']['output']; }; +export type RoleDto = { + __typename?: 'RoleDTO'; + canUpdateAllSettings: Scalars['Boolean']['output']; + description?: Maybe; + id: Scalars['String']['output']; + isEditable: Scalars['Boolean']['output']; + label: Scalars['String']['output']; + workspaceMembers: Array; +}; + export type RunWorkflowVersionInput = { /** Execution result in JSON format */ payload?: InputMaybe; @@ -1822,7 +1901,6 @@ export type UpdateFieldInput = { description?: InputMaybe; icon?: InputMaybe; isActive?: InputMaybe; - isCustom?: InputMaybe; isLabelSyncedWithName?: InputMaybe; isNullable?: InputMaybe; isSystem?: InputMaybe; diff --git a/packages/twenty-front/src/generated/graphql.tsx b/packages/twenty-front/src/generated/graphql.tsx index 9416282d1..7c78f0be3 100644 --- a/packages/twenty-front/src/generated/graphql.tsx +++ b/packages/twenty-front/src/generated/graphql.tsx @@ -251,6 +251,10 @@ export type ClientConfig = { defaultSubdomain?: Maybe; frontDomain: Scalars['String']; isEmailVerificationRequired: Scalars['Boolean']; + isGoogleCalendarEnabled: Scalars['Boolean']; + isGoogleMessagingEnabled: Scalars['Boolean']; + isMicrosoftCalendarEnabled: Scalars['Boolean']; + isMicrosoftMessagingEnabled: Scalars['Boolean']; isMultiWorkspaceEnabled: Scalars['Boolean']; publicFeatureFlags: Array; sentry: Sentry; @@ -1246,6 +1250,7 @@ export type Query = { getPostgresCredentials?: Maybe; getProductPrices: BillingProductPricesOutput; getPublicWorkspaceDataBySubdomain: PublicWorkspaceDataOutput; + getRoles: Array; getServerlessFunctionSourceCode?: Maybe; getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal; getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal; @@ -1444,6 +1449,16 @@ export type ResendEmailVerificationTokenOutput = { success: Scalars['Boolean']; }; +export type RoleDto = { + __typename?: 'RoleDTO'; + canUpdateAllSettings: Scalars['Boolean']; + description?: Maybe; + id: Scalars['String']; + isEditable: Scalars['Boolean']; + label: Scalars['String']; + workspaceMembers: Array; +}; + export type RunWorkflowVersionInput = { /** Execution result in JSON format */ payload?: InputMaybe; @@ -2192,7 +2207,7 @@ export type UpdateBillingSubscriptionMutation = { __typename?: 'Mutation', updat export type GetClientConfigQueryVariables = Exact<{ [key: string]: never; }>; -export type GetClientConfigQuery = { __typename?: 'Query', clientConfig: { __typename?: 'ClientConfig', signInPrefilled: boolean, isMultiWorkspaceEnabled: boolean, isEmailVerificationRequired: boolean, defaultSubdomain?: string | null, frontDomain: string, debugMode: boolean, analyticsEnabled: boolean, chromeExtensionId?: string | null, canManageFeatureFlags: boolean, billing: { __typename?: 'Billing', isBillingEnabled: boolean, billingUrl?: string | null, trialPeriods: Array<{ __typename?: 'BillingTrialPeriodDTO', duration: number, isCreditCardRequired: boolean }> }, authProviders: { __typename?: 'AuthProviders', google: boolean, password: boolean, microsoft: boolean, sso: Array<{ __typename?: 'SSOIdentityProvider', id: string, name: string, type: IdentityProviderType, status: SsoIdentityProviderStatus, issuer: string }> }, support: { __typename?: 'Support', supportDriver: string, supportFrontChatId?: string | null }, sentry: { __typename?: 'Sentry', dsn?: string | null, environment?: string | null, release?: string | null }, captcha: { __typename?: 'Captcha', provider?: CaptchaDriverType | null, siteKey?: string | null }, api: { __typename?: 'ApiConfig', mutationMaximumAffectedRecords: number }, publicFeatureFlags: Array<{ __typename?: 'PublicFeatureFlag', key: FeatureFlagKey, metadata: { __typename?: 'PublicFeatureFlagMetadata', label: string, description: string, imagePath: string } }> } }; +export type GetClientConfigQuery = { __typename?: 'Query', clientConfig: { __typename?: 'ClientConfig', signInPrefilled: boolean, isMultiWorkspaceEnabled: boolean, isEmailVerificationRequired: boolean, defaultSubdomain?: string | null, frontDomain: string, debugMode: boolean, analyticsEnabled: boolean, chromeExtensionId?: string | null, canManageFeatureFlags: boolean, isMicrosoftMessagingEnabled: boolean, isMicrosoftCalendarEnabled: boolean, isGoogleMessagingEnabled: boolean, isGoogleCalendarEnabled: boolean, billing: { __typename?: 'Billing', isBillingEnabled: boolean, billingUrl?: string | null, trialPeriods: Array<{ __typename?: 'BillingTrialPeriodDTO', duration: number, isCreditCardRequired: boolean }> }, authProviders: { __typename?: 'AuthProviders', google: boolean, password: boolean, microsoft: boolean, sso: Array<{ __typename?: 'SSOIdentityProvider', id: string, name: string, type: IdentityProviderType, status: SsoIdentityProviderStatus, issuer: string }> }, support: { __typename?: 'Support', supportDriver: string, supportFrontChatId?: string | null }, sentry: { __typename?: 'Sentry', dsn?: string | null, environment?: string | null, release?: string | null }, captcha: { __typename?: 'Captcha', provider?: CaptchaDriverType | null, siteKey?: string | null }, api: { __typename?: 'ApiConfig', mutationMaximumAffectedRecords: number }, publicFeatureFlags: Array<{ __typename?: 'PublicFeatureFlag', key: FeatureFlagKey, metadata: { __typename?: 'PublicFeatureFlagMetadata', label: string, description: string, imagePath: string } }> } }; export type SkipSyncEmailOnboardingStepMutationVariables = Exact<{ [key: string]: never; }>; @@ -3677,6 +3692,10 @@ export const GetClientConfigDocument = gql` imagePath } } + isMicrosoftMessagingEnabled + isMicrosoftCalendarEnabled + isGoogleMessagingEnabled + isGoogleCalendarEnabled } } `; diff --git a/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx b/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx index 67f48d8c8..99d0c9a86 100644 --- a/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx +++ b/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx @@ -9,6 +9,10 @@ import { isAnalyticsEnabledState } from '@/client-config/states/isAnalyticsEnabl import { isDebugModeState } from '@/client-config/states/isDebugModeState'; import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState'; import { isEmailVerificationRequiredState } from '@/client-config/states/isEmailVerificationRequiredState'; +import { isGoogleCalendarEnabledState } from '@/client-config/states/isGoogleCalendarEnabledState'; +import { isGoogleMessagingEnabledState } from '@/client-config/states/isGoogleMessagingEnabledState'; +import { isMicrosoftCalendarEnabledState } from '@/client-config/states/isMicrosoftCalendarEnabledState'; +import { isMicrosoftMessagingEnabledState } from '@/client-config/states/isMicrosoftMessagingEnabledState'; import { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWorkspaceEnabledState'; import { labPublicFeatureFlagsState } from '@/client-config/states/labPublicFeatureFlagsState'; import { sentryConfigState } from '@/client-config/states/sentryConfigState'; @@ -57,6 +61,22 @@ export const ClientConfigProviderEffect = () => { labPublicFeatureFlagsState, ); + const setMicrosoftMessagingEnabled = useSetRecoilState( + isMicrosoftMessagingEnabledState, + ); + + const setMicrosoftCalendarEnabled = useSetRecoilState( + isMicrosoftCalendarEnabledState, + ); + + const setGoogleMessagingEnabled = useSetRecoilState( + isGoogleMessagingEnabledState, + ); + + const setGoogleCalendarEnabled = useSetRecoilState( + isGoogleCalendarEnabledState, + ); + const { data, loading, error } = useGetClientConfigQuery({ skip: clientConfigApiStatus.isLoaded, }); @@ -123,6 +143,12 @@ export const ClientConfigProviderEffect = () => { }); setCanManageFeatureFlags(data?.clientConfig?.canManageFeatureFlags); setLabPublicFeatureFlags(data?.clientConfig?.publicFeatureFlags); + setMicrosoftMessagingEnabled( + data?.clientConfig?.isMicrosoftMessagingEnabled, + ); + setMicrosoftCalendarEnabled(data?.clientConfig?.isMicrosoftCalendarEnabled); + setGoogleMessagingEnabled(data?.clientConfig?.isGoogleMessagingEnabled); + setGoogleCalendarEnabled(data?.clientConfig?.isGoogleCalendarEnabled); }, [ data, setIsDebugMode, @@ -143,6 +169,10 @@ export const ClientConfigProviderEffect = () => { setAuthProviders, setCanManageFeatureFlags, setLabPublicFeatureFlags, + setMicrosoftMessagingEnabled, + setMicrosoftCalendarEnabled, + setGoogleMessagingEnabled, + setGoogleCalendarEnabled, ]); return <>; diff --git a/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts b/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts index 560c237b5..67ed1ef60 100644 --- a/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts +++ b/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts @@ -56,6 +56,10 @@ export const GET_CLIENT_CONFIG = gql` imagePath } } + isMicrosoftMessagingEnabled + isMicrosoftCalendarEnabled + isGoogleMessagingEnabled + isGoogleCalendarEnabled } } `; diff --git a/packages/twenty-front/src/modules/client-config/states/isGoogleCalendarEnabledState.ts b/packages/twenty-front/src/modules/client-config/states/isGoogleCalendarEnabledState.ts new file mode 100644 index 000000000..12074285f --- /dev/null +++ b/packages/twenty-front/src/modules/client-config/states/isGoogleCalendarEnabledState.ts @@ -0,0 +1,6 @@ +import { createState } from '@ui/utilities/state/utils/createState'; + +export const isGoogleCalendarEnabledState = createState({ + key: 'isGoogleCalendarEnabled', + defaultValue: false, +}); diff --git a/packages/twenty-front/src/modules/client-config/states/isGoogleMessagingEnabledState.ts b/packages/twenty-front/src/modules/client-config/states/isGoogleMessagingEnabledState.ts new file mode 100644 index 000000000..1142b6eb6 --- /dev/null +++ b/packages/twenty-front/src/modules/client-config/states/isGoogleMessagingEnabledState.ts @@ -0,0 +1,6 @@ +import { createState } from '@ui/utilities/state/utils/createState'; + +export const isGoogleMessagingEnabledState = createState({ + key: 'isGoogleMessagingEnabled', + defaultValue: false, +}); diff --git a/packages/twenty-front/src/modules/client-config/states/isMicrosoftCalendarEnabledState.ts b/packages/twenty-front/src/modules/client-config/states/isMicrosoftCalendarEnabledState.ts new file mode 100644 index 000000000..6942fb88a --- /dev/null +++ b/packages/twenty-front/src/modules/client-config/states/isMicrosoftCalendarEnabledState.ts @@ -0,0 +1,6 @@ +import { createState } from '@ui/utilities/state/utils/createState'; + +export const isMicrosoftCalendarEnabledState = createState({ + key: 'isMicrosoftCalendarEnabled', + defaultValue: false, +}); diff --git a/packages/twenty-front/src/modules/client-config/states/isMicrosoftMessagingEnabledState.ts b/packages/twenty-front/src/modules/client-config/states/isMicrosoftMessagingEnabledState.ts new file mode 100644 index 000000000..c4493a9a3 --- /dev/null +++ b/packages/twenty-front/src/modules/client-config/states/isMicrosoftMessagingEnabledState.ts @@ -0,0 +1,6 @@ +import { createState } from '@ui/utilities/state/utils/createState'; + +export const isMicrosoftMessagingEnabledState = createState({ + key: 'isMicrosoftMessagingEnabled', + defaultValue: false, +}); diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsListEmptyStateCard.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsListEmptyStateCard.tsx index 1a04f8459..7364dbe0e 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsListEmptyStateCard.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsListEmptyStateCard.tsx @@ -1,6 +1,11 @@ +import { isGoogleCalendarEnabledState } from '@/client-config/states/isGoogleCalendarEnabledState'; +import { isGoogleMessagingEnabledState } from '@/client-config/states/isGoogleMessagingEnabledState'; +import { isMicrosoftCalendarEnabledState } from '@/client-config/states/isMicrosoftCalendarEnabledState'; +import { isMicrosoftMessagingEnabledState } from '@/client-config/states/isMicrosoftMessagingEnabledState'; import { useTriggerApisOAuth } from '@/settings/accounts/hooks/useTriggerApiOAuth'; import styled from '@emotion/styled'; import { useLingui } from '@lingui/react/macro'; +import { useRecoilValue } from 'recoil'; import { Button, Card, @@ -33,23 +38,40 @@ export const SettingsAccountsListEmptyStateCard = ({ const { t } = useLingui(); + const isGoogleMessagingEnabled = useRecoilValue( + isGoogleMessagingEnabledState, + ); + const isMicrosoftMessagingEnabled = useRecoilValue( + isMicrosoftMessagingEnabledState, + ); + + const isGoogleCalendarEnabled = useRecoilValue(isGoogleCalendarEnabledState); + + const isMicrosoftCalendarEnabled = useRecoilValue( + isMicrosoftCalendarEnabledState, + ); + return ( {label || t`No connected account`} -