Skip to content

Instantly share code, notes, and snippets.

@pedrosmmoreira
Last active January 21, 2016 06:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save pedrosmmoreira/8dc0ba1e7f359ab5d669 to your computer and use it in GitHub Desktop.
Save pedrosmmoreira/8dc0ba1e7f359ab5d669 to your computer and use it in GitHub Desktop.
Dynamic Pundit Policies per user type
class FoosController < ApplicationController
include Pundit
#...
# record policy
def set_record_policy
policy(PolicyContext.new(record, current_user)
end
# scope policy
def set_policy_scope
policy_scope(PolicyContext.new(RecordClassName, current_user))
end
# authorizing controller action
def authorize_action
authorize PolicyContext.new(record, user), "#{action_name}?"
end
end
class AdminFooPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, context)
@user = user
@scope = context.record
end
def resolve
scope.not_cancelled?
end
end
def initialize(user, context)
@user = user
@record = context.record
end
def show?
!record.cancelled?
end
end
class FooPolicy < ApplicationPolicy
#...
class Scope
#...
def resolve
if user.roles.include?("admin")
scope.not_cancelled
elsif user.roles.include?("official")
scope.not_draft
elsif user.roles.include?("provider")
scope.provided_by(user)
else
scope.none
end
end
end
def show?
(provider && !record.cancelled?) ||
(official || user_is_assigned_provider?(user))
end
end
class PolicyContext
attr_reader :record
def initialize(record, user)
@record = record
@user = user
end
def policy_class
"#{@user.role}FooPolicy".classify
end
end
class AdminFooPolicy < ApplicationPolicy
# ...
class Scope
# ...
def resolve
scope.not_cancelled
end
end
def show?
record.cancelled?
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment