No release in over 3 years
Low commit activity in last 3 years
Rails authorization with controllers's actions.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

>= 3.0
 Project Readme

Action Authorizer

Gem Version Build Status

Rails authorization with controllers actions.

ActionAuthorizer is a gem to authorize the controllers's actions. Designed to work with RSpec and Devise. Where each controller will have an authorizer with the same actions. Each action authorizer will return its permission result.

<% if authorized? :new %>
  <a hre="<%= new_model_path %>">New</a>
<% end %>

Getting Started

After setting up Rspec and Devise! Set up ActionAuthorizer.

  • Edit: Gemfile
gem 'action_authorizer', '~> 2.0'
  • Run
bundle install
rails generate action_authorizer:install
  • Edit: app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  ...
  before_action :authenticate_user!
  before_action :authorize!, unless: :devise_controller?
  ...
  private
  ...
  def authorize!
    unauthorize! unless authorized?
  end

  def authorized?
    ActionAuthorizer::Base.authorized?(current_user, controller_path, action_name, params.except(:controller, :action))
  end

  def unauthorize!
    if request.format.json?
      render(json: {status: 404, error: 'Not Found'}, status: :not_found)
    elsif Rails.env.production?
      render(file: Rails.root.join('public/404'), layout: false, status: :not_found)
    else
      raise(ActionController::RoutingError, "No route matches [#{request.env['REQUEST_METHOD']}] #{request.env['PATH_INFO'].inspect}")
    end
  end
end
  • Edit: spec/rails_helper.rb
require 'action_authorizer_matchers_helper'
...
RSpec.configure do |config|
  # Controllers Spec with ActionAuthorizer
  config.before :each, type: :controller do
    allow(controller).to receive(:authorize!)
  end

  # Views Spec with ActionAuthorizer
  # case rails < 3.1
  # config.before :each, type: :view do
  #   view.extend ActionAuthorizerHelper
  # end
end

Authorizing models with module

  • Run
rails generate action_authorizer:authorizer namespace/model

Authorizing models without module

  • Run
rails generate action_authorizer:authorizer model

Authorizing Account's Record or Cancellation (Optional)

  • Edit: app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  include ActionAuthorizer::Config
  ...
  before_action :authenticate_user!
  before_action :authorize!, if: :authorizer_controller?

  private

  def authorizer_controller?
    controller_path == 'devise/registrations' || !devise_controller?
  end
end
  • Edit: /app/views/devise/registrations/edit.html.erb
<% if authorized? 'devise/registrations', :cancel %>
<h3>Cancel my account</h3>

<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
<% end %>
  • Edit: /app/views/devise/shared/_links.html.erb
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
  <%= link_to "Sign up", new_registration_path(resource_name) if authorized? 'devise/registrations', :new %><br />
<% end -%>
  • Run
rails generate action_authorizer:authorizer devise/registration
  • Edit: app/authorizers/devise/registrations_authorizer.rb
class Devise::RegistrationsAuthorizer < ApplicationAuthorizer
  skip_authentication only: %i[new create]

  # Account registration page
  def new
  end

  # Account edition page
  def edit
    true
  end

  # Account registration submition
  def create
  end

  # Account edition submition
  def update
    true
  end

  # Account cancellation page
  def destroy
  end

  # Account cancellation submition
  def cancel
  end
end
  • Edit: /spec/authorizers/devise/registrations_authorizer_spec.rb
require 'rails_helper'

RSpec.describe Devise::RegistrationsAuthorizer, type: :authorizer do
  let(:guest_user) { nil }
  let(:user) { double('User') }

  describe '#new' do
    context 'when not authorize' do
      it { expect(user).to be_unauthorized(:new) }
      it { expect(guest_user).to be_unauthorized(:new) }
    end
  end

  describe '#edit' do
    context 'when authorize' do
      it { expect(user).to be_authorized(:edit) }
    end

    context 'when not authorize' do
      it { expect(guest_user).to be_unauthorized(:edit) }
    end
  end

  describe '#create' do
    context 'when not authorize' do
      it { expect(user).to be_unauthorized(:create) }
      it { expect(guest_user).to be_unauthorized(:create) }
    end
  end

  describe '#update' do
    context 'when authorize' do
      it { expect(user).to be_authorized(:update) }
    end

    describe 'not authorize' do
      it { expect(guest_user).to be_unauthorized(:update) }
    end
  end

  describe '#destroy' do
    context 'when not authorize' do
      it { expect(user).to be_unauthorized(:destroy) }
      it { expect(guest_user).to be_unauthorized(:destroy) }
    end
  end

  describe '#cancel' do
    context 'when not authorize' do
      it { expect(user).to be_unauthorized(:cancel) }
      it { expect(guest_user).to be_unauthorized(:cancel) }
    end
  end
end