before_filter:require_owner

我有许多资源(旅行,计划等),其行动应仅限于资源所有者。

如何使用ApplicationController中定义的#require_owner方法实现代码来实现此目的? 理想情况下,代码将查找所有者的inheritance链,因此before_filter将处理:belongs_to:travel that belongs_to:user的注释。

class TripsController < ApplicationController belongs_to :member before_filter :require_owner ... end 

我没有完全按照描述(评论真的由旅行老板拥有吗?),但是稍微扩大了jonnii的答案,这里是一个限制行程控制器的例子:

 class ApplicationController < ActionController::Base ... protected # relies on the presence of an instance variable named after the controller def require_owner object = instance_variable_get("@#{self.controller_name.singularize}") unless current_user && object.is_owned_by?(current_user) resond_to do |format| format.html { render :text => "Not Allowed", :status => :forbidden } end end end end class TripsController < ApplicationController before_filter :login_required # using restful_authentication, for example # only require these filters for actions that act on single resources before_filter :get_trip, :only => [:show, :edit, :update, :destroy] before_filter :require_owner, :only => [:show, :edit, :update, :destroy] ... protected def get_trip @trip = Trip.find(params[:id]) end end 

假设模型看起来像这样:

 class Trip < ActiveRecord::Base belongs_to :owner, :class_name => 'User' ... def is_owned_by?(agent) self.owner == agent # or, if you can safely assume the agent is always a User, you can # avoid the additional user query: # self.owner_id == agent.id end end 

login_required方法(由restful_authentication或authlogic提供或依赖auth插件)确​​保用户登录并为用户提供current_user方法, get_trip设置trip实例变量,然后在require_owner检查。

如果模型已经实现了is_owned_by? ,那么这个模式可以适用于任何其他资源is_owned_by? 方法。 如果您在资源是注释时尝试检查它,那么您将在CommentsController

 class CommentsController < ApplicationController before_filter :login_required # using restful_authentication, for example before_filter :get_comment, :only => [:show, :edit, :update, :destroy] before_filter :require_owner, :only => [:show, :edit, :update, :destroy] ... protected def get_comment @comment = Comment.find(params[:id]) end end 

使用Comment模型,如下所示:

 class Comment < ActiveRecord::Base belongs_to :trip # either # delegate :is_owned_by?, :to => :trip # or the long way: def is_owned_by?(agent) self.trip.is_owned_by?(agent) end end 

确保在执行此操作时检查日志,因为如果您不小心,依赖关联的检查可能会导致大量查询。

有几种不同的方法可以做到这一点。 你一定要查看acl9插件( http://wiki.github.com/be9/acl9/tutorial-securing-a-controller )。

如果您决定自己想要这样做,我建议您做以下事情:

 class Trip < ... def owned_by?(user) self.user == user end end class Comment < ... delegate :owned_by?, :to => :trip end # in your comment controller, for example before_filter :find_comment before_filter :require_owner def require_owner redirect_unless_owner_of(@commemt) end # in your application controller def redirect_unless_owner_of(model) redirect_to root_url unless model.owned_by?(current_user) end 

请原谅我,如果有任何语法错误=)我希望这有帮助!

Acl9是一个授权插件。 我会给你链接,但我没有剪切和粘贴我的iPhone。 如果我到达计算机时没有其他人提供链接,我会帮你的。 或者你可以谷歌。 任何。 🙂

我刚刚开始使用它,但它有一个非常简单的界面。 您只需创建角色表和roles_user 。 如果您决定使用它,请告诉我它是怎么回事。

或者只使用inheritance的资源:

InheritedResources还引入了另一个名为begin_of_association_chain的方法。 当你想要根据@current_user创建资源并且你有像“account / projects”这样的url时,它主要用于。 在这种情况下,您必须在您的操作中执行@ current_user.projects.find或@ current_user.projects.build。

你可以通过这样做来处理它:

 class ProjectsController < InheritedResources::Base protected def begin_of_association_chain @current_user end end