Fix-issue-370 (#9996)
Fixes the issue from introduced when alowing gmail and outlook. fixes https://github.com/twentyhq/core-team-issues/issues/370
This commit is contained in:
@ -258,6 +258,10 @@ export type ClientConfig = {
|
|||||||
defaultSubdomain?: Maybe<Scalars['String']['output']>;
|
defaultSubdomain?: Maybe<Scalars['String']['output']>;
|
||||||
frontDomain: Scalars['String']['output'];
|
frontDomain: Scalars['String']['output'];
|
||||||
isEmailVerificationRequired: Scalars['Boolean']['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'];
|
isMultiWorkspaceEnabled: Scalars['Boolean']['output'];
|
||||||
publicFeatureFlags: Array<PublicFeatureFlag>;
|
publicFeatureFlags: Array<PublicFeatureFlag>;
|
||||||
sentry: Sentry;
|
sentry: Sentry;
|
||||||
@ -462,6 +466,69 @@ export type EmailPasswordResetLink = {
|
|||||||
success: Scalars['Boolean']['output'];
|
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<EnvironmentVariablesSubgroupData>;
|
||||||
|
variables: Array<EnvironmentVariable>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EnvironmentVariablesOutput = {
|
||||||
|
__typename?: 'EnvironmentVariablesOutput';
|
||||||
|
groups: Array<EnvironmentVariablesGroupData>;
|
||||||
|
};
|
||||||
|
|
||||||
|
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<EnvironmentVariable>;
|
||||||
|
};
|
||||||
|
|
||||||
export type ExecuteServerlessFunctionInput = {
|
export type ExecuteServerlessFunctionInput = {
|
||||||
/** Id of the serverless function to execute */
|
/** Id of the serverless function to execute */
|
||||||
id: Scalars['UUID']['input'];
|
id: Scalars['UUID']['input'];
|
||||||
@ -819,7 +886,7 @@ export type Mutation = {
|
|||||||
track: Analytics;
|
track: Analytics;
|
||||||
unsyncRemoteTable: RemoteTable;
|
unsyncRemoteTable: RemoteTable;
|
||||||
updateBillingSubscription: BillingUpdateOutput;
|
updateBillingSubscription: BillingUpdateOutput;
|
||||||
updateLabPublicFeatureFlag: Scalars['Boolean']['output'];
|
updateLabPublicFeatureFlag: FeatureFlag;
|
||||||
updateOneField: Field;
|
updateOneField: Field;
|
||||||
updateOneObject: Object;
|
updateOneObject: Object;
|
||||||
updateOneRemoteServer: RemoteServer;
|
updateOneRemoteServer: RemoteServer;
|
||||||
@ -1314,10 +1381,12 @@ export type Query = {
|
|||||||
findWorkspaceFromInviteHash: Workspace;
|
findWorkspaceFromInviteHash: Workspace;
|
||||||
findWorkspaceInvitations: Array<WorkspaceInvitation>;
|
findWorkspaceInvitations: Array<WorkspaceInvitation>;
|
||||||
getAvailablePackages: Scalars['JSON']['output'];
|
getAvailablePackages: Scalars['JSON']['output'];
|
||||||
|
getEnvironmentVariablesGrouped: EnvironmentVariablesOutput;
|
||||||
getHostnameDetails?: Maybe<CustomHostnameDetails>;
|
getHostnameDetails?: Maybe<CustomHostnameDetails>;
|
||||||
getPostgresCredentials?: Maybe<PostgresCredentials>;
|
getPostgresCredentials?: Maybe<PostgresCredentials>;
|
||||||
getProductPrices: BillingProductPricesOutput;
|
getProductPrices: BillingProductPricesOutput;
|
||||||
getPublicWorkspaceDataBySubdomain: PublicWorkspaceDataOutput;
|
getPublicWorkspaceDataBySubdomain: PublicWorkspaceDataOutput;
|
||||||
|
getRoles: Array<RoleDto>;
|
||||||
getServerlessFunctionSourceCode?: Maybe<Scalars['JSON']['output']>;
|
getServerlessFunctionSourceCode?: Maybe<Scalars['JSON']['output']>;
|
||||||
getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal;
|
getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal;
|
||||||
getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal;
|
getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal;
|
||||||
@ -1584,6 +1653,16 @@ export type ResendEmailVerificationTokenOutput = {
|
|||||||
success: Scalars['Boolean']['output'];
|
success: Scalars['Boolean']['output'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type RoleDto = {
|
||||||
|
__typename?: 'RoleDTO';
|
||||||
|
canUpdateAllSettings: Scalars['Boolean']['output'];
|
||||||
|
description?: Maybe<Scalars['String']['output']>;
|
||||||
|
id: Scalars['String']['output'];
|
||||||
|
isEditable: Scalars['Boolean']['output'];
|
||||||
|
label: Scalars['String']['output'];
|
||||||
|
workspaceMembers: Array<WorkspaceMember>;
|
||||||
|
};
|
||||||
|
|
||||||
export type RunWorkflowVersionInput = {
|
export type RunWorkflowVersionInput = {
|
||||||
/** Execution result in JSON format */
|
/** Execution result in JSON format */
|
||||||
payload?: InputMaybe<Scalars['JSON']['input']>;
|
payload?: InputMaybe<Scalars['JSON']['input']>;
|
||||||
@ -1822,7 +1901,6 @@ export type UpdateFieldInput = {
|
|||||||
description?: InputMaybe<Scalars['String']['input']>;
|
description?: InputMaybe<Scalars['String']['input']>;
|
||||||
icon?: InputMaybe<Scalars['String']['input']>;
|
icon?: InputMaybe<Scalars['String']['input']>;
|
||||||
isActive?: InputMaybe<Scalars['Boolean']['input']>;
|
isActive?: InputMaybe<Scalars['Boolean']['input']>;
|
||||||
isCustom?: InputMaybe<Scalars['Boolean']['input']>;
|
|
||||||
isLabelSyncedWithName?: InputMaybe<Scalars['Boolean']['input']>;
|
isLabelSyncedWithName?: InputMaybe<Scalars['Boolean']['input']>;
|
||||||
isNullable?: InputMaybe<Scalars['Boolean']['input']>;
|
isNullable?: InputMaybe<Scalars['Boolean']['input']>;
|
||||||
isSystem?: InputMaybe<Scalars['Boolean']['input']>;
|
isSystem?: InputMaybe<Scalars['Boolean']['input']>;
|
||||||
|
|||||||
@ -251,6 +251,10 @@ export type ClientConfig = {
|
|||||||
defaultSubdomain?: Maybe<Scalars['String']>;
|
defaultSubdomain?: Maybe<Scalars['String']>;
|
||||||
frontDomain: Scalars['String'];
|
frontDomain: Scalars['String'];
|
||||||
isEmailVerificationRequired: Scalars['Boolean'];
|
isEmailVerificationRequired: Scalars['Boolean'];
|
||||||
|
isGoogleCalendarEnabled: Scalars['Boolean'];
|
||||||
|
isGoogleMessagingEnabled: Scalars['Boolean'];
|
||||||
|
isMicrosoftCalendarEnabled: Scalars['Boolean'];
|
||||||
|
isMicrosoftMessagingEnabled: Scalars['Boolean'];
|
||||||
isMultiWorkspaceEnabled: Scalars['Boolean'];
|
isMultiWorkspaceEnabled: Scalars['Boolean'];
|
||||||
publicFeatureFlags: Array<PublicFeatureFlag>;
|
publicFeatureFlags: Array<PublicFeatureFlag>;
|
||||||
sentry: Sentry;
|
sentry: Sentry;
|
||||||
@ -1246,6 +1250,7 @@ export type Query = {
|
|||||||
getPostgresCredentials?: Maybe<PostgresCredentials>;
|
getPostgresCredentials?: Maybe<PostgresCredentials>;
|
||||||
getProductPrices: BillingProductPricesOutput;
|
getProductPrices: BillingProductPricesOutput;
|
||||||
getPublicWorkspaceDataBySubdomain: PublicWorkspaceDataOutput;
|
getPublicWorkspaceDataBySubdomain: PublicWorkspaceDataOutput;
|
||||||
|
getRoles: Array<RoleDto>;
|
||||||
getServerlessFunctionSourceCode?: Maybe<Scalars['JSON']>;
|
getServerlessFunctionSourceCode?: Maybe<Scalars['JSON']>;
|
||||||
getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal;
|
getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal;
|
||||||
getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal;
|
getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal;
|
||||||
@ -1444,6 +1449,16 @@ export type ResendEmailVerificationTokenOutput = {
|
|||||||
success: Scalars['Boolean'];
|
success: Scalars['Boolean'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type RoleDto = {
|
||||||
|
__typename?: 'RoleDTO';
|
||||||
|
canUpdateAllSettings: Scalars['Boolean'];
|
||||||
|
description?: Maybe<Scalars['String']>;
|
||||||
|
id: Scalars['String'];
|
||||||
|
isEditable: Scalars['Boolean'];
|
||||||
|
label: Scalars['String'];
|
||||||
|
workspaceMembers: Array<WorkspaceMember>;
|
||||||
|
};
|
||||||
|
|
||||||
export type RunWorkflowVersionInput = {
|
export type RunWorkflowVersionInput = {
|
||||||
/** Execution result in JSON format */
|
/** Execution result in JSON format */
|
||||||
payload?: InputMaybe<Scalars['JSON']>;
|
payload?: InputMaybe<Scalars['JSON']>;
|
||||||
@ -2192,7 +2207,7 @@ export type UpdateBillingSubscriptionMutation = { __typename?: 'Mutation', updat
|
|||||||
export type GetClientConfigQueryVariables = Exact<{ [key: string]: never; }>;
|
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; }>;
|
export type SkipSyncEmailOnboardingStepMutationVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
@ -3677,6 +3692,10 @@ export const GetClientConfigDocument = gql`
|
|||||||
imagePath
|
imagePath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
isMicrosoftMessagingEnabled
|
||||||
|
isMicrosoftCalendarEnabled
|
||||||
|
isGoogleMessagingEnabled
|
||||||
|
isGoogleCalendarEnabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -9,6 +9,10 @@ import { isAnalyticsEnabledState } from '@/client-config/states/isAnalyticsEnabl
|
|||||||
import { isDebugModeState } from '@/client-config/states/isDebugModeState';
|
import { isDebugModeState } from '@/client-config/states/isDebugModeState';
|
||||||
import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState';
|
import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState';
|
||||||
import { isEmailVerificationRequiredState } from '@/client-config/states/isEmailVerificationRequiredState';
|
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 { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWorkspaceEnabledState';
|
||||||
import { labPublicFeatureFlagsState } from '@/client-config/states/labPublicFeatureFlagsState';
|
import { labPublicFeatureFlagsState } from '@/client-config/states/labPublicFeatureFlagsState';
|
||||||
import { sentryConfigState } from '@/client-config/states/sentryConfigState';
|
import { sentryConfigState } from '@/client-config/states/sentryConfigState';
|
||||||
@ -57,6 +61,22 @@ export const ClientConfigProviderEffect = () => {
|
|||||||
labPublicFeatureFlagsState,
|
labPublicFeatureFlagsState,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const setMicrosoftMessagingEnabled = useSetRecoilState(
|
||||||
|
isMicrosoftMessagingEnabledState,
|
||||||
|
);
|
||||||
|
|
||||||
|
const setMicrosoftCalendarEnabled = useSetRecoilState(
|
||||||
|
isMicrosoftCalendarEnabledState,
|
||||||
|
);
|
||||||
|
|
||||||
|
const setGoogleMessagingEnabled = useSetRecoilState(
|
||||||
|
isGoogleMessagingEnabledState,
|
||||||
|
);
|
||||||
|
|
||||||
|
const setGoogleCalendarEnabled = useSetRecoilState(
|
||||||
|
isGoogleCalendarEnabledState,
|
||||||
|
);
|
||||||
|
|
||||||
const { data, loading, error } = useGetClientConfigQuery({
|
const { data, loading, error } = useGetClientConfigQuery({
|
||||||
skip: clientConfigApiStatus.isLoaded,
|
skip: clientConfigApiStatus.isLoaded,
|
||||||
});
|
});
|
||||||
@ -123,6 +143,12 @@ export const ClientConfigProviderEffect = () => {
|
|||||||
});
|
});
|
||||||
setCanManageFeatureFlags(data?.clientConfig?.canManageFeatureFlags);
|
setCanManageFeatureFlags(data?.clientConfig?.canManageFeatureFlags);
|
||||||
setLabPublicFeatureFlags(data?.clientConfig?.publicFeatureFlags);
|
setLabPublicFeatureFlags(data?.clientConfig?.publicFeatureFlags);
|
||||||
|
setMicrosoftMessagingEnabled(
|
||||||
|
data?.clientConfig?.isMicrosoftMessagingEnabled,
|
||||||
|
);
|
||||||
|
setMicrosoftCalendarEnabled(data?.clientConfig?.isMicrosoftCalendarEnabled);
|
||||||
|
setGoogleMessagingEnabled(data?.clientConfig?.isGoogleMessagingEnabled);
|
||||||
|
setGoogleCalendarEnabled(data?.clientConfig?.isGoogleCalendarEnabled);
|
||||||
}, [
|
}, [
|
||||||
data,
|
data,
|
||||||
setIsDebugMode,
|
setIsDebugMode,
|
||||||
@ -143,6 +169,10 @@ export const ClientConfigProviderEffect = () => {
|
|||||||
setAuthProviders,
|
setAuthProviders,
|
||||||
setCanManageFeatureFlags,
|
setCanManageFeatureFlags,
|
||||||
setLabPublicFeatureFlags,
|
setLabPublicFeatureFlags,
|
||||||
|
setMicrosoftMessagingEnabled,
|
||||||
|
setMicrosoftCalendarEnabled,
|
||||||
|
setGoogleMessagingEnabled,
|
||||||
|
setGoogleCalendarEnabled,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
|
|||||||
@ -56,6 +56,10 @@ export const GET_CLIENT_CONFIG = gql`
|
|||||||
imagePath
|
imagePath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
isMicrosoftMessagingEnabled
|
||||||
|
isMicrosoftCalendarEnabled
|
||||||
|
isGoogleMessagingEnabled
|
||||||
|
isGoogleCalendarEnabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
import { createState } from '@ui/utilities/state/utils/createState';
|
||||||
|
|
||||||
|
export const isGoogleCalendarEnabledState = createState<boolean>({
|
||||||
|
key: 'isGoogleCalendarEnabled',
|
||||||
|
defaultValue: false,
|
||||||
|
});
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
import { createState } from '@ui/utilities/state/utils/createState';
|
||||||
|
|
||||||
|
export const isGoogleMessagingEnabledState = createState<boolean>({
|
||||||
|
key: 'isGoogleMessagingEnabled',
|
||||||
|
defaultValue: false,
|
||||||
|
});
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
import { createState } from '@ui/utilities/state/utils/createState';
|
||||||
|
|
||||||
|
export const isMicrosoftCalendarEnabledState = createState<boolean>({
|
||||||
|
key: 'isMicrosoftCalendarEnabled',
|
||||||
|
defaultValue: false,
|
||||||
|
});
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
import { createState } from '@ui/utilities/state/utils/createState';
|
||||||
|
|
||||||
|
export const isMicrosoftMessagingEnabledState = createState<boolean>({
|
||||||
|
key: 'isMicrosoftMessagingEnabled',
|
||||||
|
defaultValue: false,
|
||||||
|
});
|
||||||
@ -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 { useTriggerApisOAuth } from '@/settings/accounts/hooks/useTriggerApiOAuth';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useLingui } from '@lingui/react/macro';
|
import { useLingui } from '@lingui/react/macro';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
@ -33,23 +38,40 @@ export const SettingsAccountsListEmptyStateCard = ({
|
|||||||
|
|
||||||
const { t } = useLingui();
|
const { t } = useLingui();
|
||||||
|
|
||||||
|
const isGoogleMessagingEnabled = useRecoilValue(
|
||||||
|
isGoogleMessagingEnabledState,
|
||||||
|
);
|
||||||
|
const isMicrosoftMessagingEnabled = useRecoilValue(
|
||||||
|
isMicrosoftMessagingEnabledState,
|
||||||
|
);
|
||||||
|
|
||||||
|
const isGoogleCalendarEnabled = useRecoilValue(isGoogleCalendarEnabledState);
|
||||||
|
|
||||||
|
const isMicrosoftCalendarEnabled = useRecoilValue(
|
||||||
|
isMicrosoftCalendarEnabledState,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<StyledHeader>{label || t`No connected account`}</StyledHeader>
|
<StyledHeader>{label || t`No connected account`}</StyledHeader>
|
||||||
<StyledBody>
|
<StyledBody>
|
||||||
<Button
|
{(isGoogleMessagingEnabled || isGoogleCalendarEnabled) && (
|
||||||
Icon={IconGoogle}
|
<Button
|
||||||
title={t`Connect with Google`}
|
Icon={IconGoogle}
|
||||||
variant="secondary"
|
title={t`Connect with Google`}
|
||||||
onClick={() => triggerApisOAuth('google')}
|
variant="secondary"
|
||||||
/>
|
onClick={() => triggerApisOAuth('google')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<Button
|
{(isMicrosoftMessagingEnabled || isMicrosoftCalendarEnabled) && (
|
||||||
Icon={IconMicrosoft}
|
<Button
|
||||||
title={t`Connect with Microsoft`}
|
Icon={IconMicrosoft}
|
||||||
variant="secondary"
|
title={t`Connect with Microsoft`}
|
||||||
onClick={() => triggerApisOAuth('microsoft')}
|
variant="secondary"
|
||||||
/>
|
onClick={() => triggerApisOAuth('microsoft')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</StyledBody>
|
</StyledBody>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -53,4 +53,8 @@ export const mockedClientConfig: ClientConfig = {
|
|||||||
api: { mutationMaximumAffectedRecords: 100 },
|
api: { mutationMaximumAffectedRecords: 100 },
|
||||||
canManageFeatureFlags: true,
|
canManageFeatureFlags: true,
|
||||||
publicFeatureFlags: [],
|
publicFeatureFlags: [],
|
||||||
|
isMicrosoftMessagingEnabled: true,
|
||||||
|
isMicrosoftCalendarEnabled: true,
|
||||||
|
isGoogleMessagingEnabled: true,
|
||||||
|
isGoogleCalendarEnabled: true,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -21,6 +21,8 @@ FRONT_PORT=3001
|
|||||||
# FILE_TOKEN_EXPIRES_IN=1d
|
# FILE_TOKEN_EXPIRES_IN=1d
|
||||||
# MESSAGING_PROVIDER_GMAIL_ENABLED=false
|
# MESSAGING_PROVIDER_GMAIL_ENABLED=false
|
||||||
# CALENDAR_PROVIDER_GOOGLE_ENABLED=false
|
# CALENDAR_PROVIDER_GOOGLE_ENABLED=false
|
||||||
|
# MESSAGING_PROVIDER_MICROSOFT_ENABLED=false
|
||||||
|
# CALENDAR_PROVIDER_MICROSOFT_ENABLED=false
|
||||||
# IS_BILLING_ENABLED=false
|
# IS_BILLING_ENABLED=false
|
||||||
# BILLING_PLAN_REQUIRED_LINK=https://twenty.com/stripe-redirection
|
# BILLING_PLAN_REQUIRED_LINK=https://twenty.com/stripe-redirection
|
||||||
# AUTH_PASSWORD_ENABLED=false
|
# AUTH_PASSWORD_ENABLED=false
|
||||||
|
|||||||
@ -15,6 +15,12 @@ CACHE_STORAGE_TYPE=redis
|
|||||||
AUTH_GOOGLE_ENABLED=false
|
AUTH_GOOGLE_ENABLED=false
|
||||||
MESSAGING_PROVIDER_GMAIL_ENABLED=false
|
MESSAGING_PROVIDER_GMAIL_ENABLED=false
|
||||||
CALENDAR_PROVIDER_GOOGLE_ENABLED=false
|
CALENDAR_PROVIDER_GOOGLE_ENABLED=false
|
||||||
|
MESSAGING_PROVIDER_MICROSOFT_ENABLED=false
|
||||||
|
CALENDAR_PROVIDER_MICROSOFT_ENABLED=false
|
||||||
|
|
||||||
AUTH_GOOGLE_CALLBACK_URL=http://localhost:3000/auth/google/redirect
|
AUTH_GOOGLE_CALLBACK_URL=http://localhost:3000/auth/google/redirect
|
||||||
AUTH_GOOGLE_APIS_CALLBACK_URL=http://localhost:3000/auth/google-apis/get-access-token
|
AUTH_GOOGLE_APIS_CALLBACK_URL=http://localhost:3000/auth/google-apis/get-access-token
|
||||||
MESSAGING_PROVIDER_GMAIL_CALLBACK_URL=http://localhost:3000/auth/google-gmail/get-access-token
|
MESSAGING_PROVIDER_GMAIL_CALLBACK_URL=http://localhost:3000/auth/google-gmail/get-access-token
|
||||||
|
|
||||||
|
AUTH_MICROSOFT_CALLBACK_URL=http://localhost:3000/auth/microsoft/redirect
|
||||||
|
AUTH_MICROSOFT_APIS_CALLBACK_URL=http://localhost:3000/auth/microsoft-apis/get-access-token
|
||||||
|
|||||||
@ -26,6 +26,16 @@ export class MicrosoftAPIsOauthExchangeCodeForTokenGuard extends AuthGuard(
|
|||||||
const request = context.switchToHttp().getRequest();
|
const request = context.switchToHttp().getRequest();
|
||||||
const state = JSON.parse(request.query.state);
|
const state = JSON.parse(request.query.state);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!this.environmentService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED') &&
|
||||||
|
!this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED')
|
||||||
|
) {
|
||||||
|
throw new AuthException(
|
||||||
|
'Microsoft apis auth is not enabled',
|
||||||
|
AuthExceptionCode.MICROSOFT_API_AUTH_DISABLED,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
new MicrosoftAPIsOauthExchangeCodeForTokenStrategy(
|
new MicrosoftAPIsOauthExchangeCodeForTokenStrategy(
|
||||||
this.environmentService,
|
this.environmentService,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,6 +4,10 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
|
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
|
import {
|
||||||
|
AuthException,
|
||||||
|
AuthExceptionCode,
|
||||||
|
} from 'src/engine/core-modules/auth/auth.exception';
|
||||||
import { MicrosoftAPIsOauthRequestCodeStrategy } from 'src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy';
|
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 { 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 { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util';
|
||||||
@ -33,6 +37,16 @@ export class MicrosoftAPIsOauthRequestCodeGuard extends AuthGuard(
|
|||||||
let workspace: Workspace | null = null;
|
let workspace: Workspace | null = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (
|
||||||
|
!this.environmentService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED') &&
|
||||||
|
!this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED')
|
||||||
|
) {
|
||||||
|
throw new AuthException(
|
||||||
|
'Microsoft apis auth is not enabled',
|
||||||
|
AuthExceptionCode.MICROSOFT_API_AUTH_DISABLED,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const request = context.switchToHttp().getRequest();
|
const request = context.switchToHttp().getRequest();
|
||||||
|
|
||||||
const { workspaceId } =
|
const { workspaceId } =
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { v4 } from 'uuid';
|
|||||||
|
|
||||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
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 { 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 { 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 { 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 { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||||
@ -48,6 +49,7 @@ export class MicrosoftAPIsService {
|
|||||||
private readonly workspaceEventEmitter: WorkspaceEventEmitter,
|
private readonly workspaceEventEmitter: WorkspaceEventEmitter,
|
||||||
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
||||||
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
||||||
|
private readonly environmentService: EnvironmentService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async refreshMicrosoftRefreshToken(input: {
|
async refreshMicrosoftRefreshToken(input: {
|
||||||
@ -167,37 +169,42 @@ export class MicrosoftAPIsService {
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const newCalendarChannel = await calendarChannelRepository.save(
|
if (
|
||||||
{
|
this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED')
|
||||||
id: v4(),
|
) {
|
||||||
connectedAccountId: newOrExistingConnectedAccountId,
|
const newCalendarChannel = await calendarChannelRepository.save(
|
||||||
handle,
|
|
||||||
visibility:
|
|
||||||
calendarVisibility || CalendarChannelVisibility.SHARE_EVERYTHING,
|
|
||||||
},
|
|
||||||
{},
|
|
||||||
manager,
|
|
||||||
);
|
|
||||||
|
|
||||||
const calendarChannelMetadata =
|
|
||||||
await this.objectMetadataRepository.findOneOrFail({
|
|
||||||
where: { nameSingular: 'calendarChannel', workspaceId },
|
|
||||||
});
|
|
||||||
|
|
||||||
this.workspaceEventEmitter.emitDatabaseBatchEvent({
|
|
||||||
objectMetadataNameSingular: 'calendarChannel',
|
|
||||||
action: DatabaseEventAction.CREATED,
|
|
||||||
events: [
|
|
||||||
{
|
{
|
||||||
recordId: newCalendarChannel.id,
|
id: v4(),
|
||||||
objectMetadata: calendarChannelMetadata,
|
connectedAccountId: newOrExistingConnectedAccountId,
|
||||||
properties: {
|
handle,
|
||||||
after: newCalendarChannel,
|
visibility:
|
||||||
},
|
calendarVisibility ||
|
||||||
|
CalendarChannelVisibility.SHARE_EVERYTHING,
|
||||||
},
|
},
|
||||||
],
|
{},
|
||||||
workspaceId,
|
manager,
|
||||||
});
|
);
|
||||||
|
|
||||||
|
const calendarChannelMetadata =
|
||||||
|
await this.objectMetadataRepository.findOneOrFail({
|
||||||
|
where: { nameSingular: 'calendarChannel', workspaceId },
|
||||||
|
});
|
||||||
|
|
||||||
|
this.workspaceEventEmitter.emitDatabaseBatchEvent({
|
||||||
|
objectMetadataNameSingular: 'calendarChannel',
|
||||||
|
action: DatabaseEventAction.CREATED,
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
recordId: newCalendarChannel.id,
|
||||||
|
objectMetadata: calendarChannelMetadata,
|
||||||
|
properties: {
|
||||||
|
after: newCalendarChannel,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
workspaceId,
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const updatedConnectedAccount = await connectedAccountRepository.update(
|
const updatedConnectedAccount = await connectedAccountRepository.update(
|
||||||
{
|
{
|
||||||
@ -291,36 +298,40 @@ export class MicrosoftAPIsService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const messageChannels = await messageChannelRepository.find({
|
if (this.environmentService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED')) {
|
||||||
where: {
|
const messageChannels = await messageChannelRepository.find({
|
||||||
connectedAccountId: newOrExistingConnectedAccountId,
|
where: {
|
||||||
},
|
connectedAccountId: newOrExistingConnectedAccountId,
|
||||||
});
|
|
||||||
|
|
||||||
for (const messageChannel of messageChannels) {
|
|
||||||
await this.messageQueueService.add<MessagingMessageListFetchJobData>(
|
|
||||||
MessagingMessageListFetchJob.name,
|
|
||||||
{
|
|
||||||
workspaceId,
|
|
||||||
messageChannelId: messageChannel.id,
|
|
||||||
},
|
},
|
||||||
);
|
});
|
||||||
|
|
||||||
|
for (const messageChannel of messageChannels) {
|
||||||
|
await this.messageQueueService.add<MessagingMessageListFetchJobData>(
|
||||||
|
MessagingMessageListFetchJob.name,
|
||||||
|
{
|
||||||
|
workspaceId,
|
||||||
|
messageChannelId: messageChannel.id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const calendarChannels = await calendarChannelRepository.find({
|
if (this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED')) {
|
||||||
where: {
|
const calendarChannels = await calendarChannelRepository.find({
|
||||||
connectedAccountId: newOrExistingConnectedAccountId,
|
where: {
|
||||||
},
|
connectedAccountId: newOrExistingConnectedAccountId,
|
||||||
});
|
|
||||||
|
|
||||||
for (const calendarChannel of calendarChannels) {
|
|
||||||
await this.calendarQueueService.add<CalendarEventListFetchJobData>(
|
|
||||||
CalendarEventListFetchJob.name,
|
|
||||||
{
|
|
||||||
calendarChannelId: calendarChannel.id,
|
|
||||||
workspaceId,
|
|
||||||
},
|
},
|
||||||
);
|
});
|
||||||
|
|
||||||
|
for (const calendarChannel of calendarChannels) {
|
||||||
|
await this.calendarQueueService.add<CalendarEventListFetchJobData>(
|
||||||
|
CalendarEventListFetchJob.name,
|
||||||
|
{
|
||||||
|
calendarChannelId: calendarChannel.id,
|
||||||
|
workspaceId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -127,4 +127,16 @@ export class ClientConfig {
|
|||||||
|
|
||||||
@Field(() => [PublicFeatureFlag])
|
@Field(() => [PublicFeatureFlag])
|
||||||
publicFeatureFlags: PublicFeatureFlag[];
|
publicFeatureFlags: PublicFeatureFlag[];
|
||||||
|
|
||||||
|
@Field(() => Boolean)
|
||||||
|
isMicrosoftMessagingEnabled: boolean;
|
||||||
|
|
||||||
|
@Field(() => Boolean)
|
||||||
|
isMicrosoftCalendarEnabled: boolean;
|
||||||
|
|
||||||
|
@Field(() => Boolean)
|
||||||
|
isGoogleMessagingEnabled: boolean;
|
||||||
|
|
||||||
|
@Field(() => Boolean)
|
||||||
|
isGoogleCalendarEnabled: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,6 +77,18 @@ export class ClientConfigResolver {
|
|||||||
this.environmentService.get('DEBUG_MODE') ||
|
this.environmentService.get('DEBUG_MODE') ||
|
||||||
this.environmentService.get('IS_BILLING_ENABLED'),
|
this.environmentService.get('IS_BILLING_ENABLED'),
|
||||||
publicFeatureFlags: PUBLIC_FEATURE_FLAGS,
|
publicFeatureFlags: PUBLIC_FEATURE_FLAGS,
|
||||||
|
isMicrosoftMessagingEnabled: this.environmentService.get(
|
||||||
|
'MESSAGING_PROVIDER_MICROSOFT_ENABLED',
|
||||||
|
),
|
||||||
|
isMicrosoftCalendarEnabled: this.environmentService.get(
|
||||||
|
'CALENDAR_PROVIDER_MICROSOFT_ENABLED',
|
||||||
|
),
|
||||||
|
isGoogleMessagingEnabled: this.environmentService.get(
|
||||||
|
'MESSAGING_PROVIDER_GMAIL_ENABLED',
|
||||||
|
),
|
||||||
|
isGoogleCalendarEnabled: this.environmentService.get(
|
||||||
|
'CALENDAR_PROVIDER_GOOGLE_ENABLED',
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
return Promise.resolve(clientConfig);
|
return Promise.resolve(clientConfig);
|
||||||
|
|||||||
@ -199,6 +199,22 @@ export class EnvironmentVariables {
|
|||||||
@ValidateIf((env) => env.AUTH_MICROSOFT_ENABLED)
|
@ValidateIf((env) => env.AUTH_MICROSOFT_ENABLED)
|
||||||
AUTH_MICROSOFT_APIS_CALLBACK_URL: string;
|
AUTH_MICROSOFT_APIS_CALLBACK_URL: string;
|
||||||
|
|
||||||
|
@EnvironmentVariablesMetadata({
|
||||||
|
group: EnvironmentVariablesGroup.Authentication,
|
||||||
|
subGroup: EnvironmentVariablesSubGroup.MicrosoftAuth,
|
||||||
|
description: 'Is Microsoft messaging provider enabled',
|
||||||
|
})
|
||||||
|
@CastToBoolean()
|
||||||
|
MESSAGING_PROVIDER_MICROSOFT_ENABLED = false;
|
||||||
|
|
||||||
|
@EnvironmentVariablesMetadata({
|
||||||
|
group: EnvironmentVariablesGroup.Authentication,
|
||||||
|
subGroup: EnvironmentVariablesSubGroup.MicrosoftAuth,
|
||||||
|
description: 'Is Microsoft Calendar provider enabled',
|
||||||
|
})
|
||||||
|
@CastToBoolean()
|
||||||
|
CALENDAR_PROVIDER_MICROSOFT_ENABLED = false;
|
||||||
|
|
||||||
@EnvironmentVariablesMetadata({
|
@EnvironmentVariablesMetadata({
|
||||||
group: EnvironmentVariablesGroup.Authentication,
|
group: EnvironmentVariablesGroup.Authentication,
|
||||||
subGroup: EnvironmentVariablesSubGroup.Tokens,
|
subGroup: EnvironmentVariablesSubGroup.Tokens,
|
||||||
|
|||||||
@ -20,6 +20,8 @@ Then you can set the following environment variables:
|
|||||||
|
|
||||||
- `MESSAGING_PROVIDER_GMAIL_ENABLED=true`
|
- `MESSAGING_PROVIDER_GMAIL_ENABLED=true`
|
||||||
- `CALENDAR_PROVIDER_GOOGLE_ENABLED=true`
|
- `CALENDAR_PROVIDER_GOOGLE_ENABLED=true`
|
||||||
|
- `MESSAGING_PROVIDER_MICROSOFT_ENABLED=false`
|
||||||
|
- `CALENDAR_PROVIDER_MICROSOFT_ENABLED=false`
|
||||||
- `AUTH_GOOGLE_CLIENT_ID=<client-id>`
|
- `AUTH_GOOGLE_CLIENT_ID=<client-id>`
|
||||||
- `AUTH_GOOGLE_CLIENT_SECRET=<client-secret>`
|
- `AUTH_GOOGLE_CLIENT_SECRET=<client-secret>`
|
||||||
- `AUTH_GOOGLE_CALLBACK_URL=https://<your-domain>/auth/google/redirect` if you want to use Google SSO
|
- `AUTH_GOOGLE_CALLBACK_URL=https://<your-domain>/auth/google/redirect` if you want to use Google SSO
|
||||||
@ -77,6 +79,8 @@ You will need to create a project in [Microsoft Azure](https://portal.azure.com/
|
|||||||
|
|
||||||
Then you can set the following environment variables:
|
Then you can set the following environment variables:
|
||||||
|
|
||||||
|
- `MESSAGING_PROVIDER_MICROSOFT_ENABLED=true`
|
||||||
|
- `CALENDAR_PROVIDER_MICROSOFT_ENABLED=true`
|
||||||
- `AUTH_MICROSOFT_ENABLED=true`
|
- `AUTH_MICROSOFT_ENABLED=true`
|
||||||
- `AUTH_MICROSOFT_CLIENT_ID=<client-id>`
|
- `AUTH_MICROSOFT_CLIENT_ID=<client-id>`
|
||||||
- `AUTH_MICROSOFT_CLIENT_SECRET=<client-secret>`
|
- `AUTH_MICROSOFT_CLIENT_SECRET=<client-secret>`
|
||||||
|
|||||||
Reference in New Issue
Block a user