Suppose I have a scenario where we have Users and each user can create their own Projects.
I'm trying to limit the Show action of my Rails controller to only allow admin or the owner of the project to be able to go through Show action.
The problem I am facing is, perhaps I'm misunderstanding on how to use Scopes in Pundit.
My Show action looks like this:
def show
project = policy_scope(Project).find_by({id: project_params[:id]})
if project
render json: project
else
render json: { error: "Not found" }, status: :not_found
end
end
My Pundit Scope class looks like this:
class Scope < Scope
def resolve
if @user.admin?
scope.all
else
# obviously, if non-matching user id, an ActiveRelation of
# empty array would be returned and subsequent find_by(...)
# would fail causing my controller's 'else' to execute
# returning 404 instead of 403
scope.where(user_id: @user.id)
end
end
end
In my Rails test, I am trying to assert that non-project owner should receive a 403 forbidden:
test "show project should return forbidden if non admin viewing other user's project" do
# "rex" here is not the owner of the project
get project_path(@project.id), headers: @rex_authorization_header
assert_response :forbidden
end
My test is failing. I am getting the error:
Failure:
ProjectsControllerTest#test_show_project_should_return_forbidden_if_non_admin_viewing_other_user's_project [/Users/zhang/App_Projects/LanceKit/Rails_Project/LanceKit/test/controllers/projects_controller_test.rb:40]:
Expected response to be a <403: forbidden>, but was a <404: Not Found>.
Expected: 403
Actual: 404
I don't quite feel like I'm using Pundit correctly.
Should I be using Pundit's authorize project instead of using policy_scope(Project)... for the Show action?
I was expecting the scope.where(...) to detect the incorrect user id and return some error saying 'you are not authorized to view this resource' rather than returning results.