Permissions
You already decide who can do what in your Bouncer policies. Azu asks the same policies, on every request. A missing method means denied.
Here’s the demo’s product policy:
import { BasePolicy } from '@adonisjs/bouncer'import type User from '#models/user'import type Product from '#models/product'
export default class ProductPolicy extends BasePolicy { viewList(user: User) { return user.role !== 'customer' }
view(_user: User, _product: Product) { return true }
create(user: User) { return user.role === 'admin' }
update(user: User, _product: Product) { return user.role === 'admin' || user.role === 'staff' }
delete(user: User) { return user.role === 'admin' }
publish(user: User) { return user.role === 'admin' }
restock(user: User, _product: Product) { return user.role === 'admin' }
/** The reusable action in app/admin/actions/feature.ts */ feature(user: User, _product: Product) { return user.role === 'admin' }}What each method controls
Section titled “What each method controls”| Method | Controls |
|---|---|
viewList |
The resource in the navigation, and its list. |
view |
Opening a record’s detail page. |
create |
The New button and the create form. |
update |
The Edit button, the edit form, and actions without .ability(). |
delete |
The built-in Delete row and bulk actions. |
Your own, such as publish |
Actions and fields that name it with .ability('publish'). |
view, update, and delete receive the record. A custom method receives it for actions and for fields on edit and detail pages. On create, the field check runs before a record exists.
Hiding is a convenience
Section titled “Hiding is a convenience”Azu hides buttons, fields, and actions a user can’t use. But hiding is a convenience. The server always checks the policy, so a crafted request gets the same answer as a click.
That includes each record in a bulk action. Records the user can’t touch are skipped and reported.
Fields and actions
Section titled “Fields and actions”.ability('publish') on a field shows it only to users your policy’s publish method allows. Azu checks it with the record on edit. A field the user can’t see is never read from the request, either.
Keep sensitive attributes out of columns and title. A field’s .ability() applies to the field, while Azu sends the resource’s columns separately. Those columns can also appear on a detail page when the user has no visible fields.
On an action, .ability() names the policy method checked for each record. See Actions.
The panel’s own gate
Section titled “The panel’s own gate”Before any policy runs, a user must pass accessAdmin, the Bouncer ability in app/abilities/main.ts. See Installation.
Screens and navigation links use Bouncer abilities instead of policies. See Screens.
Fails closed
Section titled “Fails closed”Azu denies, rather than allows, when anything is missing:
- no Bouncer installed,
- no
accessAdminability, - a missing policy method,
- an ability that throws.
The reason goes to your log, never to the user. Run node ace azu:doctor to list the policy methods your resources rely on and don’t have. Troubleshooting has more.