Toni

Gem Version Build Status Code Climate Test Coverage Inline docs

Toni enables you to create a centralized authorization rules configuration with a readable DSL, similar to declarative authorization, but not required to use with Ruby on Rails. Internally the Gem is using RSpec Matchers. You can use Toni with Sinatra and Ruby on Rails.

Installation

Add this line to your application's Gemfile:

gem 'toni'

And then execute:

$ bundle

Or install it yourself as:

$ gem install toni

Getting Started

Setup Authorization Rules

To setup the rules that your toni uses you have to create a authorization_rules.rb file e.g. in your config folder:

# Guest role gets automatically assigned if you don't have a current_user
role :guest do
  has_permission_on :books, to: :read
end

role :author do
  has_permission_on :books, to: [:create, :read, :update, :delete] do
    expect_attribute :author_id { eq(current_user.id) }
  end
end

role :admin do
  has_permission_on :books, to: [:create, :read, :update, :delete]
  has_permission_on :users, to: :delete do
    expect_attribute :id { not.eq(current_user.id) }
  end
end

Assign Roles

To provide roles it is necessary to pass a current_user that provides a role_symbols method.

class User
  def role_symbols
    [:user, :admin]
  end
end

Toni.current_user = User.new

What logic this method contains is up to you.

Sinatra

The Toni Sinatra Module provides some usefule helpers and an error handling which can be useful if you want to map not authorized errors. And there is a permitted_to method where you can pass a block that gets executed when the current user has the demanded permissions.

require "toni/sinatra"

class AuthorizationApp < Sinatra::Base
  # Register Toni Sinatra
  register Toni::Sinatra

  before do
    # Set user after authentication
    Toni.current_user = User.new
  end

  not_authorized do |e|
    # Map NotAuthorizedError to 403
    halt 403
  end

  set :show_exceptions, false

  get '/' do
    # This won't throw an exception, remove bang: false if you
    # want that the not_authorized error handler is called
    permitted_to(:read, :books, bang: false) do
      "You can read books!"
    end
  end

  get '/another_page' do
    without_authorization do
      "Hello world"
    end
  end
end

A more detailed example can be found in examples/sinatra.

Testing with RSpec

To setup Toni's RspecHelper you have to change spec_helper.rb:

require "toni/rspec_helper"
RSpec.configure { |c| c.include Toni::RSpecHelper }

Then you are able to test permissions with following matcher:

expect(user).to have_permission_on :books, to: :read
expect(user).to_not have_permission_on :books, to: :create

By default your specs are running with authorization. If you want to exclude parts or execute with a specific user you can use:

without_authorization do
  book.create
end

with_user(user) do
  book.save
end

Ruby on Rails

TODO: Write usage instructions here

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request