refactor(sso): standardize SSO identity provider query names (#10335)
Updated method, query, and variable names to align with a consistent naming convention for fetching SSO identity providers. Added comprehensive unit tests to validate SSO service logic, ensuring better reliability and maintainability. --------- Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
@ -1,6 +1,5 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
|
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
|
||||||
import { PermissionsOnAllObjectRecords } from 'twenty-shared';
|
|
||||||
export type Maybe<T> = T | null;
|
export type Maybe<T> = T | null;
|
||||||
export type InputMaybe<T> = Maybe<T>;
|
export type InputMaybe<T> = Maybe<T>;
|
||||||
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||||
@ -33,6 +32,33 @@ export type ActivateWorkspaceInput = {
|
|||||||
displayName?: InputMaybe<Scalars['String']['input']>;
|
displayName?: InputMaybe<Scalars['String']['input']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AdminPanelHealthServiceData = {
|
||||||
|
__typename?: 'AdminPanelHealthServiceData';
|
||||||
|
details?: Maybe<Scalars['String']['output']>;
|
||||||
|
queues?: Maybe<Array<AdminPanelWorkerQueueHealth>>;
|
||||||
|
status: AdminPanelHealthServiceStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum AdminPanelHealthServiceStatus {
|
||||||
|
OPERATIONAL = 'OPERATIONAL',
|
||||||
|
OUTAGE = 'OUTAGE'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AdminPanelIndicatorHealthStatusInputEnum {
|
||||||
|
DATABASE = 'DATABASE',
|
||||||
|
MESSAGE_SYNC = 'MESSAGE_SYNC',
|
||||||
|
REDIS = 'REDIS',
|
||||||
|
WORKER = 'WORKER'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AdminPanelWorkerQueueHealth = {
|
||||||
|
__typename?: 'AdminPanelWorkerQueueHealth';
|
||||||
|
metrics: WorkerQueueMetrics;
|
||||||
|
name: Scalars['String']['output'];
|
||||||
|
status: AdminPanelHealthServiceStatus;
|
||||||
|
workers: Scalars['Float']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
export type Analytics = {
|
export type Analytics = {
|
||||||
__typename?: 'Analytics';
|
__typename?: 'Analytics';
|
||||||
/** Boolean that confirms query was dispatched */
|
/** Boolean that confirms query was dispatched */
|
||||||
@ -257,6 +283,7 @@ export type ClientConfig = {
|
|||||||
debugMode: Scalars['Boolean']['output'];
|
debugMode: Scalars['Boolean']['output'];
|
||||||
defaultSubdomain?: Maybe<Scalars['String']['output']>;
|
defaultSubdomain?: Maybe<Scalars['String']['output']>;
|
||||||
frontDomain: Scalars['String']['output'];
|
frontDomain: Scalars['String']['output'];
|
||||||
|
isAttachmentPreviewEnabled: Scalars['Boolean']['output'];
|
||||||
isEmailVerificationRequired: Scalars['Boolean']['output'];
|
isEmailVerificationRequired: Scalars['Boolean']['output'];
|
||||||
isGoogleCalendarEnabled: Scalars['Boolean']['output'];
|
isGoogleCalendarEnabled: Scalars['Boolean']['output'];
|
||||||
isGoogleMessagingEnabled: Scalars['Boolean']['output'];
|
isGoogleMessagingEnabled: Scalars['Boolean']['output'];
|
||||||
@ -809,6 +836,7 @@ export type Mutation = {
|
|||||||
activateWorkspace: Workspace;
|
activateWorkspace: Workspace;
|
||||||
authorizeApp: AuthorizeApp;
|
authorizeApp: AuthorizeApp;
|
||||||
buildDraftServerlessFunction: ServerlessFunction;
|
buildDraftServerlessFunction: ServerlessFunction;
|
||||||
|
checkCustomDomainValidRecords?: Maybe<CustomDomainValidRecords>;
|
||||||
checkoutSession: BillingSessionOutput;
|
checkoutSession: BillingSessionOutput;
|
||||||
computeStepOutputSchema: Scalars['JSON']['output'];
|
computeStepOutputSchema: Scalars['JSON']['output'];
|
||||||
createDraftFromWorkflowVersion: WorkflowVersion;
|
createDraftFromWorkflowVersion: WorkflowVersion;
|
||||||
@ -1305,6 +1333,13 @@ export type PageInfo = {
|
|||||||
startCursor?: Maybe<Scalars['ConnectionCursor']['output']>;
|
startCursor?: Maybe<Scalars['ConnectionCursor']['output']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum PermissionsOnAllObjectRecords {
|
||||||
|
DESTROY_ALL_OBJECT_RECORDS = 'DESTROY_ALL_OBJECT_RECORDS',
|
||||||
|
READ_ALL_OBJECT_RECORDS = 'READ_ALL_OBJECT_RECORDS',
|
||||||
|
SOFT_DELETE_ALL_OBJECT_RECORDS = 'SOFT_DELETE_ALL_OBJECT_RECORDS',
|
||||||
|
UPDATE_ALL_OBJECT_RECORDS = 'UPDATE_ALL_OBJECT_RECORDS'
|
||||||
|
}
|
||||||
|
|
||||||
export type PostgresCredentials = {
|
export type PostgresCredentials = {
|
||||||
__typename?: 'PostgresCredentials';
|
__typename?: 'PostgresCredentials';
|
||||||
id: Scalars['UUID']['output'];
|
id: Scalars['UUID']['output'];
|
||||||
@ -1343,7 +1378,6 @@ export type PublishServerlessFunctionInput = {
|
|||||||
export type Query = {
|
export type Query = {
|
||||||
__typename?: 'Query';
|
__typename?: 'Query';
|
||||||
billingPortalSession: BillingSessionOutput;
|
billingPortalSession: BillingSessionOutput;
|
||||||
checkCustomDomainValidRecords?: Maybe<CustomDomainValidRecords>;
|
|
||||||
checkUserExists: UserExistsOutput;
|
checkUserExists: UserExistsOutput;
|
||||||
checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid;
|
checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid;
|
||||||
clientConfig: ClientConfig;
|
clientConfig: ClientConfig;
|
||||||
@ -1361,18 +1395,20 @@ export type Query = {
|
|||||||
findWorkspaceInvitations: Array<WorkspaceInvitation>;
|
findWorkspaceInvitations: Array<WorkspaceInvitation>;
|
||||||
getAvailablePackages: Scalars['JSON']['output'];
|
getAvailablePackages: Scalars['JSON']['output'];
|
||||||
getEnvironmentVariablesGrouped: EnvironmentVariablesOutput;
|
getEnvironmentVariablesGrouped: EnvironmentVariablesOutput;
|
||||||
|
getIndicatorHealthStatus: AdminPanelHealthServiceData;
|
||||||
getPostgresCredentials?: Maybe<PostgresCredentials>;
|
getPostgresCredentials?: Maybe<PostgresCredentials>;
|
||||||
getProductPrices: BillingProductPricesOutput;
|
getProductPrices: BillingProductPricesOutput;
|
||||||
getPublicWorkspaceDataByDomain: PublicWorkspaceDataOutput;
|
getPublicWorkspaceDataByDomain: PublicWorkspaceDataOutput;
|
||||||
getRoles: Array<Role>;
|
getRoles: Array<Role>;
|
||||||
|
getSSOIdentityProviders: Array<FindAvailableSsoidpOutput>;
|
||||||
getServerlessFunctionSourceCode?: Maybe<Scalars['JSON']['output']>;
|
getServerlessFunctionSourceCode?: Maybe<Scalars['JSON']['output']>;
|
||||||
|
getSystemHealthStatus: SystemHealth;
|
||||||
getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal;
|
getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal;
|
||||||
getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal;
|
getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal;
|
||||||
getTimelineThreadsFromCompanyId: TimelineThreadsWithTotal;
|
getTimelineThreadsFromCompanyId: TimelineThreadsWithTotal;
|
||||||
getTimelineThreadsFromPersonId: TimelineThreadsWithTotal;
|
getTimelineThreadsFromPersonId: TimelineThreadsWithTotal;
|
||||||
index: Index;
|
index: Index;
|
||||||
indexMetadatas: IndexConnection;
|
indexMetadatas: IndexConnection;
|
||||||
listSSOIdentityProvidersByWorkspaceId: Array<FindAvailableSsoidpOutput>;
|
|
||||||
object: Object;
|
object: Object;
|
||||||
objects: ObjectConnection;
|
objects: ObjectConnection;
|
||||||
plans: Array<BillingPlanOutput>;
|
plans: Array<BillingPlanOutput>;
|
||||||
@ -1443,6 +1479,11 @@ export type QueryGetAvailablePackagesArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryGetIndicatorHealthStatusArgs = {
|
||||||
|
indicatorName: AdminPanelIndicatorHealthStatusInputEnum;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type QueryGetProductPricesArgs = {
|
export type QueryGetProductPricesArgs = {
|
||||||
product: Scalars['String']['input'];
|
product: Scalars['String']['input'];
|
||||||
};
|
};
|
||||||
@ -1633,6 +1674,10 @@ export type ResendEmailVerificationTokenOutput = {
|
|||||||
|
|
||||||
export type Role = {
|
export type Role = {
|
||||||
__typename?: 'Role';
|
__typename?: 'Role';
|
||||||
|
canDestroyAllObjectRecords: Scalars['Boolean']['output'];
|
||||||
|
canReadAllObjectRecords: Scalars['Boolean']['output'];
|
||||||
|
canSoftDeleteAllObjectRecords: Scalars['Boolean']['output'];
|
||||||
|
canUpdateAllObjectRecords: Scalars['Boolean']['output'];
|
||||||
canUpdateAllSettings: Scalars['Boolean']['output'];
|
canUpdateAllSettings: Scalars['Boolean']['output'];
|
||||||
description?: Maybe<Scalars['String']['output']>;
|
description?: Maybe<Scalars['String']['output']>;
|
||||||
id: Scalars['String']['output'];
|
id: Scalars['String']['output'];
|
||||||
@ -1798,6 +1843,14 @@ export type Support = {
|
|||||||
supportFrontChatId?: Maybe<Scalars['String']['output']>;
|
supportFrontChatId?: Maybe<Scalars['String']['output']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type SystemHealth = {
|
||||||
|
__typename?: 'SystemHealth';
|
||||||
|
database: AdminPanelHealthServiceData;
|
||||||
|
messageSync: AdminPanelHealthServiceData;
|
||||||
|
redis: AdminPanelHealthServiceData;
|
||||||
|
worker: AdminPanelHealthServiceData;
|
||||||
|
};
|
||||||
|
|
||||||
export type TimelineCalendarEvent = {
|
export type TimelineCalendarEvent = {
|
||||||
__typename?: 'TimelineCalendarEvent';
|
__typename?: 'TimelineCalendarEvent';
|
||||||
conferenceLink: LinksMetadata;
|
conferenceLink: LinksMetadata;
|
||||||
@ -2050,8 +2103,8 @@ export type UserWorkspace = {
|
|||||||
createdAt: Scalars['DateTime']['output'];
|
createdAt: Scalars['DateTime']['output'];
|
||||||
deletedAt?: Maybe<Scalars['DateTime']['output']>;
|
deletedAt?: Maybe<Scalars['DateTime']['output']>;
|
||||||
id: Scalars['UUID']['output'];
|
id: Scalars['UUID']['output'];
|
||||||
settingsPermissions?: Maybe<Array<SettingsFeatures>>;
|
|
||||||
objectRecordsPermissions?: Maybe<Array<PermissionsOnAllObjectRecords>>;
|
objectRecordsPermissions?: Maybe<Array<PermissionsOnAllObjectRecords>>;
|
||||||
|
settingsPermissions?: Maybe<Array<SettingsFeatures>>;
|
||||||
updatedAt: Scalars['DateTime']['output'];
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
user: User;
|
user: User;
|
||||||
userId: Scalars['String']['output'];
|
userId: Scalars['String']['output'];
|
||||||
@ -2065,6 +2118,16 @@ export type ValidatePasswordResetToken = {
|
|||||||
id: Scalars['String']['output'];
|
id: Scalars['String']['output'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type WorkerQueueMetrics = {
|
||||||
|
__typename?: 'WorkerQueueMetrics';
|
||||||
|
active: Scalars['Float']['output'];
|
||||||
|
completed: Scalars['Float']['output'];
|
||||||
|
delayed: Scalars['Float']['output'];
|
||||||
|
failed: Scalars['Float']['output'];
|
||||||
|
prioritized: Scalars['Float']['output'];
|
||||||
|
waiting: Scalars['Float']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
export type WorkflowAction = {
|
export type WorkflowAction = {
|
||||||
__typename?: 'WorkflowAction';
|
__typename?: 'WorkflowAction';
|
||||||
id: Scalars['UUID']['output'];
|
id: Scalars['UUID']['output'];
|
||||||
|
|||||||
@ -1264,6 +1264,7 @@ export type Query = {
|
|||||||
getProductPrices: BillingProductPricesOutput;
|
getProductPrices: BillingProductPricesOutput;
|
||||||
getPublicWorkspaceDataByDomain: PublicWorkspaceDataOutput;
|
getPublicWorkspaceDataByDomain: PublicWorkspaceDataOutput;
|
||||||
getRoles: Array<Role>;
|
getRoles: Array<Role>;
|
||||||
|
getSSOIdentityProviders: Array<FindAvailableSsoidpOutput>;
|
||||||
getServerlessFunctionSourceCode?: Maybe<Scalars['JSON']>;
|
getServerlessFunctionSourceCode?: Maybe<Scalars['JSON']>;
|
||||||
getSystemHealthStatus: SystemHealth;
|
getSystemHealthStatus: SystemHealth;
|
||||||
getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal;
|
getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal;
|
||||||
@ -1272,7 +1273,6 @@ export type Query = {
|
|||||||
getTimelineThreadsFromPersonId: TimelineThreadsWithTotal;
|
getTimelineThreadsFromPersonId: TimelineThreadsWithTotal;
|
||||||
index: Index;
|
index: Index;
|
||||||
indexMetadatas: IndexConnection;
|
indexMetadatas: IndexConnection;
|
||||||
listSSOIdentityProvidersByWorkspaceId: Array<FindAvailableSsoidpOutput>;
|
|
||||||
object: Object;
|
object: Object;
|
||||||
objects: ObjectConnection;
|
objects: ObjectConnection;
|
||||||
plans: Array<BillingPlanOutput>;
|
plans: Array<BillingPlanOutput>;
|
||||||
@ -2364,10 +2364,10 @@ export type EditSsoIdentityProviderMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type EditSsoIdentityProviderMutation = { __typename?: 'Mutation', editSSOIdentityProvider: { __typename?: 'EditSsoOutput', id: string, type: IdentityProviderType, issuer: string, name: string, status: SsoIdentityProviderStatus } };
|
export type EditSsoIdentityProviderMutation = { __typename?: 'Mutation', editSSOIdentityProvider: { __typename?: 'EditSsoOutput', id: string, type: IdentityProviderType, issuer: string, name: string, status: SsoIdentityProviderStatus } };
|
||||||
|
|
||||||
export type ListSsoIdentityProvidersByWorkspaceIdQueryVariables = Exact<{ [key: string]: never; }>;
|
export type GetSsoIdentityProvidersQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type ListSsoIdentityProvidersByWorkspaceIdQuery = { __typename?: 'Query', listSSOIdentityProvidersByWorkspaceId: Array<{ __typename?: 'FindAvailableSSOIDPOutput', type: IdentityProviderType, id: string, name: string, issuer: string, status: SsoIdentityProviderStatus }> };
|
export type GetSsoIdentityProvidersQuery = { __typename?: 'Query', getSSOIdentityProviders: Array<{ __typename?: 'FindAvailableSSOIDPOutput', type: IdentityProviderType, id: string, name: string, issuer: string, status: SsoIdentityProviderStatus }> };
|
||||||
|
|
||||||
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, analyticsTinybirdJwts?: { __typename?: 'AnalyticsTinybirdJwtMap', getWebhookAnalytics: string, getPageviewsAnalytics: string, getUsersAnalytics: string, getServerlessFunctionDuration: string, getServerlessFunctionSuccessRate: string, getServerlessFunctionErrorCount: string } | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentUserWorkspace?: { __typename?: 'UserWorkspace', settingsPermissions?: Array<SettingsFeatures> | null, objectRecordsPermissions?: Array<PermissionsOnAllObjectRecords> | null } | null, currentWorkspace?: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, subdomain: string, hasValidEnterpriseKey: boolean, customDomain?: string | null, metadataVersion: number, workspaceMembersCount?: number | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: FeatureFlagKey, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus }> } | null, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, subdomain: string, customDomain?: string | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null } } | null }> };
|
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, analyticsTinybirdJwts?: { __typename?: 'AnalyticsTinybirdJwtMap', getWebhookAnalytics: string, getPageviewsAnalytics: string, getUsersAnalytics: string, getServerlessFunctionDuration: string, getServerlessFunctionSuccessRate: string, getServerlessFunctionErrorCount: string } | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentUserWorkspace?: { __typename?: 'UserWorkspace', settingsPermissions?: Array<SettingsFeatures> | null, objectRecordsPermissions?: Array<PermissionsOnAllObjectRecords> | null } | null, currentWorkspace?: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, subdomain: string, hasValidEnterpriseKey: boolean, customDomain?: string | null, metadataVersion: number, workspaceMembersCount?: number | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: FeatureFlagKey, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus }> } | null, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, subdomain: string, customDomain?: string | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null } } | null }> };
|
||||||
|
|
||||||
@ -4392,9 +4392,9 @@ export function useEditSsoIdentityProviderMutation(baseOptions?: Apollo.Mutation
|
|||||||
export type EditSsoIdentityProviderMutationHookResult = ReturnType<typeof useEditSsoIdentityProviderMutation>;
|
export type EditSsoIdentityProviderMutationHookResult = ReturnType<typeof useEditSsoIdentityProviderMutation>;
|
||||||
export type EditSsoIdentityProviderMutationResult = Apollo.MutationResult<EditSsoIdentityProviderMutation>;
|
export type EditSsoIdentityProviderMutationResult = Apollo.MutationResult<EditSsoIdentityProviderMutation>;
|
||||||
export type EditSsoIdentityProviderMutationOptions = Apollo.BaseMutationOptions<EditSsoIdentityProviderMutation, EditSsoIdentityProviderMutationVariables>;
|
export type EditSsoIdentityProviderMutationOptions = Apollo.BaseMutationOptions<EditSsoIdentityProviderMutation, EditSsoIdentityProviderMutationVariables>;
|
||||||
export const ListSsoIdentityProvidersByWorkspaceIdDocument = gql`
|
export const GetSsoIdentityProvidersDocument = gql`
|
||||||
query ListSSOIdentityProvidersByWorkspaceId {
|
query GetSSOIdentityProviders {
|
||||||
listSSOIdentityProvidersByWorkspaceId {
|
getSSOIdentityProviders {
|
||||||
type
|
type
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@ -4405,31 +4405,31 @@ export const ListSsoIdentityProvidersByWorkspaceIdDocument = gql`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useListSsoIdentityProvidersByWorkspaceIdQuery__
|
* __useGetSsoIdentityProvidersQuery__
|
||||||
*
|
*
|
||||||
* To run a query within a React component, call `useListSsoIdentityProvidersByWorkspaceIdQuery` and pass it any options that fit your needs.
|
* To run a query within a React component, call `useGetSsoIdentityProvidersQuery` and pass it any options that fit your needs.
|
||||||
* When your component renders, `useListSsoIdentityProvidersByWorkspaceIdQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
* When your component renders, `useGetSsoIdentityProvidersQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
* you can use to render your UI.
|
* 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;
|
* @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
|
* @example
|
||||||
* const { data, loading, error } = useListSsoIdentityProvidersByWorkspaceIdQuery({
|
* const { data, loading, error } = useGetSsoIdentityProvidersQuery({
|
||||||
* variables: {
|
* variables: {
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useListSsoIdentityProvidersByWorkspaceIdQuery(baseOptions?: Apollo.QueryHookOptions<ListSsoIdentityProvidersByWorkspaceIdQuery, ListSsoIdentityProvidersByWorkspaceIdQueryVariables>) {
|
export function useGetSsoIdentityProvidersQuery(baseOptions?: Apollo.QueryHookOptions<GetSsoIdentityProvidersQuery, GetSsoIdentityProvidersQueryVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return Apollo.useQuery<ListSsoIdentityProvidersByWorkspaceIdQuery, ListSsoIdentityProvidersByWorkspaceIdQueryVariables>(ListSsoIdentityProvidersByWorkspaceIdDocument, options);
|
return Apollo.useQuery<GetSsoIdentityProvidersQuery, GetSsoIdentityProvidersQueryVariables>(GetSsoIdentityProvidersDocument, options);
|
||||||
}
|
}
|
||||||
export function useListSsoIdentityProvidersByWorkspaceIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ListSsoIdentityProvidersByWorkspaceIdQuery, ListSsoIdentityProvidersByWorkspaceIdQueryVariables>) {
|
export function useGetSsoIdentityProvidersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetSsoIdentityProvidersQuery, GetSsoIdentityProvidersQueryVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return Apollo.useLazyQuery<ListSsoIdentityProvidersByWorkspaceIdQuery, ListSsoIdentityProvidersByWorkspaceIdQueryVariables>(ListSsoIdentityProvidersByWorkspaceIdDocument, options);
|
return Apollo.useLazyQuery<GetSsoIdentityProvidersQuery, GetSsoIdentityProvidersQueryVariables>(GetSsoIdentityProvidersDocument, options);
|
||||||
}
|
}
|
||||||
export type ListSsoIdentityProvidersByWorkspaceIdQueryHookResult = ReturnType<typeof useListSsoIdentityProvidersByWorkspaceIdQuery>;
|
export type GetSsoIdentityProvidersQueryHookResult = ReturnType<typeof useGetSsoIdentityProvidersQuery>;
|
||||||
export type ListSsoIdentityProvidersByWorkspaceIdLazyQueryHookResult = ReturnType<typeof useListSsoIdentityProvidersByWorkspaceIdLazyQuery>;
|
export type GetSsoIdentityProvidersLazyQueryHookResult = ReturnType<typeof useGetSsoIdentityProvidersLazyQuery>;
|
||||||
export type ListSsoIdentityProvidersByWorkspaceIdQueryResult = Apollo.QueryResult<ListSsoIdentityProvidersByWorkspaceIdQuery, ListSsoIdentityProvidersByWorkspaceIdQueryVariables>;
|
export type GetSsoIdentityProvidersQueryResult = Apollo.QueryResult<GetSsoIdentityProvidersQuery, GetSsoIdentityProvidersQueryVariables>;
|
||||||
export const DeleteUserAccountDocument = gql`
|
export const DeleteUserAccountDocument = gql`
|
||||||
mutation DeleteUserAccount {
|
mutation DeleteUserAccount {
|
||||||
deleteUser {
|
deleteUser {
|
||||||
|
|||||||
@ -49,7 +49,6 @@ export const SettingsAccountsRowDropdownMenu = ({
|
|||||||
<>
|
<>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
dropdownId={dropdownId}
|
dropdownId={dropdownId}
|
||||||
className={className}
|
|
||||||
dropdownPlacement="right-start"
|
dropdownPlacement="right-start"
|
||||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||||
clickableComponent={
|
clickableComponent={
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import styled from '@emotion/styled';
|
|||||||
import { useLingui } from '@lingui/react/macro';
|
import { useLingui } from '@lingui/react/macro';
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
import { IconKey } from 'twenty-ui';
|
import { IconKey } from 'twenty-ui';
|
||||||
import { useListSsoIdentityProvidersByWorkspaceIdQuery } from '~/generated/graphql';
|
import { useGetSsoIdentityProvidersQuery } from '~/generated/graphql';
|
||||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||||
|
|
||||||
const StyledLink = styled(Link, {
|
const StyledLink = styled(Link, {
|
||||||
@ -36,13 +36,11 @@ export const SettingsSSOIdentitiesProvidersListCard = () => {
|
|||||||
SSOIdentitiesProvidersState,
|
SSOIdentitiesProvidersState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { loading } = useListSsoIdentityProvidersByWorkspaceIdQuery({
|
const { loading } = useGetSsoIdentityProvidersQuery({
|
||||||
fetchPolicy: 'network-only',
|
fetchPolicy: 'network-only',
|
||||||
skip: currentWorkspace?.hasValidEnterpriseKey === false,
|
skip: currentWorkspace?.hasValidEnterpriseKey === false,
|
||||||
onCompleted: (data) => {
|
onCompleted: (data) => {
|
||||||
setSSOIdentitiesProviders(
|
setSSOIdentitiesProviders(data?.getSSOIdentityProviders ?? []);
|
||||||
data?.listSSOIdentityProvidersByWorkspaceId ?? [],
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
onError: (error: Error) => {
|
onError: (error: Error) => {
|
||||||
enqueueSnackBar(error.message, {
|
enqueueSnackBar(error.message, {
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
export const LIST_WORKSPACE_SSO_IDENTITY_PROVIDERS = gql`
|
export const GET_SSO_IDENTITY_PROVIDERS = gql`
|
||||||
query ListSSOIdentityProvidersByWorkspaceId {
|
query GetSSOIdentityProviders {
|
||||||
listSSOIdentityProvidersByWorkspaceId {
|
getSSOIdentityProviders {
|
||||||
type
|
type
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
|||||||
@ -0,0 +1,209 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
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 { SSOException } from 'src/engine/core-modules/sso/sso.exception';
|
||||||
|
|
||||||
|
describe('SSOService', () => {
|
||||||
|
let service: SSOService;
|
||||||
|
let repository: Repository<WorkspaceSSOIdentityProvider>;
|
||||||
|
let billingService: BillingService;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
SSOService,
|
||||||
|
{
|
||||||
|
provide: getRepositoryToken(WorkspaceSSOIdentityProvider, 'core'),
|
||||||
|
useClass: Repository,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: BillingService,
|
||||||
|
useValue: {
|
||||||
|
hasEntitlement: jest.fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: EnvironmentService,
|
||||||
|
useValue: {
|
||||||
|
get: jest.fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: ExceptionHandlerService,
|
||||||
|
useValue: {
|
||||||
|
captureExceptions: jest.fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<SSOService>(SSOService);
|
||||||
|
repository = module.get<Repository<WorkspaceSSOIdentityProvider>>(
|
||||||
|
getRepositoryToken(WorkspaceSSOIdentityProvider, 'core'),
|
||||||
|
);
|
||||||
|
billingService = module.get<BillingService>(BillingService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('createOIDCIdentityProvider', () => {
|
||||||
|
it('should create an OIDC identity provider successfully', async () => {
|
||||||
|
const workspaceId = 'workspace-123';
|
||||||
|
const data = {
|
||||||
|
issuer: 'https://example.com',
|
||||||
|
clientID: 'client-id',
|
||||||
|
clientSecret: 'client-secret',
|
||||||
|
name: 'Test Provider',
|
||||||
|
};
|
||||||
|
const mockIssuer = { metadata: { issuer: 'https://example.com' } };
|
||||||
|
const mockSavedProvider = {
|
||||||
|
id: 'provider-123',
|
||||||
|
type: 'OIDC',
|
||||||
|
name: 'Test Provider',
|
||||||
|
status: 'ACTIVE',
|
||||||
|
issuer: 'https://example.com',
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.spyOn(billingService, 'hasEntitlement').mockResolvedValue(true);
|
||||||
|
jest
|
||||||
|
.spyOn(service as any, 'getIssuerForOIDC')
|
||||||
|
.mockResolvedValue(mockIssuer);
|
||||||
|
jest
|
||||||
|
.spyOn(repository, 'save')
|
||||||
|
.mockResolvedValue(mockSavedProvider as any);
|
||||||
|
|
||||||
|
const result = await service.createOIDCIdentityProvider(
|
||||||
|
data,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
id: 'provider-123',
|
||||||
|
type: 'OIDC',
|
||||||
|
name: 'Test Provider',
|
||||||
|
status: 'ACTIVE',
|
||||||
|
issuer: 'https://example.com',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(billingService.hasEntitlement).toHaveBeenCalledWith(
|
||||||
|
workspaceId,
|
||||||
|
'SSO',
|
||||||
|
);
|
||||||
|
expect(repository.save).toHaveBeenCalledWith({
|
||||||
|
type: 'OIDC',
|
||||||
|
clientID: 'client-id',
|
||||||
|
clientSecret: 'client-secret',
|
||||||
|
issuer: 'https://example.com',
|
||||||
|
name: 'Test Provider',
|
||||||
|
workspaceId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an exception when SSO is disabled', async () => {
|
||||||
|
const workspaceId = 'workspace-123';
|
||||||
|
const data = {
|
||||||
|
issuer: 'https://example.com',
|
||||||
|
clientID: 'client-id',
|
||||||
|
clientSecret: 'client-secret',
|
||||||
|
name: 'Test Provider',
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.spyOn(billingService, 'hasEntitlement').mockResolvedValue(false);
|
||||||
|
|
||||||
|
const result = await service.createOIDCIdentityProvider(
|
||||||
|
data,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toBeInstanceOf(SSOException);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('deleteSSOIdentityProvider', () => {
|
||||||
|
it('should delete the identity provider successfully', async () => {
|
||||||
|
const identityProviderId = 'provider-123';
|
||||||
|
const workspaceId = 'workspace-123';
|
||||||
|
const mockProvider = { id: identityProviderId };
|
||||||
|
|
||||||
|
jest.spyOn(repository, 'findOne').mockResolvedValue(mockProvider as any);
|
||||||
|
jest.spyOn(repository, 'delete').mockResolvedValue(null as any);
|
||||||
|
|
||||||
|
const result = await service.deleteSSOIdentityProvider(
|
||||||
|
identityProviderId,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual({ identityProviderId: 'provider-123' });
|
||||||
|
expect(repository.findOne).toHaveBeenCalledWith({
|
||||||
|
where: { id: identityProviderId, workspaceId },
|
||||||
|
});
|
||||||
|
expect(repository.delete).toHaveBeenCalledWith({
|
||||||
|
id: identityProviderId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an exception if the identity provider does not exist', async () => {
|
||||||
|
const identityProviderId = 'provider-123';
|
||||||
|
const workspaceId = 'workspace-123';
|
||||||
|
|
||||||
|
jest.spyOn(repository, 'findOne').mockResolvedValue(null);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
service.deleteSSOIdentityProvider(identityProviderId, workspaceId),
|
||||||
|
).rejects.toThrow(SSOException);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getAuthorizationUrlForSSO', () => {
|
||||||
|
it('should return an authorization URL', async () => {
|
||||||
|
const identityProviderId = 'provider-123';
|
||||||
|
const searchParams = { client: 'web' };
|
||||||
|
const mockIdentityProvider = {
|
||||||
|
id: 'provider-123',
|
||||||
|
type: 'OIDC',
|
||||||
|
};
|
||||||
|
|
||||||
|
jest
|
||||||
|
.spyOn(repository, 'findOne')
|
||||||
|
.mockResolvedValue(mockIdentityProvider as any);
|
||||||
|
jest
|
||||||
|
.spyOn(service as any, 'buildIssuerURL')
|
||||||
|
.mockReturnValue('https://example.com/auth');
|
||||||
|
|
||||||
|
const result = await service.getAuthorizationUrlForSSO(
|
||||||
|
identityProviderId,
|
||||||
|
searchParams,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
id: 'provider-123',
|
||||||
|
authorizationURL: 'https://example.com/auth',
|
||||||
|
type: 'OIDC',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(repository.findOne).toHaveBeenCalledWith({
|
||||||
|
where: { id: identityProviderId },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an exception if the identity provider is not found', async () => {
|
||||||
|
const identityProviderId = 'provider-123';
|
||||||
|
const searchParams = {};
|
||||||
|
|
||||||
|
jest.spyOn(repository, 'findOne').mockResolvedValue(null);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
service.getAuthorizationUrlForSSO(identityProviderId, searchParams),
|
||||||
|
).rejects.toThrow(SSOException);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -223,7 +223,7 @@ export class SSOService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async listSSOIdentityProvidersByWorkspaceId(workspaceId: string) {
|
async getSSOIdentityProviders(workspaceId: string) {
|
||||||
return (await this.workspaceSSOIdentityProviderRepository.find({
|
return (await this.workspaceSSOIdentityProviderRepository.find({
|
||||||
where: { workspaceId },
|
where: { workspaceId },
|
||||||
select: ['id', 'name', 'type', 'issuer', 'status'],
|
select: ['id', 'name', 'type', 'issuer', 'status'],
|
||||||
|
|||||||
@ -42,12 +42,12 @@ export class SSOResolver {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(EnterpriseFeaturesEnabledGuard)
|
@UseGuards(WorkspaceAuthGuard, EnterpriseFeaturesEnabledGuard)
|
||||||
@Query(() => [FindAvailableSSOIDPOutput])
|
@Query(() => [FindAvailableSSOIDPOutput])
|
||||||
async listSSOIdentityProvidersByWorkspaceId(
|
async getSSOIdentityProviders(
|
||||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||||
) {
|
) {
|
||||||
return this.sSOService.listSSOIdentityProvidersByWorkspaceId(workspaceId);
|
return this.sSOService.getSSOIdentityProviders(workspaceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(WorkspaceAuthGuard, EnterpriseFeaturesEnabledGuard)
|
@UseGuards(WorkspaceAuthGuard, EnterpriseFeaturesEnabledGuard)
|
||||||
|
|||||||
Reference in New Issue
Block a user