2016-06-11 10 views
0

Angenommen, ich habe ein Szenario, in dem wir haben Users und jeder Benutzer kann ihre eigenen Projects erstellen.Pundit Scoping Verwendung leer Ergebnisse

Ich versuche die Aktion meines Rails-Controllers zu beschränken, um nur dem Administrator oder dem Besitzer des Projekts zu erlauben, durch die Show Aktion gehen zu können.

Das Problem, dem ich gegenüberstehe, ist vielleicht, dass ich Missverständnis darüber habe, wie man Scopes in Pundit benutzt.

Meine Show Aktion sieht wie folgt aus:

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 

sieht My Pundit Scope Klasse wie folgt:

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 meinem Rails-Test, ich sollte, dass nicht-Projektinhaber geltend zu machen versuche erhalten a 403 verboten:

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 

Mein Test schlägt fehl. Ich erhalte den Fehler:

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 

Ich fühle mich nicht wie ich Pundit richtig verwende.

Sollte ich Pundit authorize project statt policy_scope(Project)... für die Show Aktion verwenden?

Ich erwartete, dass die scope.where(...) die falsche Benutzer-ID erkennen und einen Fehler zurücksenden, der besagt "Sie sind nicht berechtigt, diese Ressource anzuzeigen", anstatt Ergebnisse zurückzuliefern.

+0

Ich fand auch diese Stackoverflow-Post: http://StackOverflow.com/Questions/21172620/Why-are-Scope-orientierte -Aktionen-insbesondere-Index-Aktionen-behandelte-Differen Die Antwort von Rob scheint vorzuschlagen, den Anwendungsbereich zu verwenden für Index-/Show-Aktionen. – Zhang

Antwort

1

Von was meine Testergebnisse zu mir anzeigen, ist die Verwendung von Bereich für show Aktion falsch.

Mein Befund sagt mir Pundit Geltungsbereich werden nur zum Filtern einer Reihe von Daten verwendet, um nur diejenigen, die eine Bedingung entspricht zurückgeben, überprüft es nicht, ob der current_user der Besitzer der Ressource ist. Der Pundit-Bereich löst keinen 403 Forbidden Fehler aus.

Mit anderen Worten, die Verwendung von Scoping nur in der show Aktion führt zu einem semantischen Fehler, der this project with id 3 does not exist in the database zum Beispiel sagt statt you are not authorized to view this project because it belongs to a different user.

Eine Zusammenfassung für mich:

  • Verwendung policy_scope für index Aktion
  • Verwendung authorize für show, create, update, delete
  • Verwendung authorize UND policy_scope wenn Sie nicht Eigentümer Ressourcen und versuchen, auf einige funky Plural Ressource Route wie

    zugreifen

    für den Fall, dass Sie überprüfen möchten, ob der Benutzer einen "Projektmanager" oder "Mitarbeiter" sagt, der Ihr Projekt sehen darf.In diesem Fall müssten Sie Ihren Gültigkeitscode wahrscheinlich mit einer zusätzlichen elsif-Klausel ändern.

In Bezug auf meine obige Frage, modifizierte ich mein Projekt authorize in meiner show Aktion zu verwenden:

def show 
    project = Project.find_by({id: project_params[:id]}) 

    authorize project 

    if project 
     render json: project 
    else 
     render json: { error: "Not found" }, status: :not_found 
    end 
    end 

Dies hebt dann die erwarteten 403 Forbidden Fehler, meine Tests erwartet werden und somit mein Test geht vorbei.

+0

Dem stimme ich zu, wenn Sie auf eine Sendung zugreifen, fragen Sie nach einem bestimmten Datensatz. Pundit-Bereiche sind nur für einen Index (oder eine andere Erfassungsmethode) sinnvoll. – ardochhigh