I'm running Pundit in my Rails app for authorisation. I seem to be getting the hang of it all but want to know how to restrict the edit or update actions to a certain field.
For example, a user can edit their user.first_name, user.mobile or user.birthday etc but can't edit their user.role. Essentially my logic is, let the user edit anything that's cosmetic but not if it is functional.
These fields should only be able to be edited by a user who has a 'super_admin' role (which I have setup on the user.rb with methods such as the below).
def super_admin?
role == "super admin"
end
def account?
role == "account"
end
def segment?
role == "segment"
end
def sales?
role == "sale"
end
def regional?
role == "regional"
end
def national?
role == "national"
end
def global?
role == "global"
end
I pretty much have a clean slate user_policy.rb file where the update and edit actions are the default
def update?
false
end
def edit?
update?
end
Maybe I am thinking entirely wrong about this and should just wrap a user.super_admin? if statement around the role field on the user show page but this feels wrong if I am only using that tactic for security.
Use Pundit's permitted_attributes helper which is described on the gem's README page: https://github.com/elabs/pundit
# app/policies/post_policy.rb
class PostPolicy < ApplicationPolicy
def permitted_attributes
if user.admin? || user.owner_of?(post)
[:title, :body, :tag_list]
else
[:tag_list]
end
end
end
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def update
@post = Post.find(params[:id])
if @post.update_attributes(post_params)
redirect_to @post
else
render :edit
end
end
private
def post_params
params.require(:post).permit(policy(@post).permitted_attributes)
end
end
In your views, you can limit what users can see based on their role.
User View
- if current_user.super_admin?
= f.select(:role, User.roles.keys.map {|role| [role.titleize.role]})
- else
= user.role
And in the policy you can call the role of the user to make sure they are able to edit.
class UserPolicy
attr_reader :current_user, :model
def initialize(current_user, model)
@current_user = current_user
@user = model
end
def edit?
@current_user.super_admin || @current_user == @user
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With