Skip to content

Instantly share code, notes, and snippets.

@willscripted
Created August 28, 2014 16:46
Show Gist options
  • Save willscripted/ba8a004941b2f22a4347 to your computer and use it in GitHub Desktop.
Save willscripted/ba8a004941b2f22a4347 to your computer and use it in GitHub Desktop.
Fine-grained permissions
## e.g. Usage
def V1::UserController < V1::BaseController
## In controller
def show
render :json => reject_unpermitted(user, V1::UserPresenter.new(user))
end
def update
user = User.find(params[:id])
if user.update_attributes(updatable_params(user))
render :status => 200, :json => V1::UserPresenter.new(user)
else
render :status => :unprocessable_entity, :json => { :errors => user.errors }
end
end
def index
render :json => User.all.map {|u| reject_unpermitted(u, V1::UserPresenter.new(u))}
end
private
def updateable_params(user)
# Determine what fields the user with `current_ability` can update
updatable = V1::UserPermissions.new(user, current_ability).on_update
# Remove anything they can't update
p = params.clone
p.slice!(updatable)
p
end
def reject_unpermitted(user, json)
# Determine showable fields
# e.g. [:is_admin, :username, :password]
showable = V1::UserPermissions.new(user, current_ability).on_show
# Remove unpermitted fields from json
json.slice!(showable)
json
end
end
# Takes a target object and current ability, and
# spits out arrays of permitted keys. Arrays can then
# be used to slice! params or json
class V1::UserPermissions
def initialize(user, current_ability)
@user = user
@ability = current_ability
end
# Returns an array of attribute symbols that @current_user can update on @user
def on_update
fields = [:username, :email, :password]
fields.push(:is_admin) if @ability.can?(:manage, @user)
fields
end
# Returns an array of attribute symbols that can be shown to a user with @ability
def on_show
fields = User.attribute_names
fields -= [:is_admin]
fields
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment