I am following CASL's cookbook on roles with predefined permissions. I have defined my PlatformAbility as follows, in line with the cookbook instructions.
import { Ability, AbilityClass, ForcedSubject } from '@casl/ability';
const platformBaseActions = ['manage', 'read', 'write'] as const;
const platformSubjects = [
'all',
'membership',
'work-order',
'equipment',
'user',
] as const;
type PlatformAbilities = [
typeof platformBaseActions[number],
(
| typeof platformSubjects[number]
| ForcedSubject<Exclude<typeof platformSubjects[number], 'all'>>
),
];
export type PlatformAbility = Ability<PlatformAbilities>;
export const PlatformAbility = Ability as AbilityClass<PlatformAbility>;
Setting up role's permissions also works well.
import { AbilityBuilder } from '@casl/ability';
import { MembershipForUserDto } from '@my-org/shared/dtos-user-mgmt';
import { PlatformAbility } from './platform-ability';
import { PlatformRole } from './platform-role';
type PermissionsSetter = (
membership: MembershipForUserDto,
builder: AbilityBuilder<PlatformAbility>,
) => void;
export const platformRolePermissions: Record<PlatformRole, PermissionsSetter> =
{
PLATFORM_ADMIN(_, { can }) {
can('manage', 'all');
},
DISTRIBUTOR_ADMIN({ distributorId }, { can }) {
// can('read', 'membership', { distributorId: { $eq: '' } });
// can('read', 'membership', { distributorId });
can('write', 'membership');
},
DISTRIBUTOR_USER({ distributorId }, { can }) {
can('read', 'work-order');
can('read', 'equipment');
},
};
However, the moment I try to set a condition on one of the permissions (one of the commented out lines above), I get the following typing errors, respectively. The first error is on the entire line (can(...);) and the second only on distributorId.
No overload matches this call.
Overload 1 of 2, '(action: "manage" | "read" | "write" | ("manage" | "read" | "write")[], subject: "membership" | "membership"[], conditions?: MongoQuery<never> | undefined): RuleBuilder<...>', gave the following error.
Type 'string' is not assignable to type 'undefined'.
Overload 2 of 2, '(action: "manage" | "read" | "write" | ("manage" | "read" | "write")[], subject: "membership" | "membership"[], fields?: string | string[] | undefined, conditions?: MongoQuery<never> | undefined): RuleBuilder<...>', gave the following error.
Argument of type '{ distributorId: { $eq: string; }; }' is not assignable to parameter of type 'string | string[] | undefined'.
Object literal may only specify known properties, and 'distributorId' does not exist in type 'string[]'.ts(2769)
(property) distributorId: string
No overload matches this call.
Overload 1 of 2, '(action: "manage" | "read" | "write" | ("manage" | "read" | "write")[], subject: "membership" | "membership"[], conditions?: MongoQuery<never> | undefined): RuleBuilder<...>', gave the following error.
Type 'string' is not assignable to type 'Pick<MongoQueryOperators<MergeUnion<never, string | number | symbol>>, "$eq" | "$ne" | "$lt" | "$lte" | "$gt" | "$gte" | "$in" | "$nin" | ... 5 more ... | "$exists"> | OperatorValues<...> | undefined'.
Overload 2 of 2, '(action: "manage" | "read" | "write" | ("manage" | "read" | "write")[], subject: "membership" | "membership"[], fields?: string | string[] | undefined, conditions?: MongoQuery<never> | undefined): RuleBuilder<...>', gave the following error.
Argument of type '{ distributorId: string; }' is not assignable to parameter of type 'string | string[] | undefined'.
Object literal may only specify known properties, and 'distributorId' does not exist in type 'string[]'.ts(2769)
I am not sure if this is a bug or if I did something wrong with my typing. I've double and triple-checked my setup and I don't see where I diverged from the instructions in the cookbook. I tried explicitly setting the second Ability type parameter (Ability<PlatformAbilities, MongoQuery> and Ability<PlatformAbilities, MongoQuery<any>>) and I still get the same typing errors.