无法显示授权的视图元素
我正在尝试使用 Rails 的 devise/cancan 获得一些基本的身份验证/授权。我没有使用 Ryan B 的截屏视频和其他示例等角色,而是尝试做一些基本的事情:
1 - 用户可以登录
2 - 用户只能编辑/销毁自己的文章(没有角色,您要么已登录并可以创建新文章并编辑/销毁您自己的文章,要么您已注销并且只能查看文章并登录)
我'我在第一部分中使用了 devise,效果很好,但我无法让第二部分与 CanCan 一起使用。当您登录时,文章的编辑和销毁链接不会出现,并且即使该文章是其他用户的,直接 URL(例如 /articles/3/edit)仍然允许。
我的能力.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
也不起作用。正如我上面提到的,它也不限制实际操作,因为您可以直接深层链接来编辑文章,并且它允许这样做。
我不确定我在这里做错了什么。如果能得到一些帮助那就太好了。
提前致谢
贾森
I'm trying to get some basic authentication/authorization with devise/cancan with Rails. Rather than using roles like Ryan B's screencast and other examples around I'm trying to do something basic:
1 - A user can log in
2 - A user can only edit/destroy their own articles (no roles, you're either logged in and can create new articles and edit/destroy your own or you're logged out and you can only see articles and login)
I'm using devise for the first part and that's working well but I can't get the second part working with CanCan. The the edit and destroy links for the articles don't appear when you're logged in and the direct URL (e.g. /articles/3/edit) still allows even if the article is for another user.
My ability.rb
is
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
and the view partial that lists articles _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>
With this setup, the edit/destroy links in the view don't show up unless there's a blanket can :manage, :all
, even can :manage, Article
doesn't work. As I mentioned above, it also isn't restricting the actual actions as you're able to deep link straight to editing an article and it permits it.
I'm not sure what I'm doing wrong here. It would be great to get some help.
Thanks in advance
Jason
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我设法解决了我的问题。我重置了我的环境(rvm - 重新安装了 gems 和 gemsets - ruby 1.9.2 和 Rails 3.0.0)并更改了一些代码,我遇到的所有问题都消失了(重定向循环,视图元素没有根据记录而改变)中,未经授权的控制器操作仍然是允许的)。我粘贴了
ability.rb
、articles_controller.rb
和_article_list.html.erb
。ability.rb
:我想现在这是有道理的,但是因为只有更新和删除应该适用于当前用户的文章,所以我将 CRUD 元素拆分为特定的。
articles_controller.rb
load_and_authorize_resource
有效,但我已经进行了特定授权!每个控制器操作中的行,因为我在底部有一个额外的操作。两者现在都可以工作。我将对@article 的引用更新为article 以引用
_article_list.html.rb
中列表中的当前文章:现在一切正常。感谢您在这里提供的帮助,希望这能帮助其他遇到此问题的人。
I managed to resolve my problem. I reset my environment (rvm - resintalled the gems and gemsets - ruby 1.9.2 and rails 3.0.0) and changed some of the code and all the issues I was having went away (redirect loop, view elements not changing based on being logged in, unauthorized controller actions still permissable). I've pasted
ability.rb
,articles_controller.rb
, and_article_list.html.erb
.ability.rb
:I guess it makes sense now but because only update and delete were supposed to be for the current user's articles, I split out the CRUD elements to be specific.
articles_controller.rb
load_and_authorize_resource
works but I've put specific authorize! lines in each controller action as I have an extra action at the bottom. Both now work.I updated the reference to @article to article to reference the current article in the list in
_article_list.html.rb
:All working now. Thanks for the help here and hopefully this will help someone else out if they run into this problem.
您匹配用户 ID 的条件不太正确。它应该是:
您要检查的属性映射到您要检查的值。
另外,您正在检查
user.nil?
当它不能为零时,因为您刚刚初始化了它。 (可能是尝试了很多事情的症状!)Your condition for matching a user id isn't quite right. It should be:
The attribute you want to check is mapped to the value you want to check against.
Also, you are checking for
user.nil?
when it can't be nil because you've just initialised it. (Probably a symptom of having tried lots of things!)你的捕获有效吗?如果取消注释 can :manage, :all 行,用户是否能够编辑他/她的帖子(当然还有其他人的帖子)?
您是否尝试过将 can :manage, Article, :user_id == user 更改为
我从未能够加载工作授权 - 尽管我怀疑我做错了什么。为了防止有人直接访问该网址,请在您文章的编辑操作中尝试添加以下内容
Does your catch work? If you uncomment the can :manage, :all line will a user be able to edit his/ her post ( along with everyone else's of course )?
Have you tried changing, can :manage, Article, :user_id == user to
I have never been able to get load an authorize to work- although I suspect that I was doing something wrong. To prevent someone from accessing the url directly, in your article's edit action, try adding this