Linting error (@typescript-eslint/unbound-method) #835
-
I keep getting a import {
AbilityBuilder,
createMongoAbility,
MongoAbility,
} from '@casl/ability';
import { Role } from '@prisma/client';
import { z } from 'zod';
import { User } from '@/lib/zod/next-auth';
import { RoleType } from '@/lib/zod/prisma/generated';
export enum Action {
MANAGE = 'manage',
CREATE = 'create',
DELETE = 'delete',
READ = 'read',
READ_SENSITIVE = 'read_sensitive',
UPDATE = 'update',
}
export const ActionSchema = z.nativeEnum(Action);
export enum Subject {
ALL = 'all',
APPLICATION = 'application',
CLIENT = 'client',
CONTACT = 'contact',
USER = 'user',
}
export const SubjectSchema = z.nativeEnum(Subject);
export type AppAbility = MongoAbility<[Action, Subject]>;
export type ActionAndSubject = z.infer<typeof ActionAndSubjectSchema>;
export const ActionAndSubjectSchema = z.object({
action: ActionSchema,
subject: SubjectSchema,
});
const userHasRole = (user: User, role: RoleType) => {
return user.roles.includes(role);
};
export const defineAbilityFor = (user?: User) => {
const { can, build } = new AbilityBuilder<AppAbility>(createMongoAbility);
if (!user) {
return build();
}
// Application admin
if (userHasRole(user, Role.APPLICATION_ADMIN)) {
can(Action.MANAGE, Subject.ALL);
}
// Clients
if (userHasRole(user, Role.CLIENT_ADMIN)) {
can(Action.MANAGE, Subject.CLIENT);
}
if (userHasRole(user, Role.CLIENT_EDITOR)) {
can(Action.CREATE, Subject.CLIENT);
can(Action.UPDATE, Subject.CLIENT);
}
if (userHasRole(user, Role.CLIENT_VIEWER)) {
can(Action.READ, Subject.CLIENT);
}
if (userHasRole(user, Role.CLIENT_VIEWER_SENSITIVE)) {
can(Action.READ_SENSITIVE, Subject.CLIENT);
}
// Contacts
if (userHasRole(user, Role.CONTACT_ADMIN)) {
can(Action.MANAGE, Subject.CONTACT);
}
if (userHasRole(user, Role.CONTACT_EDITOR)) {
can(Action.CREATE, Subject.CONTACT);
can(Action.UPDATE, Subject.CONTACT);
}
if (userHasRole(user, Role.CONTACT_VIEWER)) {
can(Action.READ, Subject.CONTACT);
}
if (userHasRole(user, Role.CONTACT_VIEWER_SENSITIVE)) {
can(Action.READ_SENSITIVE, Subject.CONTACT);
}
return build();
}; However, when I try to destructure the result of the const { can } = defineAbilityFor(user); I saw a related issue (#736) that seemed to suggest it was resolved but I'm still getting the error. Is there a better way to create the |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
AbilityBuilder can/cannot methods are very complicated in terms of type inference. Eslint thinks the method is unbound because it cannot detect bound methods created with so methods are bound be sure. I’ve tried to rewrite AbilityBuilder so eslint understand that methods are bound but I remember it brought even more complexities. That’s why those changes have not been released If you want to get rid of that issue with deli t just use a variable const b = new AbilityBuilder<AppAbility>(createMongoAbility);
b.can(…) |
Beta Was this translation helpful? Give feedback.
AbilityBuilder can/cannot methods are very complicated in terms of type inference.
Eslint thinks the method is unbound because it cannot detect bound methods created with
.bind
so methods are bound be sure.
I’ve tried to rewrite AbilityBuilder so eslint understand that methods are bound but I remember it brought even more complexities. That’s why those changes have not been released
If you want to get rid of that issue with deli t just use a variable