Reputation: 13
I'm currently working on a KeystoneJS project and encountering an issue with TypeScript. I've defined an access control function, isAdmin, as suggested in the KeystoneJS documentation:
const isAdmin = ({ session }: { session: Session }) => session?.data.isAdmin;
However, when I use this function in the access configuration for list operations (create, delete) in my schema.ts, TypeScript throws the following error:
Type '() => boolean' is not assignable to type 'ListOperationAccessControl<"create" | "delete", TypeInfo<any>>'.
Types of parameters '__0' and 'args' are incompatible.
Type 'BaseAccessArgs<TypeInfo<any>> & { operation: "create"; }' is not assignable to type '{ session: Session; }'.
Property 'session' is optional in type 'BaseAccessArgs<TypeInfo<any>> & { operation: "create"; }' but required in type '{ session: Session; }'.
Here's a simplified version of my schema.ts:
import { list } from "@keystone-6/core";
import type { Lists } from ".keystone/types";
type Session = {
data: {
id: string;
isAdmin: boolean;
};
};
const isAdmin = ({ session }: { session: Session }) => session?.data.isAdmin;
export const lists: Lists = {
User: list({
access: {
operation: {
create: isAdmin,
delete: isAdmin,
},
// ... other access controls
},
fields: {
// ... other fields
},
}),
// ... other lists
};
Additionally, I find it interesting that the built-in allowAll function in node_modules/@keystone-6/core/src/access.ts, which simply returns true, works without any issues.
export function allowAll() {
return true;
}
But when I tried to the same thing for isAdmin is still does not work.
function isAdmin() {
return true;
}
I tried to debug by using the valid inbuilt function (allowAll) as local function (isAdmin) with same logic but it still doesn't work.
When I run npm run dev
it still works, but when I run npm run test
it wouldn't.
npm run test is just running jest.
Upvotes: 1
Views: 103
Reputation: 61
I just faced and fixed the same issue right now. It's a typo in their documentation. They define a custom Session Type
type Session = {
data: {
id: string;
isAdmin: boolean;
}
}
to extract the "isAdmin" arrow function in a constant and forget to make the session optional, but the access.operation fields have optional inputs (you can use any of ({ session, context, listKey, operation }))
So the solution is very simple, just one key. Place a ? in session to make it not required
change
const isAdmin = ({ session }: { session: Session }) => session?.data.isAdmin;
to
const isAdmin = ({ session }: { session?: Session }) => session?.data.isAdmin;
Upvotes: 0
Reputation: 1
You got two different cases:
First
const isAdmin = ({ session }: { session: Session }) => session?.data.isAdmin;
Because the session variable can be of type "undefined" you can't return "undefined", so you need to place something to force the return as boolean like:
const isAdmin = ({ session }: { session: Session }) => Boolean(session?.data.isAdmin);
Second
function isAdmin() { return true; }
You can place that function in access as general but at the specific operations, you must define all the operations, query, create, update, delete.
{
access: {
operation: {
query: isAdmin,
create: isAdmin,
update: isAdmin,
delete: isAdmin,
}
},
Upvotes: 0