SkillAgentSearch skills...

Authority

*CURRENTLY UNMAINTAINED*. Authority helps you authorize actions in your Rails app. It's ORM-neutral and has very little fancy syntax; just group your models under one or more Authorizer classes and write plain Ruby methods on them.

Install / Use

/learn @nathanl/Authority
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Authority (CURRENTLY UNMAINTAINED)

Authority is now unmaintained. Users who have installed it decided to trust me, and I'm not comfortable transferring that trust to someone else on their behalf. However, if you'd like to fork it, feel free.

Gary Foster has provided a script to migrate to Pundit.

Overview

Authority helps you authorize actions in your Ruby app. It's ORM-neutral and has very little fancy syntax; just group your models under one or more Authorizer classes and write plain Ruby methods on them.

Authority will work fine with a standalone app or a single sign-on system. You can check roles in a database or permissions in a YAML file. It doesn't care! What it does do is give you an easy way to organize your logic and handle unauthorized actions.

If you're using it with Rails controllers, it requires that you already have some kind of user object in your application, accessible via a method like current_user (configurable).

Gem Version Build Status Code Climate Dependency Status Join the chat at https://gitter.im/nathanl/authority

Contents

<ul> <li><a href="#overview">Overview</a></li> <li><a href="#flow_of_authority">The flow of Authority</a></li> <li><a href="#installation">Installation</a></li> <li><a href="#defining_your_abilities">Defining Your Abilities</a></li> <li><a href="#wiring_it_together">Wiring It Together</a> <ul> <li><a href="#users">Users</a></li> <li><a href="#models">Models</a></li> <li><a href="#authorizers">Authorizers</a> <ul> <li><a href="#passing_options">Passing Options</a></li> <li><a href="#default_methods">Default methods</a></li> <li><a href="#testing_authorizers">Testing Authorizers</a></li> </ul></li> <li><a href="#controllers">Controllers</a></li> <li><a href="#views">Views</a></li> </ul></li> <li><a href="#the_generic_can">The Generic `can?`</a> <li><a href="#security_violations_and_logging">Security Violations &amp; Logging</a></li> <li><a href="#credits">Credits</a></li> <li><a href="#contributing">Contributing</a></li> </ul> <a name="overview"> ## Overview

Using Authority, you have:

  • Broad, class-level rules. Examples:
    • "Basic users cannot delete any Widget."
    • "Only admin users can create Offices."
  • Fine-grained, instance-level rules. Examples:
    • "Management users can only edit schedules with date ranges in the future."
    • "Users can't create playlists more than 20 songs long unless they've paid."
  • A clear syntax for permissions-based views. Examples:
    • link_to 'Edit Widget', edit_widget_path(@widget) if current_user.can_update?(@widget)
    • link_to 'Keelhaul Scallywag', keelhaul_scallywag_path(@scallywag) if current_user.can_keelhaul?(@scallywag)
  • Graceful handling of access violations: by default, it displays a "you can't do that" screen and logs the violation.
  • Minimal effort and mess.

Most importantly, you have total flexibility: Authority does not constrain you into using a particular scheme of roles and/or permissions.

Authority lets you control access based on:

  • Roles in your app's database (rolify makes this easy)
  • Roles in a separate, single-sign-on app
  • Users' points (like StackOverflow)
  • Time and date
  • Weather, stock prices, vowels in the user's name, or anything else you can check with Ruby

All you have to do is define the methods you need on your authorizers. You have all the flexibility of normal Ruby classes.

You make the rules; Authority enforces them.

<a name="flow_of_authority"> ## The flow of Authority

Authority encapsulates all authorization logic in Authorizer classes. Want to do something with a model? Ask its authorizer.

You can specify a model's authorizer one of two ways:

  • specify the class itself: authorizer = SomeAuthorizer
  • specify the class's name: authorizer_name = 'SomeAuthorizer' (useful if the constant isn't yet loaded)

If you don't specify an authorizer, the model will:

  • Look for an authorizer with its name. Eg, Comment will look for CommentAuthorizer.
  • If that's not found, it will use ApplicationAuthorizer.

Models that have the same authorization rules should use the same authorizer. In other words, if you would write the exact same methods on two models to determine who can create them, who can edit them, etc, then they should use the same authorizer.

Some example groupings:

     Simplest case                Logical groups                                 Most granular

  ApplicationAuthorizer        ApplicationAuthorizer                         ApplicationAuthorizer
           +                             +                                             +
           |                    +--------+-------+                 +-------------------+-------------------+
           |                    +                +                 +                   +                   +
           |             BasicAuthorizer   AdminAuthorizer  CommentAuthorizer  ArticleAuthorizer  EditionAuthorizer
           |                    +                +                 +                   +                   +
   +-------+-------+            +-+       +------+                 |                   |                   |
   +       +       +              +       +      +                 +                   +                   +
Comment Article Edition        Comment Article Edition          Comment             Article             Edition

The authorization process generally flows like this:

               current_user.can_create?(Article)                 # You ask this question, and the user
                           +                                     # automatically asks the model...
                           |
                           v
             Article.creatable_by?(current_user)                 # The model automatically asks
                           +                                     # its authorizer...
                           |
                           v
           AdminAuthorizer.creatable_by?(current_user)           # *You define this method.*
                           +                                     # If you don't, the inherited one
                           |                                     # calls `default`...
                           v
    AdminAuthorizer.default(:creatable, current_user)            # *You define this method.*
                                                                 # If you don't, it will use the one
                                                                 # inherited from ApplicationAuthorizer.
                                                                 # (Its parent, Authority::Authorizer,
                                                                 # defines the method as `return false`.)

If the answer is false and the original caller was a controller, this is treated as a SecurityViolation. If it was a view, maybe you just don't show a link.

The authorization process for instances is different in that it calls the instance's default method before calling the class default method. This allows you to define default behaviour that requires access to the model instance to be determined (eg, assume any action on a blog post is allowed if that post is marked 'wiki').

(Diagrams made with AsciiFlow)

<a name="installation"> ## Installation

Starting from a clean commit status, add authority to your Gemfile, then bundle.

If you're using Rails, run rails g authority:install. Otherwise, pass a block to Authority.configure with configuration options somewhere when your application boots up.

<a name="defining_your_abilities"> ## Defining Your Abilities

Edit config/initializers/authority.rb. That file documents all your options, but one of particular interest is config.abilities, which defines the verbs and corresponding adjectives in your app. The defaults are:

config.abilities =  {
  :create => 'creatable',
  :read   => 'readable',
  :update => 'updatable',
  :delete => 'deletable'
}

This option determines what methods are added to your users, models and authorizers. If you need to ask user.can_deactivate?(Satellite) and @satellite.deactivatable_by?(user), add :deactivate => 'deactivatable' to the hash.

<a name="wiring_it_together"> ## Wiring It Together <a name="users"> ### Users
# Whatever class represents a logged-in user in your app
class User
  # Adds `can_create?(resource)`, etc
  include Authority::UserAbilities
...
end
<a name="models"> ### Models
class Article
  # Adds `creatable_by?(user)`, etc
  include Authority::Abilities

  # Without this, 'ArticleAuthorizer' is assumed;
  # if that doesn't exist, 'ApplicationAuthorizer'
  self.authorizer_name = 'AdminAuthorizer'
  ...
end
<a name="authorizers"> ### Authorizers

Add your authorizers under app/authorizers, subclassing the generated ApplicationAuthorizer.

These are where your actual authorization logic goes. Here's how it works:

  • Instance methods answer questions about model instanc

Related Skills

View on GitHub
GitHub Stars1.2k
CategoryDevelopment
Updated3d ago
Forks68

Languages

Ruby

Security Score

100/100

Audited on Mar 25, 2026

No findings