diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 14e6a7aef..59805ee23 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1,6 +1,5 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -import { PermissionsOnAllObjectRecords } from 'twenty-shared'; export type Maybe = T | null; export type InputMaybe = Maybe; export type Exact = { [K in keyof T]: T[K] }; @@ -33,6 +32,33 @@ export type ActivateWorkspaceInput = { displayName?: InputMaybe; }; +export type AdminPanelHealthServiceData = { + __typename?: 'AdminPanelHealthServiceData'; + details?: Maybe; + queues?: Maybe>; + 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 = { __typename?: 'Analytics'; /** Boolean that confirms query was dispatched */ @@ -257,6 +283,7 @@ export type ClientConfig = { debugMode: Scalars['Boolean']['output']; defaultSubdomain?: Maybe; frontDomain: Scalars['String']['output']; + isAttachmentPreviewEnabled: Scalars['Boolean']['output']; isEmailVerificationRequired: Scalars['Boolean']['output']; isGoogleCalendarEnabled: Scalars['Boolean']['output']; isGoogleMessagingEnabled: Scalars['Boolean']['output']; @@ -809,6 +836,7 @@ export type Mutation = { activateWorkspace: Workspace; authorizeApp: AuthorizeApp; buildDraftServerlessFunction: ServerlessFunction; + checkCustomDomainValidRecords?: Maybe; checkoutSession: BillingSessionOutput; computeStepOutputSchema: Scalars['JSON']['output']; createDraftFromWorkflowVersion: WorkflowVersion; @@ -1305,6 +1333,13 @@ export type PageInfo = { startCursor?: Maybe; }; +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 = { __typename?: 'PostgresCredentials'; id: Scalars['UUID']['output']; @@ -1343,7 +1378,6 @@ export type PublishServerlessFunctionInput = { export type Query = { __typename?: 'Query'; billingPortalSession: BillingSessionOutput; - checkCustomDomainValidRecords?: Maybe; checkUserExists: UserExistsOutput; checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid; clientConfig: ClientConfig; @@ -1361,18 +1395,20 @@ export type Query = { findWorkspaceInvitations: Array; getAvailablePackages: Scalars['JSON']['output']; getEnvironmentVariablesGrouped: EnvironmentVariablesOutput; + getIndicatorHealthStatus: AdminPanelHealthServiceData; getPostgresCredentials?: Maybe; getProductPrices: BillingProductPricesOutput; getPublicWorkspaceDataByDomain: PublicWorkspaceDataOutput; getRoles: Array; + getSSOIdentityProviders: Array; getServerlessFunctionSourceCode?: Maybe; + getSystemHealthStatus: SystemHealth; getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal; getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal; getTimelineThreadsFromCompanyId: TimelineThreadsWithTotal; getTimelineThreadsFromPersonId: TimelineThreadsWithTotal; index: Index; indexMetadatas: IndexConnection; - listSSOIdentityProvidersByWorkspaceId: Array; object: Object; objects: ObjectConnection; plans: Array; @@ -1443,6 +1479,11 @@ export type QueryGetAvailablePackagesArgs = { }; +export type QueryGetIndicatorHealthStatusArgs = { + indicatorName: AdminPanelIndicatorHealthStatusInputEnum; +}; + + export type QueryGetProductPricesArgs = { product: Scalars['String']['input']; }; @@ -1633,6 +1674,10 @@ export type ResendEmailVerificationTokenOutput = { export type Role = { __typename?: 'Role'; + canDestroyAllObjectRecords: Scalars['Boolean']['output']; + canReadAllObjectRecords: Scalars['Boolean']['output']; + canSoftDeleteAllObjectRecords: Scalars['Boolean']['output']; + canUpdateAllObjectRecords: Scalars['Boolean']['output']; canUpdateAllSettings: Scalars['Boolean']['output']; description?: Maybe; id: Scalars['String']['output']; @@ -1798,6 +1843,14 @@ export type Support = { supportFrontChatId?: Maybe; }; +export type SystemHealth = { + __typename?: 'SystemHealth'; + database: AdminPanelHealthServiceData; + messageSync: AdminPanelHealthServiceData; + redis: AdminPanelHealthServiceData; + worker: AdminPanelHealthServiceData; +}; + export type TimelineCalendarEvent = { __typename?: 'TimelineCalendarEvent'; conferenceLink: LinksMetadata; @@ -2050,8 +2103,8 @@ export type UserWorkspace = { createdAt: Scalars['DateTime']['output']; deletedAt?: Maybe; id: Scalars['UUID']['output']; - settingsPermissions?: Maybe>; objectRecordsPermissions?: Maybe>; + settingsPermissions?: Maybe>; updatedAt: Scalars['DateTime']['output']; user: User; userId: Scalars['String']['output']; @@ -2065,6 +2118,16 @@ export type ValidatePasswordResetToken = { 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 = { __typename?: 'WorkflowAction'; id: Scalars['UUID']['output']; diff --git a/packages/twenty-front/src/generated/graphql.tsx b/packages/twenty-front/src/generated/graphql.tsx index a03fb87ab..e5deadd85 100644 --- a/packages/twenty-front/src/generated/graphql.tsx +++ b/packages/twenty-front/src/generated/graphql.tsx @@ -1264,6 +1264,7 @@ export type Query = { getProductPrices: BillingProductPricesOutput; getPublicWorkspaceDataByDomain: PublicWorkspaceDataOutput; getRoles: Array; + getSSOIdentityProviders: Array; getServerlessFunctionSourceCode?: Maybe; getSystemHealthStatus: SystemHealth; getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal; @@ -1272,7 +1273,6 @@ export type Query = { getTimelineThreadsFromPersonId: TimelineThreadsWithTotal; index: Index; indexMetadatas: IndexConnection; - listSSOIdentityProvidersByWorkspaceId: Array; object: Object; objects: ObjectConnection; plans: Array; @@ -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 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 | null, objectRecordsPermissions?: Array | 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; export type EditSsoIdentityProviderMutationResult = Apollo.MutationResult; export type EditSsoIdentityProviderMutationOptions = Apollo.BaseMutationOptions; -export const ListSsoIdentityProvidersByWorkspaceIdDocument = gql` - query ListSSOIdentityProvidersByWorkspaceId { - listSSOIdentityProvidersByWorkspaceId { +export const GetSsoIdentityProvidersDocument = gql` + query GetSSOIdentityProviders { + getSSOIdentityProviders { type id 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. - * When your component renders, `useListSsoIdentityProvidersByWorkspaceIdQuery` returns an object from Apollo Client that contains loading, error, and data properties + * To run a query within a React component, call `useGetSsoIdentityProvidersQuery` and pass it any options that fit your needs. + * 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. * * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; * * @example - * const { data, loading, error } = useListSsoIdentityProvidersByWorkspaceIdQuery({ + * const { data, loading, error } = useGetSsoIdentityProvidersQuery({ * variables: { * }, * }); */ -export function useListSsoIdentityProvidersByWorkspaceIdQuery(baseOptions?: Apollo.QueryHookOptions) { +export function useGetSsoIdentityProvidersQuery(baseOptions?: Apollo.QueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(ListSsoIdentityProvidersByWorkspaceIdDocument, options); + return Apollo.useQuery(GetSsoIdentityProvidersDocument, options); } -export function useListSsoIdentityProvidersByWorkspaceIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { +export function useGetSsoIdentityProvidersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(ListSsoIdentityProvidersByWorkspaceIdDocument, options); + return Apollo.useLazyQuery(GetSsoIdentityProvidersDocument, options); } -export type ListSsoIdentityProvidersByWorkspaceIdQueryHookResult = ReturnType; -export type ListSsoIdentityProvidersByWorkspaceIdLazyQueryHookResult = ReturnType; -export type ListSsoIdentityProvidersByWorkspaceIdQueryResult = Apollo.QueryResult; +export type GetSsoIdentityProvidersQueryHookResult = ReturnType; +export type GetSsoIdentityProvidersLazyQueryHookResult = ReturnType; +export type GetSsoIdentityProvidersQueryResult = Apollo.QueryResult; export const DeleteUserAccountDocument = gql` mutation DeleteUserAccount { deleteUser { diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsRowDropdownMenu.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsRowDropdownMenu.tsx index a02cf68bf..2cfec737e 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsRowDropdownMenu.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsRowDropdownMenu.tsx @@ -49,7 +49,6 @@ export const SettingsAccountsRowDropdownMenu = ({ <> { SSOIdentitiesProvidersState, ); - const { loading } = useListSsoIdentityProvidersByWorkspaceIdQuery({ + const { loading } = useGetSsoIdentityProvidersQuery({ fetchPolicy: 'network-only', skip: currentWorkspace?.hasValidEnterpriseKey === false, onCompleted: (data) => { - setSSOIdentitiesProviders( - data?.listSSOIdentityProvidersByWorkspaceId ?? [], - ); + setSSOIdentitiesProviders(data?.getSSOIdentityProviders ?? []); }, onError: (error: Error) => { enqueueSnackBar(error.message, { diff --git a/packages/twenty-front/src/modules/settings/security/graphql/queries/getWorkspaceSSOIdentitiesProviders.ts b/packages/twenty-front/src/modules/settings/security/graphql/queries/getWorkspaceSSOIdentitiesProviders.ts index 0fdd9701e..dded0d769 100644 --- a/packages/twenty-front/src/modules/settings/security/graphql/queries/getWorkspaceSSOIdentitiesProviders.ts +++ b/packages/twenty-front/src/modules/settings/security/graphql/queries/getWorkspaceSSOIdentitiesProviders.ts @@ -2,9 +2,9 @@ import { gql } from '@apollo/client'; -export const LIST_WORKSPACE_SSO_IDENTITY_PROVIDERS = gql` - query ListSSOIdentityProvidersByWorkspaceId { - listSSOIdentityProvidersByWorkspaceId { +export const GET_SSO_IDENTITY_PROVIDERS = gql` + query GetSSOIdentityProviders { + getSSOIdentityProviders { type id name diff --git a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts new file mode 100644 index 000000000..37a04d4f4 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts @@ -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; + 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); + repository = module.get>( + getRepositoryToken(WorkspaceSSOIdentityProvider, 'core'), + ); + billingService = module.get(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); + }); + }); +}); diff --git a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts index d3d6dd503..adb9c4968 100644 --- a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts +++ b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts @@ -223,7 +223,7 @@ export class SSOService { }; } - async listSSOIdentityProvidersByWorkspaceId(workspaceId: string) { + async getSSOIdentityProviders(workspaceId: string) { return (await this.workspaceSSOIdentityProviderRepository.find({ where: { workspaceId }, select: ['id', 'name', 'type', 'issuer', 'status'], diff --git a/packages/twenty-server/src/engine/core-modules/sso/sso.resolver.ts b/packages/twenty-server/src/engine/core-modules/sso/sso.resolver.ts index d967d3c7a..975b92b30 100644 --- a/packages/twenty-server/src/engine/core-modules/sso/sso.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/sso/sso.resolver.ts @@ -42,12 +42,12 @@ export class SSOResolver { ); } - @UseGuards(EnterpriseFeaturesEnabledGuard) + @UseGuards(WorkspaceAuthGuard, EnterpriseFeaturesEnabledGuard) @Query(() => [FindAvailableSSOIDPOutput]) - async listSSOIdentityProvidersByWorkspaceId( + async getSSOIdentityProviders( @AuthWorkspace() { id: workspaceId }: Workspace, ) { - return this.sSOService.listSSOIdentityProvidersByWorkspaceId(workspaceId); + return this.sSOService.getSSOIdentityProviders(workspaceId); } @UseGuards(WorkspaceAuthGuard, EnterpriseFeaturesEnabledGuard)