-
Notifications
You must be signed in to change notification settings - Fork 18
V0.0.3
randx edited this page Aug 27, 2011
·
2 revisions
gem install six
class BookRules
# All authorization works on objects with method 'allowed'
# No magic behind the scene
# You can put this method to any class or object you want
# It should always return array
# And be aready to get nil in args
def self.allowed(author, book)
rules = []
# good practice is to check for object type
return rules unless book && book.instance_of?(Book)
rules << :read_book if book.published?
rules << :edit_book if author && author.id == book.author_id
# you are free to write any conditions you need
if author && author.id == book.author_id && book.is_approved? # ....etc...
rules << :publis_book
end
rules
end
end
# Add rules to namespace ':book' & global namespace
Six.add_pack(:book, BookRules) # true
Six.allowed? :read_book, nil, nil # false
Six.allowed? :read_book, nil, published_book # true
Six.allowed? :edit_book, nil, nil # false
Six.allowed? :edit_book, author, author.books.first # true
# Controller
class BooksController < ApplicationController
before_filter :add_abilities
before_filter :load_author
def show
@book = Book.find(params[:id])
head(404) and return unless allowed?(:read_book, nil, @book)
end
def edit
@book = Book.find(params[:id])
head(404) and return unless allowed?(:edit_book, @author, @book)
end
protected
def add_abilities
Six.add_pack(:book, Book)
end
def allowed?(action, object, subject)
Six.allowed?(action, object, subject)
end
def load_author
@author = Author.find_by_id(params[:author_id])
end
end
# Model
class Book < ActiveRecord::Base
belongs_to :author
def self.allowed(object, subject)
rules = []
return rules unless book && book.instance_of?(Book)
rules << :read_book if subject.public?
rules << :edit_book if object && object.id == subject.author_id
rules
end
end
# Helper
module ApplicationHelper
def can?(action, object, subject)
Six.allowed?(action, object, subject)
end
end
# View
link_to 'Edit', edit_book_path(book) if can?(:edit_book, @author, book)
class BookRules
def self.allowed(author, book)
[:read_book, :edit_book, :publis_book]
end
end
class CarRules
def self.allowed(driver, car)
[:drive, :sell]
end
end
# add packs
Six.add_pack(:book, BookRules) # true
Six.add_pack(:car, CarRules) # true
Six.add_pack(:ufo, nil) # false
Six.add_pack!(:ufo, nil) # raise Six::InvalidPackPassed
# use specific pack for rules
Six.use(:book) # true
Six.allowed? :read_book, nil, nil # true
Six.allowed? :drive, nil, nil # false
Six.use(:car)
Six.allowed? :drive, nil, nil # true
Six.allowed? :read_book, nil, nil # false
# use reset to return to global usage
Six.reset_use
Six.allowed? :drive, nil, nil # true
Six.allowed? :read_book, nil, nil # true
# different use methods
Six.use(:ufo) # false
Six.use!(:ufo) # raise Six::NoPackError
# remove pack
Six.remove(:book) # true
Six.remove(:ufo) # false
Six.remove!(:ufo) # raise Six::NoPackError
Six.use(:car) # true
Six.current_rule_pack # :car