1

I'm trying to create a show view for three roles. Admin, super user, and user. An admin should see all of the users. A super user should see only users and a user should not see anyone. When I used the commented out policy method in the resolve for else user.super_user? would give me unsupported: TrueClass error. Any suggestions are welcomed.

Users Controller

def index
  @users = policy_scope(User)
  authorize User
end

User Policy

class UserPolicy
 attr_reader :current_user, :model

 def initialize(current_user, model)
   @current_user = current_user
   @user = model
 end

 class Scope
   attr_reader :user, :scope

   def initialize(user, scope)
      @user = user
      @scope = scope
   end

   def resolve
     if user.admin?
       scope.all
     else user.super_user?
       scope.where(user.role = 'user' )
       # scope.where(user.role != 'admin') [this would not work in the views, but it would work in rails c]
       end
     end
   end

  def index?
    @current_user.admin? or @current_user.super_user?
  end
end

updated Users Controller

class UsersController < ApplicationController
  before_filter :authenticate_user!
  after_action :verify_authorized

  def index
    @users = policy_scope(User)
  end
end

Correct Answer

I figured out what I needed to do. I was calling the role incorrectly. Updated scope below.

class UserPolicy
  attr_reader :current_user, :model

  def initialize(current_user, model)
    @current_user = current_user
    @user = model
  end

  class Scope
    attr_reader :user, :scope

    def initialize(user, scope)
       @user = user
       @scope = scope
    end

    def resolve
      if user.admin?
        scope.all
      else user.super_user?
        scope.where(role: 'user' )
      end
    end
  end

  def index?
    @current_user.admin? or @current_user.super_user?
  end

controller

class UsersController < ApplicationController
  before_filter :authenticate_user!
  after_action :verify_authorized

  def index
    @users = policy_scope(User)
    authorize @users
  end
AGirlThatCodes
  • 575
  • 7
  • 21

1 Answers1

2

Your resolve method should use elsif:

# Safer option
def resolve
   if user.admin?
     scope.all
   elsif user.super_user?
     scope.where(user.role = 'user' )
   else
     scope.none
   end
end

or not check for the super user at all and just depend on checking the authorization of the user before the result is used:

# This option is the same as the code you added to your question
# but doesn't include the unnecessary check
def resolve
   if user.admin?
     scope.all
   else
     scope.where(user.role = 'user' )
   end
end

EDIT: updated to deal with the case of not being an admin or super user

rdubya
  • 2,916
  • 1
  • 16
  • 20
  • Thank you! I have changed it, but I am getting `not allowed to index? this User` error. I think I might be using my scopes wrong. Any suggestions? – AGirlThatCodes Dec 29 '14 at 03:31
  • @AGirlThatCodes I believe your `authorize User` line is the problem. You should replace 'User' with an instance of an object that you want to test permissions for. It looks like the way you are calling it now, it is testing permissions on the 'User' class object. – rdubya Dec 29 '14 at 03:37
  • @AGirlThatCodes to add to my previous comment, I can't see enough of your controller to know for sure, but I'm guessing you don't need the `authorize User` line at all. The `@users = policy_scope(User)` takes care of making sure you are only showing users that the current user has access to see. – rdubya Dec 29 '14 at 03:40
  • thank you! I updated my controller with your suggestions. I have a silly ruby problem in my scope that I can't get my head around. I need to have it where the `user.role` shows only `users` (not `admin` of `super_user`). Running into a sql error. I think I need to make the user into a symbol, but I'm having an airy moment. Open for suggestions. – AGirlThatCodes Dec 29 '14 at 04:03
  • @AGirlThatCodes Sorry, I'm not sure what you are asking. It would probably be better if you created a new question for it so you can go into more detail. You can post a link here and I'll take a look at it if somebody else doesn't get there first. Also, could you mark this as the accepted answer if it helped you out? Thanks! – rdubya Dec 29 '14 at 11:13
  • Thank you! But my problem was not resolved, since based on your recommendation I would need to create another else since you can't close an `if`/`else` method with an `elsif`. I will keep it open. – AGirlThatCodes Dec 29 '14 at 17:04