I am trying to restrict access to the admin panel to just
superAdmins
and
admins
both of which are roles on the user collection.
problem: I get the typescript error when i hover over
users.access.admin
access control function:
Type 'Access' is not assignable to type '(args?: any) => boolean | Promise<boolean>'.
Type 'AccessResult | Promise<AccessResult>' is not assignable to type 'boolean | Promise<boolean>'.
Type 'Where' is not assignable to type 'boolean | Promise<boolean>'.
Type 'Where' is missing the following properties from type 'Promise<boolean>': then, catch, finally, [Symbol.toStringTag]ts(2322)
types.d.ts(311, 9): The expected type comes from property 'admin' which is declared here on type '{ create?: Access; read?: Access; readVersions?: Access; update?: Access; delete?: Access; admin?: (args?: any) => boolean | Promise<boolean>; unlock?: Access; }'
Here is my Users collectio:
import { CollectionConfig } from "payload/types";
import isSuperAdmin from "../access/isSuperAdmin";
import isAdmin from "../access/isSuperAdmin";
import isSuperAdminOrAdmin from "../access/isSuperAdminOrAdmin";
const Users: CollectionConfig = {
slug: "users",
auth: {
cookies: {
// disabe "secure" property when in development mode, otherwise no cookies will be set
// secure: process.env.PAYLOAD_ENV !== "development",
sameSite: process.env.PAYLOAD_ENV === "testing" ? "none" : "lax",
},
},
access: {
create: isAdmin,
admin: isSuperAdminOrAdmin,
},
admin: {
useAsTitle: "email",
},
fields: [
{
name: "fullName",
label: "Full Name",
type: "text",
// required: true,
},
{
name: "phoneNumber",
type: "number",
label: "Phone Number",
// required: true,
unique: true,
},
{
name: "transactionPin",
type: "number",
label: "Transaction Pin",
// hidden: true, #uncomment this to make Transaction Pin to be visible in the admin UI
// required: true,
unique: true,
},
{
name: "roles",
type: "select",
hasMany: true,
saveToJWT: true,
options: [
{
label: "Super Admin",
value: "superAdmin",
},
{
label: "Admin",
value: "admin",
},
{
label: "Api User",
value: "apiUser",
},
{
label: "Normal user",
value: "normalUser",
},
],
},
],
};
export default Users;
isSuperAdminOrAdmin
function:
import { Access } from "payload/types";
import { User } from "../payload-types";
const isSuperAdminOrAdmin: Access<any, User> = async ({ req: { user } }) => {
const isSuperAdmin = user?.roles?.includes("superAdmin");
const isAdmin = user?.roles?.includes("admin");
return Boolean(isSuperAdmin || isAdmin);
};
export default isSuperAdminOrAdmin;
Hi! Pretty much what the error says: all the access controls expect an
Access
type function (which returns a boolean OR a Where), but the admin one expect a function that returns a boolean. Because
isSuperAdminOrAdmin
is typed as
Access
, it means that it could, in theory, return either a boolean or a Where. Now looking at the function, it is clear it will only ever return a boolean, but Typescript doesn't know that.
If you are using Typescript >= 4.9, you can use the
satisfies
keyword to let Typescript infer a more precise type for the function (in which case it will consider it a function that return a boolean), while still
satisfyingthe requirements of being an
Access
function. It would look like this:
const isSuperAdminOrAdmin = (({ req: { user } }) => {
const isSuperAdmin = user?.roles?.includes("superAdmin");
const isAdmin = user?.roles?.includes("admin");
return Boolean(isSuperAdmin || isAdmin);
}) satisfies Access<any, User>;
I also removed the async as there wasn't any await inside the function
I can't thank you enough, I am really grateful.
The error has been resolved.
If you don't mind, please where/how can I check the return type of Access function.
Glad it helped. If you are using VSCode, you should be able to hold the Ctrl key and left click on a variable/class/type. It will bring you to its definition. Alternatively, you can right-click on a type/variable/class/function and click on "Go to Definition" or "Go to Type Definition"
It worked.
However, I couldn't see a
Where
return type anywhere, perhaps I may be missing something.
The Where is part of the return type of the function. You need to do the same Ctrl+click maneuver on
AccessResult
Got it now. Thank you once again.
Star
Discord
online
Get dedicated engineering support directly from the Payload team.