-
-
Save luxerama/5846217 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### | |
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### | |
# 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