2017-09-06 5 views
2

Ich verwende derzeit Devise, CanCan und Rolify zu handhaben Authentifizierung und Autorisierung für meine Rails App und ich habe eine wirklich harte Zeit zu verstehen, wie man es so macht dass ein user nur :show und :update eine spezifische Instanz eines Modells, das der Benutzer gehört (aka meine user hat eine client_id Spalte, nicht umgekehrt).CanCanCan zeigen nur Instanz des Modells, dass Benutzer gehört

Das Update Teil meiner definiert Abilities.rb für die user mit der :client Rolle arbeitet, fein, dh wenn current_user.client_id = 3 dann kann er nur einen Client aktualisieren, bei denen Client.id = 3 jedoch, dass gleiche Benutzer eine Instanz des Client Modell sehen und ich Ich kann nicht begreifen, wie ich das begrenzen kann.

Ability.rb

... 
if user.has_role? :client 
    can [:read, :update], [Property, Order], client_id: user.client_id 
    can [:read, :update], Owner 
    can :create, [Property, Order, Owner] 
    can :manage, User, id: user.id 
    can [:show, :update], Client, id: user.client_id 
end 
... 

Jeder Benutzer hat keine index alle Clients, so dass nach der Erforschung ich can [:read, :update], Client, ..-:show geändert, aber die Benutzer können immer noch die anderen clients aber das :update Teil sehen, ob es funktioniert gut Ich bin hier wirklich ratlos. Ich habe die letzten paar Stunden gegoogelt und die gesamte CanCan-Dokumentation durchgelesen, von der ich anerkenne, dass sie vielleicht angesprochen wurde, aber ich kann es nicht herausfinden.

Ich habe versucht, es von der Steuerungsseite zu begrenzen, wie unten gezeigt, aber das nicht funktioniert, entweder:

external/clients_controller.rb

class External::ClientsController < ApplicationController 
    load_and_authorize_resource 
    before_filter :client_only 

    def index 
    @clients = Client.paginate(page: params[:page], per_page: 15) 
    end 

    def show 
    @clients = Client.find(params[:id]) 
    @client_users = User.where(client_id: params[:id]) 
    @client_orders = Order.where(client_id: params[:id]).includes(:property, :owners) 
    can? :show, @clients 
    end 

    def edit 
    @clients = Client.find(params[:id]) 
    respond_to do |format| 
     format.html { @clients.save } 
     format.js 
    end 
    end 

    def update 
    @clients = Client.find(params[:id]) 
    @clients.update_attributes(client_params) 
    respond_to do |format| 
     format.html { if @clients.save 
         flash[:success] = "Client Updated Successfully" 
         redirect_to client_path(@clients) 
        else 
         render 'edit' 
        end 
     } 
     format.js 
    end 
    end 

    private 

    def client_params 
    params.require(:client).permit(:uuid, :company, :first_name, :last_name, :phone, :email, :address1, :address2, :city, :state, :zip, :notes) 
    end 

    def client_only 
    redirect_to root_path unless current_user.is_client? 
    end 

end 

Also, wenn jemand mir voll wie CanCan Griffe verstehen helfen könnte Rollenbasierte Autorisierung für eine Instanz eines Modells, dann würde ich es sehr schätzen. Danke im Voraus!

Aktualisiert-Code

Entfernt alle @client Beispiel lädt in external/clients_controller.rb

class External::ClientsController < ApplicationController 
    load_and_authorize_resource 
    before_filter :client_only 

    def show 
    @client_users = User.where(client_id: params[:id]) 
    @client_orders = Order.where(client_id: params[:id]).includes(:property, :owners).paginate(page: params[:page], per_page: 15).order("order_number DESC") 
    end 

    def edit 
    respond_to do |format| 
     format.html 
     format.js 
    end 
    end 

    def update 
    if params[:client][:state].blank? 
     params[:client][:state] = @client.try(:state) 
    end 
    @client.update_attributes(client_params) 
    respond_to do |format| 
     format.html { if @client.save 
         flash[:success] = "Client Updated Successfully" 
         redirect_to external_client_path(@client) 
        else 
         render 'edit' 
        end 
     } 
     format.js 
    end 
    end 

    private 

    def client_params 
    params.require(:client).permit(:uuid, :company, :first_name, :last_name, :phone, :email, :address1, :address2, :city, :state, :zip, :notes) 
    end 

    def client_only 
    redirect_to root_path unless current_user.is_client? 
    end 

end 

voll ability.rb

class Ability 
    include CanCan::Ability 

    def initialize(user) 
    alias_action :show, :to => :view 
    alias_action :open_external_orders, :completed_external_orders, :to => :client_order_views 

    user ||= User.new 
    if user.has_role? :admin 
     can :manage, :all 
     can :assign_roles, User 
    else 
     can :read, :all 
    end 

    if user.has_role? :executive 
     can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset, User] 
     cannot :assign_roles, User 
    end 

    if user.has_role? :management 
     can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset] 
     can :read, User 
     can :manage, User, id: user.id 
     cannot :destroy, [Property, Order, Client, User] 
    end 

    if user.has_role? :analyst 
     can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset] 
     can :manage, User, id: user.id 
     cannot :destroy, [Property, Order, Client, User] 
    end 

    if user.has_role? :it 
     can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset] 
     can :manage, User, id: user.id 
     can :read, User 
     cannot :destroy, [Property, Order, Client, User] 
    end 

    if user.has_role? :client 
     can [:read, :update], Client, id: user.client_id 
     can [:read, :update, :client_order_views], [Property, Order], client_id: user.client_id 
     can [:read, :update], Owner 
     can :create, [Property, Order, Owner] 
     can :manage, User, id: user.id 
    end 
    end 
end 
+0

Ein paar Dinge zuerst: Die Variable @ Clients in den Methoden ist eigentlich ein @ Client, oder? (singular, nicht plural, bitte ändere das), zweitens: das wird schon über 'load_and_authorize_resource' geladen, also warum lädst du es nochmal? Kannst du auch den Rest deiner Fähigkeit posten? Rb? danke – coorasse

+0

Ich bemerkte tatsächlich, dass durch die Docs letzte Nacht hatte ich bereits die meisten der Controller und so gebaut, bevor ich CanCan implementiert und ich glaube, ich habe es nie geändert, aber jetzt getan haben. Ich ging durch all meine Ansichten und änderte '@ clients' zu' @ client' und postete meine aktualisierte 'external/clients_controller.rb' sowie meine volle' fähigkeit.rb'. Danke, dass du mir geholfen hast. –

+0

Sie haben eine Regel, die besagt, dass ein Benutzer "kann: lesen,: alle", wenn es kein Admin ist. Dadurch können alle Benutzer ohne Administratorrechte alle Modelle lesen. – coorasse

Antwort

1

CanCanCan arbeitet mit "Erhöhung von Berechtigungen". Jede Regel kann die vorherige erhöhen.

Wenn Sie schreiben:

can :show, User 
can :edit, User 

die beiden Berechtigungen verbunden sein wird, und Sie werden in der Lage einen Benutzer anzuzeigen und zu bearbeiten.

In Ihrer Fähigkeit.rb definieren Sie can :read, :all Sie erteilen Berechtigungen zum Lesen (Show und Index) für alle Objekte.

Ich empfehle Ihnen, Ihre Fähigkeitsdatei nach dem Konzept der "zunehmenden Zulassungen" zu schreiben.Das bedeutet, dass du nicht anfängst, die Fähigkeit für den Admin zu definieren, aber du tust das am Ende, indem du die Fähigkeiten hinzufügst, die ein Admin benötigt, zu denen, die du bereits allen gegeben hast.

+0

Ahhh Ich mag diese Idee, ich habe das Konzept schon halb begriffen, aber '' kann ... '' dann 'kann nicht ..' danach gesetzt werden, aber ich dachte, es war in jedem 'user.has_role?' Enthalten, also danke, dass du das geklärt hast und für die Vorschläge. –

Verwandte Themen