我有一个带有以下型号的Rails应用程序:
class User < ActiveRecord::Base
has_many :administrations
has_many :calendars, through: :administrations
end
class Calendar < ActiveRecord::Base
has_many :administrations
has_many :users, through: :administrations
end
class Administration < ActiveRecord::Base
belongs_to :user
belongs_to :calendar
end
对于给定的calendar
,user
有一个role
,它在administration
联接模型中定义。
对于每个日历,用户只能拥有以下三种角色中的一种:Owner
,Editor
或Viewer
。
这些角色目前没有存储在字典或常量中,只能通过不同的方法作为字符串(“Ower”,“Editor”,“Viewer”)分配给管理。
User
模型上的身份验证是通过Devise处理的,current_user
方法正在运行。
为了仅允许登录用户访问应用内资源,我已在before_action :authenticate_user!
和calendars
控制器中添加了administrations
方法。
现在,我需要实现一个基于角色的授权系统,所以我刚刚安装了CanCanCan
gem。
这是我想要实现的目标:
user
可以创建新的calendar
。user
是owner
的{{1}},那么他可以calendar
manage
以及属于calendar
的所有administration
对此calendar
,包括他自己的administration
。editor
的{{1}},那么他可以calendar
和read
此日历,并销毁他的update
。administration
是user
的{{1}},那么他viewer
calendar
和read
calendar
destroy
administration
}。为了实现上述目标,我提出了以下ability.rb
文件:
class Ability
include CanCan::Ability
def initialize(user, calendar)
user ||= User.new
calendar = Calendar.find(params[:id])
user can :create, :calendar
if user.role?(:owner)
can :manage, :calendar, :user_id => user.id
can :manage, :administration, :user_id => user.id
can :manage, :administration, :calendar_id => calendar.id
elsif user.role?(:editor)
can [:read, :update], :calendar, :user_id => user.id
can :destroy, :administration, :user_id => user.id
elsif user.role?(:viewer)
can [:read], :calendar, :user_id => user.id
can :destroy, :administration, :user_id => user.id
end
end
end
由于我没有尝试使用Rails,这是我第一次使用CanCanCan
,我对我的代码不太自信,并希望得到一些验证或改进建议。
那么,这段代码是否有效,是否可以让我实现我的需求?
更新:使用当前代码,当我以用户身份登录,并访问其他用户日历的日历#show页面时,我实际上可以访问日历,我不应该这样做。< / p>
所以,显然,我的代码无效。
知道我做错了什么?
更新2 :我认为我的代码中存在错误,因为我使用:model
代替Model
来允许user
执行操作给定model
。
但是,代码仍无效。
知道这里可能出现什么问题?
更新3 :问题可能是由于我使用if user.role?(:owner)
检查用户的角色是否设置为所有者,而在数据库中角色实际定义为“所有者”(作为字符串)?
更新4:我继续做一些研究,我意识到我犯了两个错误。
我没有将load_and_authorize_resource
添加到calendars
和administrations
控制器。
我在两个参数中定义了两个参数 - initialize(user, calendar)
- 而不是initialize
方法中的一个。
因此,更新了两个控制器以及ability.rb文件,如下所示:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.role?(:owner)
can :manage, Calendar, :user_id => user.id
can :manage, Administration, :user_id => user.id
can :manage, Administration, :calendar_id => calendar.id
elsif user.role?(:editor)
can [:read, :update], Calendar, :user_id => user.id
can :destroy, Administration, :user_id => user.id
elsif user.role?(:viewer)
can [:read], Calendar, :user_id => user.id
can :destroy, Administration, :user_id => user.id
end
end
end
现在,当我尝试访问不属于current_user
的日历时,出现以下错误:
NoMethodError in CalendarsController#show
undefined method `role?' for #<User:0x007fd003dff860>
def initialize(user)
user ||= User.new
if user.role?(:owner)
can :manage, Calendar, :user_id => user.id
can :manage, Administration, :user_id => user.id
can :manage, Administration, :calendar_id => calendar.id
我如何解决这个问题?
答案 0 :(得分:1)
User模型没有这样的方法role?
。假设示例中存在这样的方法,Cancancan文档是错误的。
要解决此问题,您应该执行以下操作:
if user.role == 'Owner'
...
elsif user.role == 'Editor'
...
elsif user.role == 'Viewer'
...