Skip to content

API: Guantr.prototype.can.abstract

The can.abstract sub-method performs an abstract permission check — it returns true if any allow rule exists for the given action and resource key, without evaluating conditions or considering deny rules.

Use this for UI decisions (e.g. "should I show the Edit button?"), not for access control. For a full evaluation against a resource instance, use can(action, [resourceKey, instance]).

Signature

ts
can.abstract(
  action: string,
  resource: string,
): Promise<boolean>;

Parameters

  • action: (string) The action being checked (e.g. 'read', 'update').
  • resource: (string) The resource key to check (e.g. 'post', 'user').

Unlike can(), the resource is just a plain string (the key), not a tuple with an instance.

Returns

  • Promise<boolean>true if at least one allow rule exists for the action + resource pair. false if no allow rules are found.

What it ignores

AspectConsidered?
Allow rules (any effect: 'allow')✅ Checked
Deny rules (effect: 'deny')❌ Ignored
Conditions (matchCondition)❌ Ignored — rules with conditions count as present

The method answers: "Has any permission been granted at all for this resource type?" rather than "is this specific instance accessible right now?"

Evaluation

  1. Queries storage for all rules matching the given action and resource key.
  2. Returns true if any rule with effect: 'allow' is found.
  3. Returns false if no allow rules exist (regardless of deny rules or conditions).

Caching behavior

When the storage adapter provides a cache, results are cached with the key pattern:

text
can.abstract/${action}:${resource}

Cache misses/errors follow the same tolerance pattern as can(): errors from cache.get are swallowed (fall back to direct evaluation), errors from cache.set are swallowed (result returned uncached).

Examples

ts
await guantr.setRules((allow, deny) => {
  allow('read', 'post'); // unconditional allow
  deny('read', ['post', ({ eq, resource, literal }) => eq(resource('published'), literal(false))]); // conditional deny
  allow('update', [
    'post',
    ({ eq, resource, context }) => eq(resource('authorId'), context('userId')),
  ]); // conditional allow
});
ts
// Abstract — deny rule is ignored, condition is ignored
await guantr.can.abstract('read', 'post'); // true (allow rule exists)

// Full evaluation against a specific instance
const draftPost = { id: 1, published: false, title: 'Draft' };
await guantr.can('read', ['post', draftPost]); // false (deny matches this instance)

Conditional rule still counts as present

ts
// No unconditional 'update' allow, only conditional
await guantr.can.abstract('update', 'post'); // true (the conditional allow counts)

// But the actual instance might not match the condition:
await guantr.can('update', ['post', { id: 1, authorId: 'other' }]);
// false — condition not satisfied

No allow rules at all

ts
await guantr.can.abstract('delete', 'post'); // false (no 'delete' allow rule exists)

Contrast with can()

Behaviourcan.abstract(action, 'resource')can() / can.all / can.any
Checks allow rules
Evaluates conditions
Considers deny rules
Requires resource instance❌ (key only)
Caching keycan.abstract/${action}:${resource}can/${action}:${resourceKey}:${stableStringify(instance)}:${stableStringify(context)}
Recommended useUI hints, layout decisionsAccess control, authorization gating

Migration from v1.x

In guantr v1.x, can(action, resourceKeyString) performed an abstract check. This overload was deprecated in v1.1.0 and removed in v2.0.0. Replace with can.abstract:

ts
// v1.x (removed in v2.0.0)
await guantr.can('read', 'post');

// v2+ — use can.abstract for abstract checks
await guantr.can.abstract('read', 'post');

// v2+ — use the tuple form for full evaluation
await guantr.can('read', ['post', postInstance]);

See also

  • cannot.abstract — Negated abstract check.
  • can() — Full evaluation with conditions and deny rules.
  • can.all — Batch check: all must pass (full resource-aware evaluation like can()).
  • can.any — Batch check: any must pass (full resource-aware evaluation like can()).