Skip to content

Instantly share code, notes, and snippets.

@cpuguy83
Created August 27, 2013 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cpuguy83/6353857 to your computer and use it in GitHub Desktop.
Save cpuguy83/6353857 to your computer and use it in GitHub Desktop.
This is cherry-picked from an internal application that I built...
Basically, a User is assigned a set of Permissions, inheritted from their group and also directly assigned to the user object (which in my code gets merged, but is simplified here).
Permissions are a set of permissions storing a few things (allowed actions, authorization scope, etc), including the list of attrs the user is allowed to modify.
When the controller action is called it is getting filtered through the policy for that controller (which inherits from ApplicationPolicy) which determines if the user is allowed to perform that action, on that resource(s), and which fields the user is allowed to modify (in an array).
class ApplicationController < ActionController::Base
#... stuff
private
def resource_params
if params[:action] == 'new'
[]
elsif current_user.admin?
params.require(resource_instance_name).permit!
else
params.require(resource_instance_name).permit( *policy_attributes(resource_class) )
end
end
def policy_attributes(user, scope)
policy = PolicyFinder.new(scope).permitted_attributes
policy.new(user, scope).resolve if policy
end
end
class ApplicationPolicy
# My authorization logic for controller actions goes here
# ...
class PermittedAttributes < Struct.new(:user, :scope)
def resolve
if user.admin?
scope.available_attrs
else
user.materialized_accessible_attrs(scope)
end
end
end
end
class User
has_many :permissions
#... user stuff
def materialized_accessible_attrs(klass)
# ...
# I have some additional logic where a user is in a group,
# and attrs can be defined at the group level and the user level
# Skipping that here
permissions.where(model_class: klass.to_s).pluck(&:accessible_attrs)
end
# Checks accessible_attrs to see if user can write to it
def has_write_permission_to_field?(klass, field)
if materialized_accessible_attrs(klass).include? field
true
else
false
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment