CANCAN zeigt, die nicht autorisierte Ansichtselemente
-
26-09-2019 - |
Frage
Ich versuche, einige grundlegende Authentifizierung / Autorisierung zu erhalten mit devise / Cancan mit Rails. Anstatt um ich Rollen wie Ryan B Screencasts und andere Beispiele verwenden ich versucht, etwas Grundsätzliches zu tun:
1 - Ein Benutzer in
anmelden kann
2 - Ein Benutzer kann nur bearbeiten / zerstören ihre eigenen Artikel (keine Rollen, sind Sie entweder angemeldet und können neue Artikel und bearbeiten erstellen / zerstören Sie Ihre eigenen, oder du bist abgemeldet und Sie können nur Artikel und Login sehen)
Ich verwende devise für den ersten Teil und das funktioniert gut, aber ich kann nicht den zweiten Teil mit CanCan Arbeit bekommen. Die das Bearbeiten und zerstören Links für die Artikel erscheinen nicht, wenn Sie angemeldet sind und die direkte URL (z / articles / 3 / edit) erlaubt nach wie vor, auch wenn der Artikel für einen anderen Benutzer ist.
Meine ability.rb
ist
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user.nil?
can :read, :all
else
# can :manage, :all #test - with this, all the edit/destroy links appear
can :manage, Article, :user_id == user
end
end
end
articles_controller.rb
:
class ArticlesController < ApplicationController
before_filter :authenticate_user!, :except => [:index, :show] # for Devise
load_and_authorize_resource
# GET /articles
# GET /articles.xml
def index
@articles = Article.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @articles }
end
end
# GET /articles/1
# GET /articles/1.xml
def show
@article = Article.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @article }
end
end
# GET /articles/new
# GET /articles/new.xml
def new
@article = Article.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @article }
end
end
# GET /articles/1/edit
def edit
@article = Article.find(params[:id])
end
# POST /articles
# POST /articles.xml
def create
@article = Article.new(params[:article])
@article.user = current_user
respond_to do |format|
if @article.save
format.html { redirect_to(articles_path, :notice => 'Article was successfully created.') }
format.xml { render :xml => articles_path, :status => :created, :location => articles_path }
else
format.html { render :action => "new" }
format.xml { render :xml => @article.errors, :status => :unprocessable_entity }
end
end
end
# PUT /articles/1
# PUT /articles/1.xml
def update
@article = Article.find(params[:id])
respond_to do |format|
if @article.update_attributes(params[:article])
format.html { redirect_to(@article, :notice => 'Article was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @article.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.xml
def destroy
@article = Article.find(params[:id])
@article.destroy
respond_to do |format|
format.html { redirect_to(articles_url) }
format.xml { head :ok }
end
end
end
und die Ansicht teilweise, dass die Listen Artikel _article_list.html.erb
:
<table>
<tr>
<th>Title</th>
<th>Description</th>
<th>User</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.description %></td>
<td><%= article.user_id %></td>
<td><%= link_to 'Show', article %></td>
<% if can? :update, @article %>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<% end %>
<% if can? :destroy, @article %>
<td><%= link_to 'Destroy', article, :confirm => 'Are you sure?', :method => :delete %></td>
<% end%>
</tr>
<% end %>
</table>
Mit diesem Setup, das Bearbeiten / zerstören Links in der Ansicht nicht zeigen, es sei denn es gibt eine Decke can :manage, :all
, tut auch can :manage, Article
nicht Arbeit. Wie ich bereits erwähnt, es ist auch nicht die tatsächlichen Aktionen, wie Sie beschränken Artikel sind in der Lage zu Deep-Link direkt auf die Bearbeitung und erlaubt es.
Ich bin nicht sicher, was ich hier tue falsch. Es wäre toll, etwas Hilfe zu bekommen.
Vielen Dank im Voraus
Jason
Lösung
konnte ich mein Problem lösen. Ich meine Umgebung zurückgesetzt (RVM - resintalled die Edelsteine ??und gemsets - Rubin 1.9.2 und Rails 3.0.0) und geänderte Änderungen sind auf protokollierten einen Teil des Codes und alle die Fragen, die ich habe wegging (Redirect Schleife, Ansichtselemente nicht auf der Grundlage in, nicht autorisierten Controller-Aktionen noch zulässig). Ich habe klebte ability.rb
, articles_controller.rb
und _article_list.html.erb
.
ability.rb
:
class Ability
include CanCan::Ability
def initialize(user)
if user
can :create, Article
can :read, :all
can :update, Article, :user_id => user.id
can :delete, Article, :user_id => user.id
else
can :read, :all
end
end
end
Ich denke, es macht Sinn jetzt aber, da nur aktualisieren und löschen sollte für den aktuellen Benutzer Artikel sein, ich spaltete die CRUD Elemente aus spezifisch sein.
articles_controller.rb
class ArticlesController < ApplicationController
before_filter :authenticate_user!, :except => [:index, :show]
# load_and_authorize_resource # RESTful automated CanCam authorization - excludes non RESTful
# GET /articles
# GET /articles.xml
def index
@articles = Article.all
authorize! :read, @articles
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @articles }
end
end
# GET /articles/1
# GET /articles/1.xml
def show
@article = Article.find(params[:id])
authorize! :read, @article
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @article }
end
end
# GET /articles/new
# GET /articles/new.xml
def new
@article = Article.new
authorize! :create, @article
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @article }
end
end
# GET /articles/1/edit
def edit
@article = Article.find(params[:id])
authorize! :update, @article
end
# POST /articles
# POST /articles.xml
def create
@article = Article.new(params[:article])
@article.user = current_user
authorize! :create, @article
respond_to do |format|
if @article.save
format.html { redirect_to(articles_path, :notice => 'Article was successfully created.') }
format.xml { render :xml => articles_path, :status => :created, :location => articles_path }
else
format.html { render :action => "new" }
format.xml { render :xml => @article.errors, :status => :unprocessable_entity }
end
end
end
# PUT /articles/1
# PUT /articles/1.xml
def update
@article = Article.find(params[:id])
authorize! :update, @article
respond_to do |format|
if @article.update_attributes(params[:article])
format.html { redirect_to(@article, :notice => 'Article was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @article.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.xml
def destroy
@article = Article.find(params[:id])
@article.destroy
authorize! :delete, @article
respond_to do |format|
format.html { redirect_to(articles_url) }
format.xml { head :ok }
end
end
def by
@user = User.find(params[:id])
@articles = @user.articles
authorize! :read, @articles
end
end
load_and_authorize_resource
funktioniert, aber ich habe bestimmte authorise setzen! Zeilen in jeder Controller-Aktion, wie ich habe eine zusätzliche Maßnahme an der Unterseite. Beide jetzt arbeiten.
ich den Verweis auf @article zum Artikel aktualisiert, um den aktuellen Artikel in der Liste in _article_list.html.rb
zu verweisen:
<table>
<tr>
<th>Title</th>
<th>Description</th>
<th>User</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.description %></td>
<td><%= article.user_id %></td>
<td><%= link_to 'Show', article %></td>
<% if can? :update, article %>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<% end %>
<% if can? :delete, article %>
<td><%= link_to 'Destroy', article, :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<% end %>
</table>
Alle arbeiten jetzt. Danke für die Hilfe hier und hoffentlich Dies wird helfen, jemand anderes aus, wenn sie in dieses Problem.
Andere Tipps
Ihr Zustand einen Benutzer-ID für den Abgleich ist nicht ganz richtig. Es sollte sein:
can :manage, Article, :user_id => user.id
Das Attribut, das Sie überprüfen wollen, auf den Wert, den Sie gegen überprüfen möchten abgebildet.
Auch Sie überprüfen für user.nil?
, wenn es nicht gleich Null sein kann, weil Sie haben es gerade initialisiert. (Wahrscheinlich ein Symptom mit versucht, viele Dinge!)
Gibt es in Ihrem Fang Arbeit? Wenn Sie die Dose Kommentar-: verwalten,: alle Zeile wird ein Benutzer in der Lage sein, seinen / ihren Beitrag zu bearbeiten (zusammen mit allen anderen natürlich)
?Haben Sie versucht, zu ändern, können: verwalten, Artikel,: user_id == Benutzer
can :manage, Article do |article|
article.try(:user) == user
Ich habe nie in der Lage gewesen Last eine autorisieren zu bekommen, um arbeits obwohl ich vermute, dass ich etwas falsch mache. Um zu verhindern, jemand aus der URL direkt zugreifen, in Ihrem Artikel der Aktion bearbeitet, versuchen Sie, dies
unauthorized! if cannot? :edit, @article