API: Guantr.prototype.can
The can method checks if a specific action is permitted on a given resource, according to the rules defined in the Guantr instance. It considers both allow and deny rules, including any applicable conditions based on the resource instance and context.
Signature
ts
interface Guantr<Meta, Context> {
can(
action: string, // Or specific action type from Meta
resource: string | [resourceKey: string, resourceInstance: object] // Or typed resource key/instance from Meta
): Promise<boolean>;
}Parameters
action: (string) The action being attempted (e.g.,'read','update').resource: (string|[string, object]) The resource being acted upon.- If a
string(e.g.,'post') is provided, it checks rules defined for the general resource type without evaluating instance-specific conditions. - If a tuple
[resourceKey: string, resourceInstance: object](e.g.,['post', { id: 1, status: 'draft' }]) is provided, it checks rules for theresourceKeyand evaluates any conditions against the properties of theresourceInstanceand the current context.
- If a
Returns
Promise<boolean>: A promise that resolves to:trueif the action is allowed (at least one matchingallowrule exists and no matchingdenyrule exists).falseif the action is denied (either no matchingallowrule exists, or a matchingdenyrule overrides anyallowrule).
How it Works
- Retrieves all rules relevant to the given
actionandresourcekey usingqueryRulesfrom the storage adapter. - If a
resourceInstanceis provided, it evaluates theconditionof each relevant rule against the instance's properties and the current context (obtained viagetContext). - Determines the outcome: Permission is granted (
true) if there's at least one applicableallowrule and no applicabledenyrules. Otherwise, permission is denied (false).
Examples
ts
// Assume guantr instance is initialized and rules are set:
// allow('read', 'article');
// deny('read', ['article', { status: ['eq', 'archived'] }]);
// allow('edit', ['article', { ownerId: ['eq', '$ctx.userId'] }]);
const activeArticle = { id: 1, status: 'published', ownerId: 'user-123' };
const archivedArticle = { id: 2, status: 'archived', ownerId: 'user-123' };
const someoneElsesArticle = { id: 3, status: 'published', ownerId: 'user-456' };
// Assume current context userId is 'user-123'
// Check general read permission (doesn't evaluate conditions)
const canReadType = await guantr.can('read', 'article');
// -> true (because the general 'allow read article' rule exists)
// Check read permission on specific instances
const canReadActive = await guantr.can('read', ['article', activeArticle]);
// -> true (general 'allow' applies, 'deny' condition doesn't match)
const canReadArchived = await guantr.can('read', ['article', archivedArticle]);
// -> false (general 'allow' applies, but 'deny' condition *does* match)
// Check edit permission (requires context and instance properties)
const canEditOwn = await guantr.can('edit', ['article', activeArticle]);
// -> true (condition ownerId === $ctx.userId matches)
const canEditElse = await guantr.can('edit', ['article', someoneElsesArticle]);
// -> false (condition ownerId === $ctx.userId does not match)