Канкан не показывает авторизованные элементы просмотра
-
26-09-2019 - |
Вопрос
Я пытаюсь получить базовую аутентификацию / авторизацию с разработкой / канкан с рельсами. Вместо того, чтобы использование ролей, таких как скринкаст Ryan B и другие примеры вокруг я пытаюсь сделать что-то базовое:
1 - пользователь может войти в систему
2 - Пользователь может редактировать / уничтожить свои собственные статьи (без ролей, вы либо вошли в систему, и можете создавать новые статьи и редактировать / уничтожить свой собственный или вы выходить из системы, и вы можете увидеть только статьи и вход только в систему)
Я использую разработку для первой части, и это хорошо работает, но я не могу получить вторую часть, работающую с CANCAN. Ссылки для редактирования и уничтожения для статей не появляются, когда вы вошли в систему, и прямой URL (например, / статьи / 3 / редактирование) до сих пор допускают, даже если статья для другого пользователя.
Мой ability.rb
является
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
и вид частичный, который перечисляет статьи _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>
С этой настройкой ссылки редактирования / уничтожения в представлении не отображаются, если нет одеяла can :manage, :all
, четное can :manage, Article
не работает. Как я уже упоминал выше, он также не ограничивает фактические действия, поскольку вы можете глубоко связать прямую связь, чтобы редактировать статью, и это позволяет ему.
Я не уверен, что я делаю не так. Было бы здорово получить помощь.
заранее спасибо
Джейсон
Решение
Мне удалось решить мою проблему. Я сбрасываю свою среду (RVM - Resintrated Gems и Gемсет - Ruby 1.9.2 и Rails 3.0.0) и изменил некоторые из кодов, и все проблемы, которые я прошел (перенаправить петлю, просмотр элементов, не меняющихся на основе регистрации В несанкционированном контроллере действий все еще допустимо). Я вставил ability.rb
, articles_controller.rb
, а также _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
Я думаю, что это имеет смысл сейчас, но потому что только обновление и удаление должны были быть для текущих средств пользователя, я разбил элементы Crud, чтобы быть конкретными.
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
Работает, но я положил конкретную авторизую! Линии в каждом действии контроллера, так как у меня есть дополнительные действия внизу. Оба сейчас работают.
Я обновил ссылку на @Article к статье, чтобы ссылаться на текущую статью в списке в _article_list.html.rb
:
<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>
Все работает сейчас. Спасибо за помощь здесь и, надеюсь, это поможет кому-то еще, если они столкнутся с этой проблемой.
Другие советы
Ваше условие соответствия идентификатора пользователя не совсем правильно. Так должно быть:
can :manage, Article, :user_id => user.id
Атрибут, который вы хотите проверить, сопоставлен на значение, на котором вы хотите проверить.
Кроме того, вы проверяете на user.nil?
Когда он не может быть ноль, потому что вы только что инициализировали. (Вероятно, симптом пробовал много вещей!)
Ваша работаешь? Если вы беспокоить CAN: Manage: All Line будет возможность редактировать свой пост (вместе со всеми остальными)?
Вы пытались меняться, можно: Управление, статья: user_id == пользователь на
can :manage, Article do |article|
article.try(:user) == user
Я никогда не смог нагружать разрешение на работу - хотя я подозреваю, что я делаю что-то не так. Чтобы предотвратить доступ к кому-либо доступа к URL-адресам, в редактировании вашей статьи, попробуйте добавить это
unauthorized! if cannot? :edit, @article