CanCan: limiting a user's ability to set certain model attributes based on their role

北战南征 提交于 2019-11-30 04:48:06

So far it is not possible. But according to this: https://github.com/ryanb/cancan/issues/326 this feature should be in cancan 2.0.

Update: you can see this on CanCan 2.0 branch here: https://github.com/ryanb/cancan/tree/2.0 in section "Resource Attributes"

John Goodman

Check out this post: How do I use CanCan with rails admin to check for ownership

It shows how to make a field not visible based off a users role.

UPDATE I was able to set options in rails admin with this code:

config.model User do
  edit do
    configure :organization do
      visible do
        bindings[:view]._current_user.max_role_name != 'admin' ? false : true
      end
    end

    configure :organization_id, :hidden do
      visible do
        true if bindings[:view]._current_user.max_role_name != 'admin'
      end
      default_value do
        bindings[:view]._current_user.organization_id if bindings[:view]._current_user.max_role_name != 'admin'
      end
    end

    include_all_fields
  end
end

This configuration will hide the organization field if the logged in user is not an admin. It will then show an organization_id field ( set to type='hidden' ) and set the default value.

Hope this helps someone.

Until CanCan 2.0 comes out, I've solved this by creating a subclass of the model with restricted accessibility, something like:

class AuthorPost < Post
  attr_protected :published
end

And then give authors access to AuthorPosts: can :manage => AuthorPost

Then in your controller, you can set the resource you want in a before_filter:

before_filter :set_resource
...
  private
    def set_resource
      if current_user and current_user.author?
        @resource = AuthorPost
      else
        @resource = Post
      end
      params[:post] ||= params[:author_post]
    end

One last caveat: you won't be able to use load_and_authorize_resource in that controller. You'll have to do that manually, as detailed here: https://github.com/ryanb/cancan/wiki/Controller-Authorization-Example

You'll need to replace Project with @resource.

I'm on the fence as to whether this is more or less effective than the method described in the railscast. For my purposes, it left the original model totally intact, so my other code wasn't affected--and just allowed me to give some users fewer editable fields.

There is a way, I did something like this in my project. But CanCan is not entirely the answer. What you need to do is make attr_accessible in your model dynamic based on user role, so if you're an admin, then you're allowed to update the published field. If not, then giving the field a new value simply won't take when the model saves.

Railscasts comes to the rescue once again: http://railscasts.com/episodes/237-dynamic-attr-accessible

Following getting the backend part of that implemented, then you can do something about the frontend form by wrapping the publish field in the View with a roles check or something to show or hide the field based on the user. Rough example of my implementation...

<% if current_user.roles.where(:name => ['Administrator','Editor']).present? %>
    <%= f.label :display_name %>
    <%= f.text_field :display_name %>
<% end %>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!