2011-03-02 68 views
3

作为新手ROR开发者,我一直在想办法保护某些方法,以确保正确的用户更新他们自己的内容。这是我的方法的一个例子。保护方法的好习惯

你会推荐一个更清洁的方式或更好的方式来完成这样的任务吗?

# Example Controller 
class Owner::PropertiesController < Owner::BaseController 

    def index 
    end 

    etc..... 

    def update 
    @property = Property.find(params[:id]) 

    # Check correct owner 
    check_owner(:owner_id => @property.owner_id) 

    if @property.update_attributes(params[:property]) 
     redirect_to([:owner, @property], :notice => 'Property was successfully updated.') 
    else 
     render :action => "edit" 
    end 

    end 

    def destroy 
    @property = Property.find(params[:id]) 

    # Check correct owner 
    check_owner(:owner_id => @property.owner_id) 

    @property.destroy 
    redirect_to(owner_properties_url) 
    end 

    private 

    def check_owner p = {} 
    if p[:owner_id] != session[:owner_id] 
     redirect_to([:owner, @property], :notice => "Property not found.") 
    end 
    end 

回答

0

您可以使用像declarative_authorization这样的宝石来做到这一点。如果你想自己做,我会建议干脆晒你的代码一点点:

class Owner::PropertiesController < Owner::BaseController 
    before_filter :check_owner, :only => [:update, :destroy] 

    def update 
    if @property.update_attributes(params[:property]) 
     redirect_to([:owner, @property], :notice => 'Property was successfully updated.') 
    else 
     render :action => "edit" 
    end 
    end 

    def destroy 
    @property.destroy 
    redirect_to(owner_properties_url) 
    end 

    private 

    def check_owner 
    @property = Property.find(params[:id] 

    if @property.owner_id != session[:owner_id] 
     redirect_to([:owner, @property], :notice => "Property not found.") and return 
    end 
    end 
end 

此外,您可以通过所有者筛选属性,以确保谁是不是所有者不能与交互的用户属性不是他/她的。例如:

def update 
    @owner = Owner.find(session[:owner_id]) 
    @property = @owner.properties.find(params[:id]) 
    redirect_to unauthorized_page and return if @property.nil? 
end 

这将迫使您正在搜索是属于会话的那些属性[:owner_id],而不是性质的整个宇宙。这意味着会话[:owner_id]不拥有的属性甚至不会被考虑。然后,您可以将此代码放入before_filter中,以便它可以在多个操作中重用。

+0

感谢您的所有评论。我更喜欢保持干燥,这很好。我不想因为拥有许多宝石而混乱,所以只需使用并通过过滤器传递属性就是完美的。 TY – Lee 2011-03-02 00:48:46

0

考虑使用所讨论的技术here

仅在您的用户模型和查询属性内通过该关联添加关联。

property = Property.find(params[:id]) 
# vs 
property = current_user.properties.find(params[:id]) 
4

这是这样做的一种方式,虽然有点笨拙的国际海事组织。我倾向于采取以下方法在这些情况下:

class FoosController < ApplicationController 
    before_filter :find_user 

    def create 
    @foo = @user.foos.build 
    end 

    def update 
    @foo = @user.foos.find(params[:id]) 
    end 

    private 

    def find_user 
    @user = User.find(session[:current_user_id]) 
    end 
end 

这是一个很大清洁剂,以及意图非常明显:你只在试图找到一个Foo属于@user感兴趣。这种方法的缺点之一是,如果所有权规则发生变化,则需要一些工作来改变它,但我发现它对我来说合理地合理。