Skip to content

Commit

Permalink
Aff filter coercion and validation back to filter access control (#6678)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmatown authored Sep 29, 2021
1 parent 372bde5 commit eb1a89f
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/few-bats-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystone-next/keystone': patch
---

Fixed returning filters like `{ NOT: [{ name: { equals: 'blah' } }] }` from filter access control and improve error messages when returning bad filters from filter access control
15 changes: 14 additions & 1 deletion packages/keystone/src/lib/core/access-control.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { assertInputObjectType } from 'graphql';
import {
BaseGeneratedListTypes,
CreateListItemAccessControl,
Expand All @@ -12,7 +13,9 @@ import {
ListOperationAccessControl,
ListFilterAccessControl,
KeystoneContext,
getGqlNames,
} from '../../types';
import { coerceAndValidateForGraphQLInput } from '../coerceAndValidateForGraphQLInput';
import { accessReturnError, extensionError } from './graphql-errors';
import { InitialisedList } from './types-for-lists';
import { InputFilter } from './where-inputs';
Expand Down Expand Up @@ -58,7 +61,17 @@ export async function getAccessFilters(
const access = list.access.filter[operation];
try {
// @ts-ignore
return typeof access === 'function' ? await access(args) : access;
let filters = typeof access === 'function' ? await access(args) : access;
if (typeof filters === 'boolean') {
return filters;
}
const schema = context.sudo().graphql.schema;
const whereInput = assertInputObjectType(schema.getType(getGqlNames(list).whereInputName));
const result = coerceAndValidateForGraphQLInput(schema, whereInput, filters);
if (result.kind === 'valid') {
return result.value;
}
throw result.error;
} catch (error: any) {
throw extensionError('Access control', [
{ error, tag: `${args.listKey}.access.filter.${args.operation}` },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { text } from '@keystone-next/keystone/fields';
import { list } from '@keystone-next/keystone';
import { setupTestRunner } from '@keystone-next/keystone/testing';
import { apiTestConfig } from '../utils';

const runner = setupTestRunner({
config: apiTestConfig({
lists: {
BadAccess: list({
fields: { name: text({ isFilterable: true, isOrderable: true }) },
access: {
filter: {
query: () => {
return {
name: 'blah',
};
},
},
},
}),
Coercion: list({
fields: { name: text({ isFilterable: true, isOrderable: true }) },
access: {
filter: {
query: () => {
return { NOT: { name: { equals: 'blah' } } };
},
},
},
}),
},
}),
});

describe('Access control - Filter', () => {
test(
'findMany - Bad function return value',
runner(async ({ graphQLRequest }) => {
// Valid name
const { body } = await graphQLRequest({
query: `query { badAccesses { id } }`,
});

// Returns null and throws an error
expect(body.data).toEqual({ badAccesses: null });
expect(body.errors).toHaveLength(1);
expect(body.errors[0].path).toEqual(['badAccesses']);
expect(body.errors[0].message).toMatchInlineSnapshot(`
"An error occured while running \\"Access control\\".
- BadAccess.access.filter.query: Variable \\"$where\\" got invalid value \\"blah\\" at \\"where.name\\"; Expected type \\"StringFilter\\" to be an object."
`);
})
);
test(
'findMany - Coercion',
runner(async ({ context }) => {
await context.query.Coercion.createMany({ data: [{ name: 'something' }, { name: 'blah' }] });
expect(await context.query.Coercion.findMany({ query: 'name' })).toEqual([
{ name: 'something' },
]);
})
);
});

0 comments on commit eb1a89f

Please sign in to comment.