Note that there are some explanatory texts on larger screens.

plurals
  1. PODevise / Rolify / CanCan 2.0: Preventing users from changing a user's role
    text
    copied!<p>I am using Devise for authentication, Rolify for role management and CanCan 2.0 for authorization.</p> <p>I am trying to allow the :admin role to change a user's roles, but disallow all other users access.</p> <p>Here is what I have tried and is not working:</p> <pre><code>#ability.rb class Ability include CanCan::Ability def initialize(user) if user.has_role? :admin can :access, :all elsif user.has_role? :moderator can [:index, :read, :update, :destroy], :users, :user_id =&gt; user.id cannot :access, :users, [:role_ids] end end #application_controller.rb ... rescue_from CanCan::Unauthorized do |exception| redirect_to root_url, :alert =&gt; exception.message end </code></pre> <p>I have intentionally left the association in my user form:</p> <pre><code>#_form.html.erb &lt;%= simple_form_for @user do |f| %&gt; &lt;%= f.association :roles, as: :check_boxes %&gt; &lt;%#= f.association :roles, as: :check_boxes if can? :update, @user, :roles %&gt; &lt;%= f.button :submit %&gt; &lt;% end %&gt; </code></pre> <p>controller</p> <pre><code>#users_controller.rb class UsersController &lt; ApplicationController before_filter :authenticate_user! load_and_authorize_resource def index @users = User.accessible_by(current_ability) end def new @user = User.new end def create @user = User.new(params[:user]) end def show @user = User.find(params[:id]) end def edit @user = User.find(params[:id]) end def update @user = User.find(params[:id]) @user.update_without_password(params[:user]) if successfully_updated redirect_to @user else render :action =&gt; "edit" end end end </code></pre> <p>and the model:</p> <pre><code>#user.rb class User &lt; ActiveRecord::Base rolify attr_accessible :role_ids ... </code></pre> <p>Now if a user who has the role of :moderator tries to change another user's (or his own) roles, here is what happens:</p> <ol> <li>A CanCan::Unauthorized exception is thrown and the user is redirected to root_url</li> <li>The roles are changed for the user</li> </ol> <p>I am confused. If the exception happens, why are the changes still made? I am probably doing something very wrong :)</p> <p>I have tried manipulating the query params depending on a users role in users_controller.rb If I put a log statement right after def update, here is my output:</p> <pre><code>2013-04-24 12:42:21 [4161] DEBUG (0.1ms) BEGIN 2013-04-24 12:42:21 [4161] DEBUG (0.3ms) INSERT INTO "users_roles" ("user_id", "role_id") VALUES (5, 1) 2013-04-24 12:42:21 [4161] DEBUG (0.4ms) COMMIT 2013-04-24 12:42:21 [4161] DEBUG User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", "5"]] 2013-04-24 12:42:21 [4161] DEBUG {"username"=&gt;"Blabla", "email"=&gt;"bla@bla.com", "password"=&gt;"", "password_confirmation"=&gt;"", "approved"=&gt;"1", "role_ids"=&gt;["1", "2", ""]} </code></pre> <p>I must be overlooking something...</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload