2014-01-16 5 views
9

ich in BezugWarum werden "scope" -orientierte Aktionen (insbesondere "index" -Aktionen) in Pundit unterschiedlich behandelt?

Ich habe den Eindruck zu https://github.com/elabs/pundit#scopes schreibe, dass Genehmigung die Frage beantworten sollte Sie den Zugriff auf diese Ressource erlaubt sind?, d.h. eine true/false Antwort. Dies ist der Fall bei allen Aktionen außer index, die laut Pundits Dokumenten unterschiedliche ActiveRecord::Relation zurückgeben sollen, je nachdem, wer fragt. Zum Beispiel erhält ein Administratorscope.all, während ein regulärer Benutzer bekommt scope.where(:published => true).

app/Politik/post_policy.rb

class Scope < Struct.new(:user, :scope) 
    def resolve 
    if user.admin? 
     scope.all 
    else 
     scope.where(:published => true) 
    end 
    end 
end 

app/controllers/posts_controller.rb

def index 
    @posts = policy_scope(Post) 
end 

Meine Buchung ist, dass dies ein rutschiger Abhang ist, und bald werde ich Hinzufügen von Präsentationen zu den Bereichen (z. B. scope.all.order('created_at ASC')) - und es fühlt sich einfach komisch dabei in einer Autorisierungsrichtlinie.

Natürlich ich, dass an den Controller bewegen konnte ...

def index 
    @post = policy_scope(post) 
    if user.admin? 
     @post = @post.order('created_at ASC') 
    end 
end 

... aber ist, dass die Aufgabe des Controller? Und ich denke nicht, dass es richtig wäre, einen solchen Aufruf zu der Ansicht hinzuzufügen. Vielleicht sollte es eine Modellmethode sein?

Was würden Sie sagen, sind die Vor- und Nachteile der folgenden Schritte?

app/Controller/posts_controller.rb

Diese index zu authorize genau wie die anderen Methoden, mit einem Anruf hält, und ein Anruf an ein Modell Methode.

def index 
    authorize(Post) 
    @posts = Post.index(current_user) 
end 

app/Politik/post_policy.rb

Dies gibt einfach eine Wahr/Falsch-Antwort. Sind Sie autorisiert? Ja oder Nein.

def index? 
    user.admin? || user.regular_user? 
end 

app/models/post.rb

Und im Modell können wir als Lust bekommen, wie wir wollen.

def self.index(user) 
    if user.admin? 
    Post.all.order('created_at ASC') 
    else 
    Post.where(user_id: user.id) 
    end 
end 

Gedanken?

Antwort

11

Mein Verständnis der Zulassung vs Bereiche in Pundit ist wie folgt:

authorization: ‚dieser Benutzer wirken auf (create/update/zerstören) diese Ressource erlaubt ist?'

within scope: 'soll dieser Benutzer in der Lage sein zu siehe (Index/show) diese Ressource'?

Autorisierung (authorize @resource) für die Antwort auf permitted_attributes in ResourcePolicy.

Scopes (policy_scope(Resource)) verschieben auf resolve.

Ich glaube, der Grundgedanke hinter Pundits Bereichen ist, dass es nur einen Speicherort in Ihrem Code geben sollte, an dem Sie definieren, wer Zugriff auf welche Ressourcen haben soll.

Sie könnten, wie Sie beschrieben haben, das gleiche Verhalten in Ihren Controllern oder Ihren Ansichten implementieren. Wenn Sie jedoch den Code in eine Policy einbetten, werden Sie vor unbefugten Zugriffen geschützt, falls Sie vergessen sollten, in einer Ihrer Controller-Methoden entsprechend zu skalieren.

Ich denke an policy_scope() als die Möglichkeit, die Sichtbarkeit zu beschränken, während andere Ergebnisverbesserungen (z. B. Sortieren) auf der Controller-Ebene stattfinden können. Es gibt jedoch zweifellos eine Menge persönlicher Vorlieben im Spiel.

+0

Es scheint mir mehr wie authorize zu überprüfen, ob der Benutzer die Berechtigung hat, auf eine einzelne Ressource zuzugreifen, während scoping das filtern was in einer Indexaktion zurückgegeben wird, dh das Scoping wirft keinen 403 verbotenen Fehler auf wie authorised, Es wird nur zum Entfernen von Datensätzen verwendet, die nicht zu current_user gehören. – Zhang

+0

Sogar die offizielle Github-Seite von Pundit hat folgendes: 'def show @user = berechtige User.find (params [: id]) end' https://github.com/elabs/pundit – Zhang