Defining permissions

This guide covers the definePermissions function and the Permissions class. You will learn how to:

  • Define permissions using the resource/action pattern
  • Use prefixes to namespace permissions
  • Mark permissions as inactive or create aliases
  • Query the permission definitions at runtime

Overview

Permissions are defined as a flat resource/action map. Each resource (like product or billing) contains actions (like create, update, delete). The combination produces permission keys in resource.action format, for example product.create or billing.refund.

You define permissions once in a dedicated file and import the resulting Permissions instance wherever you need it.

Basic definition

Use definePermissions to create a Permissions instance. Each action value controls how the permission is configured:

  • true generates the permission with an auto-generated description.
  • A string uses that string as the description.
  • An object provides full control over description, inactive state, and aliases.
start/permissions.ts
import { definePermissions } from '@adonisplus/permissions'

export const permissions = definePermissions({
  product: {
    create: true,
    update: 'Update existing products',
    delete: {
      description: 'Delete products permanently',
    },
  },
  billing: {
    refund: 'Issue refunds to customers',
  },
})

This produces four permission keys: product.create, product.update, product.delete, and billing.refund. All keys are type-safe. Your editor will autocomplete them wherever a permission key is expected.

Using prefixes

Use the prefix function to namespace a group of permissions. This is useful when different parts of your application have overlapping resource names.

start/permissions.ts
import { definePermissions, prefix } from '@adonisplus/permissions'

export const permissions = definePermissions(
  prefix('admin', {
    product: { create: true, update: true, delete: true },
  }),
  {
    billing: { refund: 'Issue refunds' },
  }
)

The prefixed keys become admin:product.create, admin:product.update, and admin:product.delete. The colon separates the prefix from the resource, and the dot separates the resource from the action.

You can pass multiple definition objects to definePermissions. They are merged together into a single Permissions instance.

Aliases

Aliases let you rename permission keys without breaking existing role assignments. When a user or role has an aliased key stored in the database, the system resolves it to the canonical key automatically.

start/permissions.ts
export const permissions = definePermissions({
  product: {
    delete: {
      description: 'Delete products',
      aliases: ['product.remove'],
    },
  },
})

A role with product.remove in the database will be treated as having product.delete. This works transparently across access checks and Bouncer abilities.

Inactive permissions

Mark a permission as inactive to remove it from runtime checks without deleting it from the definition. Inactive permissions are excluded from access checks, meaning roles that have the key stored in the database will no longer receive it.

start/permissions.ts
export const permissions = definePermissions({
  product: {
    archive: {
      description: 'Archive products',
      inactive: true,
    },
  },
})

This is useful when deprecating a permission. The key remains in .keys() and .all() for reference, but it has no effect on authorization.

Querying permissions

The Permissions instance provides methods to inspect the definition at runtime. These are useful for building admin UIs where you list available permissions for role assignment.

// All permissions with metadata (key, description, inactive, aliases)
permissions.all()

// All permission keys (including inactive)
permissions.keys()

// Only active permission keys
permissions.active()

// Type-safe key validation (throws if unknown)
permissions.getKey('product.create')

// Resolve raw keys: resolves aliases, removes inactive and unknown
permissions.filterKeys(['product.remove', 'product.archive', 'unknown.key'])
// → ['product.delete']  (alias resolved, inactive and unknown removed)

Permissions instance methods

all
method

Returns all permissions as an array of objects with key, description, inactive, and aliases properties.

permissions.all()
keys
method

Returns all permission keys as strings, including inactive ones.

permissions.keys()
active
method

Returns only active permission keys.

permissions.active()
getKey
method

Returns the key as-is. Exists for compile-time type safety. Throws if the key is not defined.

permissions.getKey('product.create')
filterKeys
method

Takes raw permission strings (from the database or tokens), resolves aliases, removes inactive and unknown keys. Returns the filtered list of canonical keys.

permissions.filterKeys(rawKeys)
createAccess
method

Creates a new empty Access instance tied to this permission definition. Call access.use(rawKeys) to populate it.

const access = permissions.createAccess()
createAccessFor
method

Creates an Access instance pre-populated with the entity's resolved permissions. The entity must implement getPermissions().

const access = await permissions.createAccessFor(user)
abilities
method

Returns an object of Bouncer abilities, one per active permission key. See the Bouncer integration guide.

const abilities = permissions.abilities()
Terms & License Agreement