Skip to content

Instantly share code, notes, and snippets.

@roman
Created February 1, 2010 23:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save roman/292160 to your computer and use it in GitHub Desktop.
Save roman/292160 to your computer and use it in GitHub Desktop.
- # app/views/posts/_post.html
%h1= post.title
...
%p Actions:
%ul
- # checking the authorizations on the view...
%li= edit_post_path(post) if current_user.can?(:update, post)
%li= post_path(post) if current_user.can?(:read, post)
# lib/walruz/policies.rb
# The core of the walruz framework, this will be the authorization file, here
# you can manage the authorization rules of each of the resources you want to
# check authorizations in.
module Policies
UserReadPolicy = any(ActorIsSubject, RolePolicy[:admin])
# This will be a policy that grabs the post.owner and invoke the following policies
# For now this is just the author of the post or an user with the Admin role
PostReadPolicy = any(ActorIsSubject,
RolePolicy[:admin]).for_subject(:owner)
# This is the same as the read policy, so we don't need to specify it again
PostCreatePolicy = PostReadPolicy
PostUpdatePolicy = any(ActorIsSubject,
RolePolicy[:editor],
RolePolicy[:admin]).for_subject(:owner)
end
# app/models/post.rb
# Post is an object that has some authorization logic, so that's why
# it is including the Walruz::Subject interface, after requiring the
# walruz/policies, you can assign each policy to a label (in this case,
# the labels will be the CRUD actions)
# NOTE: this labels are not related in anything to the method names, this could
# be easily named :foo, :bar, :whatever
require 'walruz/policies'
class Post < ActiveRecord::Base
include Walruz::Subject
belongs_to :author, :class_name => 'User'
check_authorizations :create => Policies::PostCreatePolicy,
:read => Policies::PostReadPolicy,
:update => Policies::PostUpdatePolicy,
:delete => Policies::PostDestroyPolicy
end
# app/controllers/posts_controller.rb
# You can use the check_authorization! before_filters to manage
# the authorization of a resource, if the authorization requirements are not
# met, a Walruz::NotAuthorized exception will be thrown.
# This will cause the method 'unauthorized' to be called on the ApplicationController
class PostsController
# user must be authenticated an accessible via `current_user` method
before_filter :check_authenticated_user
# must get the subject before doing any authorization at all
before_filter :get_post
# requires `current_user` and `@post` or `self.post` to work
before_filter check_authorization!(:read, :post), :only => [:show]
before_filter check_authorization!(:update, :post), :only => [:edit, :update]
def get_post
# [edit, update, show] actions
@post = if params[:id]
Post.find(params[:id])
# [create action]
elsif params[:post]
params[:post].merge!(:author => current_user)
Post.new(params[:post])
else
Post.new(:author => @current_user)
end
end
protected :get_post
def edit
end
def update
end
def show
end
end
# lib/walruz/policies/role_policy.rb
class RolePolicy
cattr_reader :created_roles
@created_roles = []
def self.[](role_name)
unless self.created_roles.key?(role_name)
self.created_roles[role_name] = self.__create_policy_for_role(role_name)
end
self.created_roles[role_name]
end
protected
def self.__create_policy_for_role(role_name)
# Here we are creating an anonymous class extending from Walruz::Policy
# Walruz::Policy will hold a method called `authorize!` that will receive
# the `actor` (normally `current_user`) and the `subject` (in this case a post).
# This method should return a true if the `actor` fulfils the policy on the `subject`
walruz_policy = Class.new(Walruz::Policy) do
# This method will add an identifier to the Policy Class
# so you can access easily via `satisfies?` method
set_policy_label(:"#{role_name}_role_policy")
# We don't need subjects for this, the actor roles is the important thing
def authorize!(actor, _)
actor.role == role_name.to_s
end
end
walruz_policy
end
end
# app/models/user.rb
# Given that the user model is the one who represents a user doing actions on subjects
# this will have the Walruz::Actor module included
class User < ActiveRecord::Base
include Walruz::Actor
ROLES = ['admin', 'editor'].freeze
has_many :posts
validates_inclusion_of :role, :in => ROLES
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment