Roles
Roles use a bitmask stored in the rolemask column on {prefix}accounts.
Custom Roles
Define your own roles with defineRoles. It assigns sequential powers of 2 and returns a frozen object.
import { defineRoles } from "@eaccess/auth";
const Roles = defineRoles("admin", "owner", "editor", "viewer", "billing");
// { admin: 1, owner: 2, editor: 4, viewer: 8, billing: 16 }
Pass it into your auth config:
This does two things:
getRoleNames()returns your custom names instead of the built-in defaults- The admin UI reads roles from the backend, so your custom roles show up automatically
Names are preserved exactly as provided - no transformation. Maximum 31 roles (PostgreSQL INTEGER is 32-bit signed). The order matters: don't reorder or remove roles from the middle, or existing users' rolemasks will map to the wrong names.
Built-in Roles
If you don't set config.roles, the built-in AuthRole enum is used. It has 21 predefined roles (Admin, Author, Collaborator, etc.).
import { AuthRole } from "@eaccess/auth";
await req.auth.addRoleForUserBy({ email: "user@example.com" }, AuthRole.Admin | AuthRole.Editor);
Assign and Check
await req.auth.addRoleForUserBy({ email: "user@example.com" }, Roles.editor);
await req.auth.removeRoleForUserBy({ email: "user@example.com" }, Roles.editor);
const canEdit = await req.auth.hasRole(Roles.editor);
const isAdmin = await req.auth.isAdmin();
const names = req.auth.getRoleNames();
Standalone Role Functions
For use outside of Express routes:
import { addRoleToUser, removeRoleFromUser, setUserRoles, getUserRoles } from "@eaccess/auth";
await addRoleToUser(authConfig, { email: "user@example.com" }, Roles.editor);
await removeRoleFromUser(authConfig, { email: "user@example.com" }, Roles.editor);
await setUserRoles(authConfig, { email: "user@example.com" }, Roles.admin | Roles.owner);
const mask = await getUserRoles(authConfig, { email: "user@example.com" });
Why Bitmasks
- Single integer column, no join tables
- Fast bitwise checks
- Easy to combine:
Roles.admin | Roles.editorgives a user both roles - Easy to check:
(rolemask & Roles.admin) === Roles.admin