我正在尝试使用Rails的devise / cancan获得一些基本的身份验证/授权。而不是使用像Ryan B的截屏和其他示例的角色,我正在尝试做一些基本的事情:
1 - 用户可以登录
2 - 用户只能编辑/销毁他们自己的文章(没有角色,您既可以登录也可以创建新文章并编辑/销毁自己的文章,或者您已经注销,而且只能查看文章和登录)
我正在使用设计第一部分并且运行良好但我无法让第二部分与CanCan合作。当您登录时,文章的编辑和销毁链接不会出现,并且直接URL(例如/ articles / 3 / edit)仍然允许,即使该文章是针对其他用户的。
我的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
也不起作用。正如我上面提到的,它也不会限制实际操作,因为您可以直接深入链接到编辑文章并允许它。
我不确定我在这里做错了什么。得到一些帮助会很棒。
提前致谢
杰森
答案 0 :(得分:2)
我设法解决了我的问题。我重置了我的环境(rvm - 重新设置了宝石和gemsets - 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>
现在全部工作。感谢您的帮助,希望如果他们遇到这个问题,这将有助于其他人。
答案 1 :(得分:1)
您匹配用户ID的条件不太对。它应该是:
can :manage, Article, :user_id => user.id
您要检查的属性将映射到您要检查的值。
另外,当你刚刚初始化它时,你正在检查user.nil?
什么时候它不能为零。 (可能是尝试过很多东西的症状!)
答案 2 :(得分:0)
你的捕获量是否有效?如果您取消注释can:manage,:所有行都可以让用户编辑他/她的帖子(当然还有其他人)?
您是否尝试过更改,可以:manage,Article,:user_id == user to
can :manage, Article do |article|
article.try(:user) == user
我从来没有能够加载授权工作 - 尽管我怀疑我做错了什么。要防止某人直接访问该网址,请在文章的编辑操作中尝试添加此
unauthorized! if cannot? :edit, @article