Rails - 寻求与各种嵌套资源兼容的干授权方法

时间:2010-04-16 02:53:32

标签: ruby-on-rails routing rest

共识是你不应该嵌套超过1级的资源。所以,如果我有3个这样的模特 (以下只是假设情况)

用户has_many Houses has_many Tenants

并遵守以上所述

map.resources :users, :has_many => :houses
map.resorces :houses, :has_many => :tenants

现在我希望用户能够编辑他们的房屋和他们的租户详细信息,但我想阻止他们通过伪造网址的user_id部分来尝试编辑其他用户房屋和租户。所以我创建了一个像这样的before_filter

 def prevent_user_acting_as_other_user
        if User.find_by_id(params[:user_id]) != current_user()
            @current_user_session.destroy
            flash[:error] = "Stop screwing around wiseguy"
            redirect_to login_url()
            return
        end
    end

对于那些容易的房子,因为user_id是通过

传递的
edit_user_house_path(@user, @house)

但是在tenents案例中

tenant house_tenent_path(@house)

没有传递用户ID。但我可以通过@ house.user.id来获取用户ID,但是id必须将上面的代码更改为此。

    def prevent_user_acting_as_other_user
    if params[:user_id]
        @user = User.find(params[:user_id]
    elsif params[:house_id]
        @user = House.find(params[:house_id]).user
    end
    if @user != current_user()
        #kick em out
    end
end

它完成了这项工作,但我想知道是否有更优雅的方式。每次我添加一个需要防止用户伪造的新资源时,我必须不断添加条件。我不认为会有很多案例,但如果有的话,我想知道更好的方法。

1 个答案:

答案 0 :(得分:1)

执行以下操作:

class User < ActiveRecord::Base
  has_many :houses
  has_many :tenants
end

class House < ActiveRecord::Base
  belongs_to :user
  has_many :tenants
end

class Tenant < ActiveRecord::Base
  belongs_to :user
  belongs_to :house
end

在您的过滤器中执行以下操作:

def kill_session(message)
  @current_user_session.destroy
  flash[:error] = message
   redirect_to login_url()
end

def prevent_user_acting_as_other_user
  if    params[:user_id]  and params[:user_id] != @current_user.id
    kill_session("You don't have access to this page")
  elsif params[:house_id] and !@current_user.houses.exists?(params[:house_id])
    kill_session("You don't have access to this page")
  elsif params[:tenant_id] and !@current_user.tenants.exists?(params[:tanant_id])
    kill_session("You don't have access to this page")
  end
end