fix: return proper FORBIDDEN GraphQL errors from ApiKeyResolver (#21107)
## Context CI is broken on main, regression introduced in https://github.com/twentyhq/twenty/pull/21072 Guard-rejected ApiKey mutations returned malformed GraphQL responses. RequireAccessTokenGuard (and SettingsPermissionGuard) throw plain AuthException/PermissionException classes, which are not GraphQLErrors. ApiKeyResolver had no @UseFilters, so these exceptions were never translated, they surfaced as request-level errors with no data key (data: undefined) and a non-FORBIDDEN code, instead of data: null + FORBIDDEN. This broke the `createApiKey › should reject a non-ACCESS token even with API key permission` integration test (expect(res.body.data).toBeNull() received undefined). The sibling generateApiKeyToken test passed only because it lives on AuthResolver, which already declares these filters. ## Fix Add the standard exception filters to ApiKeyResolver, matching the idiom used by other guard-protected resolvers ```ts @UseFilters(AuthGraphqlApiExceptionFilter, PermissionsGraphqlApiExceptionFilter) ```
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { UseGuards } from '@nestjs/common';
|
||||
import { UseFilters, UseGuards } from '@nestjs/common';
|
||||
import { Args, Mutation, Parent, Query, ResolveField } from '@nestjs/graphql';
|
||||
|
||||
import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
|
||||
@@ -7,6 +7,7 @@ import { PermissionFlagType } from 'twenty-shared/constants';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { ApiKeyEntity } from 'src/engine/core-modules/api-key/api-key.entity';
|
||||
import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filters/auth-graphql-api-exception.filter';
|
||||
import { CreateApiKeyInput } from 'src/engine/core-modules/api-key/dtos/create-api-key.input';
|
||||
import { GetApiKeyInput } from 'src/engine/core-modules/api-key/dtos/get-api-key.input';
|
||||
import { RevokeApiKeyInput } from 'src/engine/core-modules/api-key/dtos/revoke-api-key.input';
|
||||
@@ -17,12 +18,14 @@ import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorat
|
||||
import { RequireAccessTokenGuard } from 'src/engine/guards/require-access-token.guard';
|
||||
import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-graphql-api-exception.filter';
|
||||
import { RoleDTO } from 'src/engine/metadata-modules/role/dtos/role.dto';
|
||||
|
||||
import { ApiKeyRoleService } from './services/api-key-role.service';
|
||||
import { ApiKeyService } from './services/api-key.service';
|
||||
|
||||
@MetadataResolver(() => ApiKeyEntity)
|
||||
@UseFilters(AuthGraphqlApiExceptionFilter, PermissionsGraphqlApiExceptionFilter)
|
||||
@UseGuards(
|
||||
WorkspaceAuthGuard,
|
||||
SettingsPermissionGuard(PermissionFlagType.API_KEYS_AND_WEBHOOKS),
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ describe('api key and webhooks permissions', () => {
|
||||
const queryData = {
|
||||
query: `
|
||||
mutation createApiKey {
|
||||
createApiKey(input: { name: "escalation", expiresAt: "2025-01-01T00:00:00Z" }) {
|
||||
createApiKey(input: { name: "escalation", expiresAt: "2025-01-01T00:00:00Z", roleId: "20202020-0000-4000-8000-000000000000" }) {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user