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

后端 未结 4 1609
耶瑟儿~
耶瑟儿~ 2020-12-29 06:10

I have a Post model with a :published attribute (boolean) and a User model with a role attribute (st

相关标签:
4条回答
  • 2020-12-29 06:38

    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"

    0 讨论(0)
  • 2020-12-29 06:41

    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.

    0 讨论(0)
  • 2020-12-29 06:49

    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 %>
    
    0 讨论(0)
  • 2020-12-29 06:53

    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.

    0 讨论(0)
提交回复
热议问题