Skip to content

Instantly share code, notes, and snippets.

@lee-dohm
Forked from christhekeele/ALLOWABLE.md
Created June 20, 2013 23:56
Show Gist options
  • Save lee-dohm/5827824 to your computer and use it in GitHub Desktop.
Save lee-dohm/5827824 to your computer and use it in GitHub Desktop.
###
# Allowable
#
# A pattern for decomposing large/long conditional chains
# into readable, testable, and inspectable segments.
# Code coverage stats can help show you which conditions
# aren't getting test coverage, and printing/prying around
# the code can show you intermediary condition results.
#
# Effectively a block-syntax for the `or` operator: each `when?`
# condition will be evaulated in turn until one found to be true.
#
module Allowable
def allow(&block)
catch :allowed do
yield
end or false
end
def when?(&block)
throw :allowed, true if yield
end
end
###
# Inside your Authority initializer
#
class Authority::Authorizer
include Allowable
extend Allowable
end
###
# CommentAuthorizer
#
# Example Usage of Allowable in an Authority::Authorizer
#
# Assuming a Comment model attached to a Post:
#
class CommentAuthorizer < Authority::Authorizer
# Fallback
def self.default(ability, user, *args)
user.has_role? :super_admin
end
# Authorization for Comment class (read/create)
def self.readable_by?(user, *args)
allow do
when? { super } # Super calls still work, keeping code dry
when? { user.has_role? :member }
end
end
def self.creatable_by?(user, *args)
allow do
when? { super }
when? { user.has_role?(:member) and not user.shadow_banned? }
when? { user.anonymous? and not User.banned_ips.include?(user.ip_address) }
end
end
# Authorization for Comment instances (edit/destroy)
def updatable_by(user, *args)
allow do
when? { super }
when? { user.has_role? :author, resource }
when? { user.has_role? :moderator }
when? { user.has_role?(:member) and user.membership.joined_ago.days > 365 }
when_api_enabled(user, resource)
end
end
def deleteable_by(user, *args)
allow do
when? { super }
when? &:feeling_lucky # also accepts procs
when_api_enabled(user, resource)
end
end
private
# Re-use when? statements
def when_api_enabled(user, comment)
response = APIClient.get("/user/#{user.id}/permissions/comments/#{comment.id}")
when? { response.code == 200 }
end
def feeling_lucky
[true, false].sample
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment