Rails 3基于用户权限的ActiveRecord验证

d11*_*wtq 10 validation permissions activerecord ruby-on-rails ruby-on-rails-3

我正在将代码从非标准自定义PHP框架内置的应用程序转移到Ruby on Rails(版本3).在PHP版本中,所有控制器都非常胖,有薄模型,我一直不同意,所以我很享受Rails在模型级别进行验证的方式,这可能是这些胖控制器中发生情况的90%目前.

我面临的一个问题是,不确定如何解决问题,那就是基于谁对模型进行更改的不同验证规则.例如,管理员或记录的原始创建者应该能够执行诸如将记录标记为已删除(软删除)之类的操作,而其他人则不应该这样做.

class Something < ActiveRecord::Base
  ...
  validates :deleted, :owned_by_active_user => true
  ...
end

class OwnedByActiveUserValidator < ActiveModel::EachValidator
  validate_each(record, attr_name, attr_value)
    # Bad idea to have the model know about things such as sessions?
    unless active_user.admin? || active_user.own?(record)
      record.errors.add :base, "You do not have permission to delete this record"
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

由于模型本身(理论上)不知道正在进行更改的用户,所以做这种事情的"轨道方式"是什么?我应该将活动用户设置为记录上的虚拟属性(实际上没有保存到DB),还是应该只在控制器中执行这些检查?我不得不承认,让模型检查活动用户的权限确实很奇怪,并且在测试模型时增加了复杂性.

我渴望在模型中尽可能多地保留这一点的一个原因是因为我想提供API(通过OAuth访问)和网站,而不需要复制太多代码,例如这些类型的权限检查.

yfe*_*lum 11

管理授权或将授权委托给授权层实际上是控制器的工作.模型不应该知道,也不必关心谁当前登录以及他/她的权限是什么 - 这是控制器的工作,或控制器委托的任何auth帮助层.

你应该:deleted在- attr_accessible通过以质量分配new,createupdate_attributes.deleted=如果经过身份验证的用户已获得授权,则控制器应单独检查已验证用户的授权并单独调用.

有几个授权库和框架可以帮助授权或充当授权层,例如cancan.


Mis*_*cha 6

我会before_filter在我的控制器中解决这个问题,而不是在我的模型中使用验证.

class SomethingController < ApplicationController
  before_filter :require_delete_permission, :only => [:destroy]

  def destroy
    # delete the record
  end

  private

  def require_delete_permission
    unless current_user.is_admin || record.owner == current_user
      flash[:error] = 'You do not have delete permissions'
      redirect_to somewhere
    end
  end
end
Run Code Online (Sandbox Code Playgroud)