Skip to content

API Reference ​

createPermission(config) ​

Creates a permission instance that exposes middleware methods and helper namespaces.

ts
import { createPermission, prismaAdapter } from '@actinode/express-permission'

const permission = createPermission({
  adapter: prismaAdapter(prisma),
  getUserId: (req) => req.user?.id,
})

Config options ​

OptionTypeDefaultDescription
adapterPermissionAdapter—Required. The database adapter.
getUserId(req: Request) => string | undefinedreq.user?.idExtract the user ID from the request. Used by all middleware methods.

Middleware methods ​

All middleware methods return an Express RequestHandler. Attach them directly to routes.

permission.can(permissionName) ​

Passes if the user holds the given permission (direct, via role, or via group).

ts
app.get('/posts', permission.can('view-posts'), handler)
ParamTypeDescription
permissionNamestringThe permission to check.

permission.hasRole(roleName) ​

Passes if the user holds the given role.

ts
app.delete('/users/:id', permission.hasRole('admin'), handler)
ParamTypeDescription
roleNamestringThe role to check.

permission.canAny(permissionNames) ​

Passes if the user holds at least one of the given permissions.

ts
app.put('/posts/:id', permission.canAny(['edit-posts', 'manage-posts']), handler)
ParamTypeDescription
permissionNamesstring[]At least one must be held.

permission.canAll(permissionNames) ​

Passes if the user holds every listed permission.

ts
app.post('/posts/:id/publish', permission.canAll(['edit-posts', 'publish-posts']), handler)
ParamTypeDescription
permissionNamesstring[]All must be held.

Error responses ​

ConditionStatusBody
No userId from getUserId401{ "error": "Unauthorized", "message": "User not authenticated" }
Check fails403{ "error": "Forbidden", "message": "..." }

assign namespace ​

permission.assign.role(userId, roleName) ​

Assigns a role to a user. Creates the role if it does not exist. No-op if already assigned.

ts
await permission.assign.role(userId, 'admin')

permission.assign.permission(userId, permissionName) ​

Assigns a direct permission to a user. Creates the permission if it does not exist. No-op if already assigned.

ts
await permission.assign.permission(userId, 'edit-posts')

permission.assign.group(userId, groupName) ​

Assigns a permission group to a user. Throws PermissionError if the group does not exist.

ts
await permission.assign.group(userId, 'content-managers')

revoke namespace ​

permission.revoke.role(userId, roleName) ​

Removes a role from a user. Throws PermissionError if the role does not exist.

ts
await permission.revoke.role(userId, 'editor')

permission.revoke.permission(userId, permissionName) ​

Removes a direct permission from a user. Throws PermissionError if the permission does not exist.

ts
await permission.revoke.permission(userId, 'delete-posts')

check namespace ​

All check methods return Promise<boolean>.

permission.check.can(userId, permissionName) ​

Returns true if the user holds the permission via any vector (direct, role, or group).

ts
const allowed = await permission.check.can(userId, 'edit-posts')

permission.check.hasRole(userId, roleName) ​

Returns true if the user holds the given role.

ts
const isAdmin = await permission.check.hasRole(userId, 'admin')

permission.check.canAny(userId, permissionNames) ​

Returns true if the user holds at least one of the permissions.

ts
const canEdit = await permission.check.canAny(userId, ['edit-posts', 'manage-posts'])

permission.check.canAll(userId, permissionNames) ​

Returns true if the user holds every listed permission.

ts
const canPublish = await permission.check.canAll(userId, ['edit-posts', 'publish-posts'])

get namespace ​

permission.get.roles(userId) ​

Returns all role names assigned to the user.

ts
const roles = await permission.get.roles(userId)
// ['admin', 'editor']

Returns Promise<string[]>.

permission.get.permissions(userId) ​

Returns all direct permission names assigned to the user (not those inherited via roles or groups).

ts
const perms = await permission.get.permissions(userId)
// ['edit-posts', 'view-drafts']

Returns Promise<string[]>.

permission.get.groups(userId) ​

Returns all group names assigned to the user.

ts
const groups = await permission.get.groups(userId)
// ['content-managers']

Returns Promise<string[]>.


groups namespace ​

permission.groups.create(name, permissions) ​

Creates (or replaces) a permission group with the given permission strings.

ts
await permission.groups.create('content-managers', [
  'view-posts',
  'edit-posts',
  'publish-posts',
])
ParamTypeDescription
namestringGroup name.
permissionsstring[]Permission strings to include in the group. Replaces existing list on update.

permission.groups.assign(userId, groupName) ​

Assigns a group to a user. Throws PermissionError if the group does not exist.

ts
await permission.groups.assign(userId, 'content-managers')

TypeScript types ​

ts
interface PermissionConfig {
  adapter:     PermissionAdapter
  getUserId?:  (req: Request) => string | undefined
}

interface PermissionAdapter {
  assignRole(userId: string, roleName: string): Promise<void>
  revokeRole(userId: string, roleName: string): Promise<void>
  getRoles(userId: string): Promise<string[]>
  hasRole(userId: string, roleName: string): Promise<boolean>

  assignPermission(userId: string, permissionName: string): Promise<void>
  revokePermission(userId: string, permissionName: string): Promise<void>
  getPermissions(userId: string): Promise<string[]>

  assignGroup(userId: string, groupName: string): Promise<void>
  getGroups(userId: string): Promise<string[]>
  createGroup(name: string, permissions: string[]): Promise<void>

  can(userId: string, permissionName: string): Promise<boolean>
  canAny(userId: string, permissionNames: string[]): Promise<boolean>
  canAll(userId: string, permissionNames: string[]): Promise<boolean>
}

type PermissionMiddleware = (req: Request, res: Response, next: NextFunction) => Promise<void>

interface PermissionInstance {
  can(permissionName: string): PermissionMiddleware
  hasRole(roleName: string): PermissionMiddleware
  canAny(permissionNames: string[]): PermissionMiddleware
  canAll(permissionNames: string[]): PermissionMiddleware

  assign: AssignNamespace
  revoke: RevokeNamespace
  check:  CheckNamespace
  get:    GetNamespace
  groups: GroupsNamespace
}

class PermissionError extends Error {
  code: 'NOT_FOUND' | 'UNAUTHORIZED' | 'UNAUTHENTICATED'
}

prismaAdapter(prisma) ​

Creates a Prisma-backed adapter.

ts
import { prismaAdapter } from '@actinode/express-permission'

const adapter = prismaAdapter(prisma)

Requires the six models (Role, Permission, PermissionGroup, UserRole, UserPermission, UserGroup) to be present in your Prisma schema. See Getting Started for the full schema.


mongooseAdapter(models) ​

Creates a Mongoose-backed adapter.

ts
import { mongooseAdapter } from '@actinode/express-permission'
import type { MongooseModels } from '@actinode/express-permission'

const adapter = mongooseAdapter(models)

models must satisfy the MongooseModels interface — pass your six Mongoose model instances. See Getting Started for the full setup.

Released under the MIT License.