DEV Community

Tejas Kadam
Tejas Kadam

Posted on

I built a tiny permission checker so I'd stop writing "if user.role === admin" everywhere

Second small package in a series I started last week (first one was rule-lite, a JSON rule evaluator). This one's about permissions.

Here's the thing about "can this user edit this invoice" - it sounds like a yes/no role question but it almost never is. It's really "can this user edit this invoice, AND do they own it, AND is it under some approval limit." Plain role-based permissions handle the first half fine. Then the second half turns into random if-checks scattered across the codebase, and six months later nobody remembers why that one check exists.

So I made entitlement-lite. Small idea: roles hold permissions like normal, but any permission can also carry an optional condition.

const engine = new EntitlementEngine([
  {
    name: 'contributor',
    permissions: [{
      action: 'edit',
      resource: 'invoice',
      condition: { field: 'resource.ownerId', operator: 'eq', value: 'u1' }
    }]
  }
]);

engine.can(subject, 'edit', 'invoice', { resource: { ownerId: 'u1' } }); // true
Enter fullscreen mode Exit fullscreen mode

No condition on a permission? It's just a normal role check. Condition present? It gets evaluated at request time using rule-lite (the package I put out last week). I didn't want to write a second rule engine just for this, so it reuses the first one.

Also supports wildcards so you're not stuck writing { action: 'view' }, { action: 'edit' }, { action: 'delete' }... for an admin role - { action: '*', resource: '*' } covers it.

It's deliberately not trying to be OPA or Casbin. Those are the right call for big multi-service auth systems. This is for the much more common case: one app, a handful of roles, a few conditions that need actual logic instead of hardcoded ifs.

Repo: https://github.com/tejas821/entitlement-lite
npm: https://www.npmjs.com/package/entitlement-lite

If you've built something similar or have opinions on the API (especially the wildcard matching or how conditions merge into context), I'd like to hear it.

Top comments (0)