Permissions Roles, permissions, and policies for NetPress
NetPressv0.1.7 Permissionsv0.2.3 Docsv0.2.2
Overview Installation Policies Auth Guard
Authorization

Policies

Policies encapsulate resource-specific authorization rules. They are ordinary classes whose methods receive the current user and the resource in question, and return (or resolve) a boolean.

Defining A Policy

export default class PostPolicy {
  async view(user, post) {
    return post.status === 'published' || post.userId === user.id;
  }

  async update(user, post) {
    return user.id === post.userId;
  }

  async delete(user, post) {
    return user.hasRole('admin');
  }
}

Each method name maps to an ability. When authorization is asked for update against a Post, the registered policy's update method is called.

Registering Policies

import { registerPolicy } from '@admicaa/netpress-permissions';
import Post from '../models/Post.js';
import PostPolicy from './policies/PostPolicy.js';

registerPolicy(Post, PostPolicy);

You can also register a bulk map:

import { registerPolicies } from '@admicaa/netpress-permissions';

registerPolicies({
  Post: PostPolicy,
  Comment: CommentPolicy,
});

The key can be a class, a class name, or any string the framework uses to identify the resource (for example, a morph alias).

Where To Register

The tidiest place is a dedicated service provider:

import { ServiceProvider } from '@admicaa/netpress';
import { registerPolicy } from '@admicaa/netpress-permissions';
import Post from '../models/Post.js';
import PostPolicy from './policies/PostPolicy.js';

export default class AuthServiceProvider extends ServiceProvider {
  async boot() {
    registerPolicy(Post, PostPolicy);
  }
}

Providers run at application boot so the policies are available before any request reaches a controller.

Consuming Policies

Anywhere can() is called with a resource, policies are consulted first:

import { can } from '@admicaa/netpress-permissions';

await user.can('update', post);                // via HasPermissions trait
await can(user, 'update', post);               // core helper
await AuthGuard.can('update', 'id');      // route middleware

If the method is missing from the policy, authorization falls through to the user's role/permission graph, letting you mix policies and permissions in the same app without ceremony.

Returning Reasons

Policies can throw or return enriched objects, but authorization only inspects their truthy/falsy status. If you need to surface reasons for failure, throw a custom exception from inside the policy and catch it in your controller.

Inspecting Registered Policies

import { listPolicies, resolvePolicy } from '@admicaa/netpress-permissions';

listPolicies();            // [[resource, PolicyClass], ...]
resolvePolicy(Post);       // PolicyClass or null

Both methods are useful in dev-only dashboards and tests.

Resetting Policies

resetPolicies() clears the registered policy map. Call it in test teardown when you need to isolate policy state between suites.