Skip to content
This repository has been archived by the owner on Nov 19, 2019. It is now read-only.

Commit

Permalink
Add notes to documentaion before Rails (controller) specific components.
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Keele committed Apr 10, 2013
1 parent d6dcc66 commit f22b299
Showing 1 changed file with 24 additions and 18 deletions.
42 changes: 24 additions & 18 deletions README.markdown
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Authority

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.
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.

It requires that you already have some kind of user object in your application, accessible from all controllers and views via a method like `current_user` (configurable).
If you're using controller integration, it requires that you already have some kind of user object in your application, accessible from all controllers and views via a method like `current_user` (configurable).

[![Build Status](https://secure.travis-ci.org/nathanl/authority.png?branch=master)](http://travis-ci.org/nathanl/authority)
[![Code Climate](https://codeclimate.com/github/nathanl/authority.png)](https://codeclimate.com/github/nathanl/authority)
Expand Down Expand Up @@ -40,10 +40,10 @@ It requires that you already have some kind of user object in your application,

Using Authority, you have:

- Broad, **class-level** rules. Examples:
- Broad, **class-level** rules. Examples:
- "Basic users cannot delete any Widget."
- "Only admin users can create Offices."
- Fine-grained, **instance-level** rules. Examples:
- 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:
Expand All @@ -54,15 +54,15 @@ Using Authority, you have:

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:
Authority lets you control access based on:

- Roles in your app's database ([rolify](http://github.com/EppO/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.
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.

Expand All @@ -80,7 +80,7 @@ You can specify a model's authorizer using the class method `authorizer_name=`.

Some example groupings:

Simplest case Logical groups Most granular
Simplest case Logical groups Most granular

ApplicationAuthorizer ApplicationAuthorizer ApplicationAuthorizer
+ + +
Expand All @@ -106,8 +106,8 @@ The authorization process generally flows like this:
+ # 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
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`.)
Expand All @@ -119,7 +119,9 @@ If the answer is `false` and the original caller was a controller, this is treat
<a name="installation">
## Installation

Starting from a clean commit status, add `authority` to your Gemfile, `bundle`, then `rails g authority:install`.
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](https://github.com/nathanl/authority/blob/master/lib/generators/templates/authority_initializer.rb) somewhere when your application boots up.

<a name="defining_your_abilities">
## Defining Your Abilities
Expand All @@ -145,7 +147,7 @@ This option determines what methods are added to your users, models and authoriz

```ruby
# Whatever class represents a logged-in user in your app
class User
class User
# Adds `can_create?(resource)`, etc
include Authority::UserAbilities
...
Expand Down Expand Up @@ -195,13 +197,13 @@ class ScheduleAuthorizer < ApplicationAuthorizer
end

# undefined; calls `ScheduleAuthorizer.default(:updatable, user)`
ScheduleAuthorizer.updatable_by?(user)
ScheduleAuthorizer.updatable_by?(user)
```

As you can see, you can specify different logic for every method on every model, if necessary. On the other extreme, you could simply supply a [default method](#default_methods) that covers all your use cases.

<a name="passing_options">
#### Passing Options
#### Passing Options

Any options you pass when checking permissions will be passed right up the chain. One use case for this would be if you needed an associated instance in order to do a class-level check. For example:

Expand Down Expand Up @@ -238,7 +240,7 @@ class ApplicationAuthorizer < Authority::Authorizer
def self.default(able, user)
has_role_granting?(user, able) || user.admin?
end

protected

def has_role_granting(user, able)
Expand All @@ -264,7 +266,7 @@ One nice thing about putting your authorization logic in authorizers is the ease
# An authorizer shared by several admin-only models
describe AdminAuthorizer do

before :each do
before :each do
@user = FactoryGirl.build(:user)
@admin = FactoryGirl.build(:admin)
end
Expand Down Expand Up @@ -302,6 +304,8 @@ end
<a name="controllers">
### Controllers

If you're using Rails, ActionController support will be loaded in through a Railtie. Otherwise, you'll want to integrate it into your framework yourself. [Authority's controller](https://github.com/nathanl/authority/blob/master/lib/authority/controller.rb) is an excellent starting point.

Anytime a controller finds a user attempting something they're not authorized to do, a [Security Violation](#security_violations_and_logging) will result. Controllers get two ways to check authorization:

- `authorize_actions_for Llama` protects multiple controller actions with a `before_filter`, which performs a **class-level** check. If the current user is never allowed to delete a `Llama`, they'll never even get to the controller's `destroy` method.
Expand Down Expand Up @@ -329,7 +333,7 @@ class LlamasController < ApplicationController
# Check class-level authorizations before all actions except :create
# Also, to authorize this controller's 'neuter' action, ask whether `current_user.can_update?(Llama)`
authorize_actions_for Llama, :except => :create, :actions => {:neuter => :update},

# To authorize this controller's 'breed' action, ask whether `current_user.can_create?(Llama)`
# To authorize its 'vaporize' action, ask whether `current_user.can_delete?(Llama)`
authority_actions :breed => 'create', :vaporize => 'delete'
Expand All @@ -338,7 +342,7 @@ class LlamasController < ApplicationController

def edit
@llama = Llama.find(params[:id])
authorize_action_for(@llama) # Check to see if you're allowed to edit this llama. failure == SecurityViolation
authorize_action_for(@llama) # Check to see if you're allowed to edit this llama. failure == SecurityViolation
end

def update
Expand Down Expand Up @@ -418,7 +422,9 @@ Use this very sparingly, and consider it a [code smell](http://en.wikipedia.org/
<a name="security_violations_and_logging">
## Security Violations & Logging

If you're using Authority's view helpers, users should only see links for actions they're authorized to take. If a user deliberately tries to access a restricted resource (for instance, by typing the URL directly), Authority raises and rescues an `Authority::SecurityViolation`.
If you're using Authority's `ActiveController` integration or have used it as a template for your own, your application will handle unauthorized requests with `403 Forbidden` automatically.

If you use Authority to [conditionally render links](#security_violations_and_logging), users will only see links for actions they're authorized to take. If a user deliberately tries to access a restricted resource (for instance, by typing the URL directly), Authority raises and rescues an `Authority::SecurityViolation`.

When it rescues the exception, Authority calls whatever controller method is specified by your `security_violation_handler` option, handing it the exception. The default handler is `authority_forbidden`, which Authority mixes in to your `ApplicationController`. It does the following:

Expand Down

0 comments on commit f22b299

Please sign in to comment.