我们的项目遇到这样一个问题,相信大家也经常遇到: 高级管理员可以将任意用户的 role 字段修改为管理员, 而下面的二级管理员,最多将任意用户的 role 字段修改为三级管理员; 超级管理员可以将授权的数目修改为任意值, 而下面的管理员只能小于某个数值等等。
简单的说就是基于角色的字段验证,不知道你们是怎么做的。
http://asciicasts.com/episodes/192-authorization-with-cancan cancan 可以解决你的问题
#3 楼 @leomayleomay 但是我们一个 model 有多个 action 都有修改这个 model 的功能,而且更为重要的是,我们希望能用到 validate 提供的报错到字段的功能。
你这里只是判断用户能不能 update,而不是控制具体的字段的值。
比如你可以转账(update),但是不能转账超过你拥有钱的数目。
但是,管理员可以“印钞”,他可以给任何人转账无限多的钱。
这些都是已经进了 update action,但是每个人有限制的做操作。
@bydmm 5 楼,如果你的 update 有这么多职责,是不是违背了单一职责原则?分出新的 action,或者针对你的 domain 分离出新的 controller 都是可以考虑的方向
几年前做的一个 PHP RBAC, 用controller#action做权限控制,希望能在思路上帮到你: https://code.google.com/p/fleastart/
有视频,不用管 PHP,看思路就可以 https://code.google.com/p/fleastart/downloads/list
我思索了一下感觉你们说的很有道理,特别是在 model 加了太多验证,估计对程序的性能也会有很大的影响。 #9 楼 @leomayleomay 如果用户希望在同一个界面修改这些信息的话(四处寻找功能也有些不方便),看来要使用 ajex 来调用这些不同的 action 了。 #10 楼 @Peter 感谢!我之前学习过 thinkphp 的 RBAC 他采用的就是此类思路。
我想了想,一个 update 接口的话在发布 api 的时候有好处。做成校验的话大概是这样
validates :xxx, length: { maximum: aaa }, :if => :role_admin?
validates :xxx, length: { maximum: bbb }, :if => :role_editor?
attr_accessor :update_role
def role_admin?
update_role == :admin
end
def role_editor?
update_role == :editor
end
在 controller 调用的时候
some_object.update_attributes object_params.merge(:update_role => current_user.role_for(@project))
我倾向如 Rei 所言,通过 validates 的 if 选项传入 role 属性的方式。
此外有一个 gem 是做 Model-level authorization 的 https://github.com/stffn/declarative_authorization
个人不太喜欢把权限过滤放在 model 里面 不过,如果你的程序有很多类似的需求,可以考虑下的。