mirror of
https://github.com/directus/directus.git
synced 2026-01-23 14:47:56 -05:00
Fix legacy permissions for M2O fields in GraphQL (#16430)
* Remove relation for legacy permission without allowed field * Remove deprecated formatError and improve error handling * Add unit test Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>
This commit is contained in:
@@ -6,7 +6,6 @@ import {
|
||||
execute,
|
||||
ExecutionResult,
|
||||
FieldNode,
|
||||
formatError,
|
||||
FormattedExecutionResult,
|
||||
FragmentDefinitionNode,
|
||||
GraphQLBoolean,
|
||||
@@ -41,6 +40,7 @@ import {
|
||||
toInputObjectType,
|
||||
ObjectTypeComposerFieldConfigDefinition,
|
||||
} from 'graphql-compose';
|
||||
import processError from './utils/process-error';
|
||||
import { Knex } from 'knex';
|
||||
import { flatten, get, mapKeys, merge, omit, pick, set, transform, uniq } from 'lodash';
|
||||
import ms from 'ms';
|
||||
@@ -159,7 +159,7 @@ export class GraphQLService {
|
||||
|
||||
const formattedResult: FormattedExecutionResult = {
|
||||
...result,
|
||||
errors: result.errors?.map(formatError),
|
||||
errors: result.errors?.map((error) => processError(this.accountability, error)),
|
||||
};
|
||||
|
||||
return formattedResult;
|
||||
|
||||
34
api/src/services/graphql/utils/process-error.test.ts
Normal file
34
api/src/services/graphql/utils/process-error.test.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { GraphQLError } from 'graphql';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import processError from './process-error';
|
||||
|
||||
describe('GraphQL processError util', () => {
|
||||
const sampleError = new GraphQLError('An error message', { path: ['test_collection'] });
|
||||
const redactedError = {
|
||||
message: 'An unexpected error occurred.',
|
||||
extensions: {
|
||||
code: 'INTERNAL_SERVER_ERROR',
|
||||
},
|
||||
};
|
||||
|
||||
test('returns redacted error when unauthenticated', () => {
|
||||
expect(processError(null, sampleError)).toEqual(expect.objectContaining(redactedError));
|
||||
});
|
||||
|
||||
test('returns redacted error when authenticated but not an admin', () => {
|
||||
expect(processError({ role: 'd674e22b-f405-48ba-9958-9a7bd16a1aa9' }, sampleError)).toEqual(
|
||||
expect.objectContaining(redactedError)
|
||||
);
|
||||
});
|
||||
|
||||
test('returns original error when authenticated and is an admin', () => {
|
||||
expect(processError({ role: 'd674e22b-f405-48ba-9958-9a7bd16a1aa9', admin: true }, sampleError)).toEqual(
|
||||
expect.objectContaining({
|
||||
...sampleError,
|
||||
extensions: {
|
||||
code: 'INTERNAL_SERVER_ERROR',
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
25
api/src/services/graphql/utils/process-error.ts
Normal file
25
api/src/services/graphql/utils/process-error.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import logger from '../../../logger';
|
||||
import { GraphQLError, GraphQLFormattedError } from 'graphql';
|
||||
import { Accountability } from '@directus/shared/types';
|
||||
|
||||
const processError = (accountability: Accountability | null, error: Readonly<GraphQLError>): GraphQLFormattedError => {
|
||||
logger.error(error);
|
||||
|
||||
if (accountability?.admin === true) {
|
||||
return {
|
||||
...error,
|
||||
extensions: {
|
||||
code: 'INTERNAL_SERVER_ERROR',
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
message: 'An unexpected error occurred.',
|
||||
extensions: {
|
||||
code: 'INTERNAL_SERVER_ERROR',
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export default processError;
|
||||
@@ -85,7 +85,9 @@ export function reduceSchema(
|
||||
|
||||
if (
|
||||
relation.related_collection &&
|
||||
Object.keys(allowedFieldsInCollection).includes(relation.related_collection) === false
|
||||
(Object.keys(allowedFieldsInCollection).includes(relation.related_collection) === false ||
|
||||
// Ignore legacy permissions with an empty fields array
|
||||
allowedFieldsInCollection[relation.related_collection].length === 0)
|
||||
) {
|
||||
collectionsAllowed = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user