module Permissify::Controller

Optional Rails integration. It adds nothing to the core and imposes no runtime dependency — ‘require “permissify/rails”` only when a Rails app wants it, then:

class ApplicationController < ActionController::Base
  include Permissify::Controller
  verify_permissify_authorized   # fail loud if an action forgot to authorize
end

class ContactsController < ApplicationController
  def show
    @contact = permissify_authorize(Contact.find(params[:id]))   # raises on deny
  end

  def index
    @contacts = permissify_scope(Contact.all)                    # DB-level narrowing
  end
end

The names are deliberately distinct from Pundit’s (‘authorize`, `policy_scope`, `verify_authorized`) so both can run side by side during a shadow migration —see the Pundit-eradication plan.

Public Class Methods

included(base) click to toggle source
# File lib/permissify/rails.rb, line 28
def self.included(base)
  base.extend(ClassMethods)
end

Public Instance Methods

permissify_actor() click to toggle source

The subject under authorization. Defaults to current_user; override to authorize something else (an API token, an org membership, …).

# File lib/permissify/rails.rb, line 47
def permissify_actor
  current_user
end
permissify_authorize(resource, action: action_name, resource_key: nil, environment: nil) click to toggle source

Enforce authorization for resource. Returns resource on allow so it can wrap an assignment; raises Permissify::NotAuthorized on deny (rescue it in the host, e.g. rescue_from Permissify::NotAuthorized).

action

defaults to the controller action_name

resource_key

defaults to an inferred key (see permissify_resource_key)

# File lib/permissify/rails.rb, line 63
def permissify_authorize(resource, action: action_name, resource_key: nil, environment: nil)
  @_permissify_authorized = true
  Permissify.authorize!(
    actor: permissify_actor,
    action: action.to_sym,
    resource: resource,
    resource_key: resource_key || permissify_resource_key(resource),
    environment: environment || permissify_environment
  )
  resource
end
permissify_environment() click to toggle source

Request/tenant context passed to facts as environment. Override to supply tenant ids, feature flags, request metadata, etc. Defaults to empty.

# File lib/permissify/rails.rb, line 53
def permissify_environment
  {}
end
permissify_scope(relation, action: action_name, resource_key: nil, environment: nil) click to toggle source

Narrow relation to what the actor may see, at the database level. Delegates to Permissify.authorized_scope and raises Permissify::NoScope when the resource has no registered scope (it never returns every row by default).

# File lib/permissify/rails.rb, line 78
def permissify_scope(relation, action: action_name, resource_key: nil, environment: nil)
  @_permissify_scoped = true
  Permissify.authorized_scope(
    actor: permissify_actor,
    action: action.to_sym,
    relation: relation,
    resource_key: resource_key || permissify_resource_key(relation),
    environment: environment || permissify_environment
  )
end