[](https://badge.fury.io/rb/action_policy)
[](https://travis-ci.org/palkan/action_policy)
[](https://actionpolicy.evilmartians.io)
# ActionPolicy
Authorization framework for Ruby and Rails applications.
Composable. Extensible. Performant.
📑 [Documentation](https://actionpolicy.evilmartians.io)
## Resources
- RubyRussia, 2019 "Welcome, or access denied?" talk ([video](https://www.youtube.com/watch?v=y15a2g7v8i0) [RU], [slides](https://speakerdeck.com/palkan/rubyrussia-2019-welcome-or-access-denied))
- Seattle.rb, 2019 "A Denial!" talk ([slides](https://speakerdeck.com/palkan/seattle-dot-rb-2019-a-denial))
- RailsConf, 2018 "Access Denied" talk ([video](https://www.youtube.com/watch?v=NVwx0DARDis), [slides](https://speakerdeck.com/palkan/railsconf-2018-access-denied-the-missing-guide-to-authorization-in-rails))
## Integrations
- GraphQL Ruby ([`action_policy-graphql`](https://github.com/palkan/action_policy-graphql))
## Installation
Add this line to your application's `Gemfile`:
```ruby
gem "action_policy", "~> 0.4.0"
```
And then execute:
$ bundle
## Usage
Action Policy relies on resource-specific policy classes (just like [Pundit](https://github.com/varvet/pundit)).
First, add an application-specific `ApplicationPolicy` with some global configuration to inherit from:
```ruby
class ApplicationPolicy < ActionPolicy::Base
end
```
This may be done with `rails generate action_policy:install` generator.
Then write a policy for a resource. For example:
```ruby
class PostPolicy < ApplicationPolicy
# everyone can see any post
def show?
true
end
def update?
# `user` is a performing subject,
# `record` is a target object (post we want to update)
user.admin? || (user.id == record.user_id)
end
end
```
This may be done with `rails generate action_policy:policy Post` generator.
Now you can easily add authorization to your Rails\* controller:
```ruby
class PostsController < ApplicationController
def update
@post = Post.find(params[:id])
authorize! @post
if @post.update(post_params)
redirect_to @post
else
render :edit
end
end
end
```
\* See [Non-Rails Usage](docs/non_rails.md) on how to add `authorize!` to any Ruby project.
When authorization is successful (i.e., the corresponding rule returns `true`), nothing happens, but in case of authorization failure `ActionPolicy::Unauthorized` error is raised.
There is also an `allowed_to?` method which returns `true` or `false`, and could be used, in views, for example:
```erb
<% @posts.each do |post| %>