be careful when using admin powers with ClassName.active

Posted About 10 years ago. Visible to the public.

Very often when using consul, our scopes look something like:

  power :creatable_books, :updatable_books, :destroyable_books do
    case role
      when :user
        Book.active.where(user_id: @user.id)
    end
  end

This is perfect as new records get created with the right user_id allready set:

001: > Power.new(@user).creatable_books
  => #<Book id: nil, title: nil, description: nil, user_id: 189, created_at: nil, updated_at: nil>
002:>  # Note that the above record has the user_id set.

BUT

When you now implement something like "Admins may edit every book as well as create a new one", however, you have to be carefull:

   # THIS LEADS TO ERRORS:
   power :creatable_books, :updatable_books, :destroyable_books do
    case role
      when :user
        Book.active.where(user_id: @user.id)
       when :admin
       # Do not do it like this:
        Book.active
    end
  end

Why?

The scope "Book.active.where(user_id: @user.id)" is used for creating records as well:

 001: > Book.active.where(user_id: @user_id).new
  => #<Book id: nil, title: nil, description: nil, user_id: 189, created_at: nil, updated_at: nil>

(Note that the user_id of the new record is set through the scope). Therefore, when you use the above scope to create records as admin, the user_id is not set and the application will crash:

   002: > Power.new(@admin).creatable_idea_books.new
 => #<IBook id: nil, title: nil, description: nil, user_id: nil, created_at: nil, updated_at: nil> 
   002:>  # Note that the above record IS MISSING a user_id

Do the right thing
In a scenario like the above, you have to treat the create_scope differently:

   # THIS IS THE RIGHT THING:
   power :updatable_idea_books, :destroyable_idea_books do
    case role
      when :user
        Book.active.where(user_id: @user.id)
      when :admin
        Book.active
    end
  end

  power :creatable_books do
    Book.active.where(user_id: @user.id) unless guest?
  end

That way, also admins can create records:

 001: > Power.new(@admin).creatable_books.new
 => #<Book id: nil, title: nil, description: nil, user_id: 189, created_at: nil, updated_at: ni> 
 002:>  # Note that the above record has the user_id set.
Christoph Beck
Last edit
About 10 years ago
Posted by Christoph Beck to BitCrowd (2014-02-19 13:27)