我有一个具有以下模型的 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
的 , auser
具有在连接模型role
中定义的。administration
对于每个日历,用户只能具有以下三个角色之一Owner
:Editor
或Viewer
。
这些角色目前没有存储在字典或常量中,只是通过不同的方法作为字符串(“Ower”、“Editor”、“Viewer”)分配给管理部门。
模型上的身份验证User
是通过 Devise 处理的,并且该current_user
方法正在运行。
为了只允许登录用户访问应用内资源,我已经在和控制器中添加了该before_action :authenticate_user!
方法。calendars
administrations
现在,我需要实现一个基于角色的授权系统,所以我只是安装了CanCanCan
gem。
这是我想要实现的目标:
- 所有(登录的)
user
s 都可以创建新calendar
的s。 - 如果 a
user
是 a 的 theowner
,calendar
那么他可以manage
thecalendar
和所有administration
属于 this 的 scalendar
,包括他自己的administration
。 - 如果一个用户是
editor
一个calendar
,那么他可以read
和update
这个日历,并销毁他的administration
. - 如果 a
user
是viewer
acalendar
,那么他可以read
thiscalendar
和destroy
hisadministration
。
为了实现上述内容,我提出了以下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
,所以我对我的代码不是很有信心,希望得到一些验证或改进建议。
那么,这段代码会起作用吗,它能让我实现我所需要的吗?
更新:使用当前代码,当我以用户身份登录并访问另一个用户日历的 calendars#show 页面时,我实际上可以访问日历,这是我不应该的。
所以,显然,我的代码不起作用。
知道我做错了什么吗?
更新 2:我认为我的代码中有错误,因为我使用:model
而不是Model
允许user
s 对给定的model
.
但是,代码仍然无法正常工作。
知道这里可能有什么问题吗?
更新 3:问题可能是由于我if user.role?(:owner)
用来检查用户的角色是否设置为所有者,而在数据库中角色实际上被定义为“所有者”(作为字符串)?
更新4:我继续做一些研究,我意识到我犯了两个错误。
我没有添加
load_and_authorize_resource
到calendars
和administrations
控制器。我在我的方法中定义了两个属性和两个参数——<code>initialize(user, calendar)——而不是一个
initialize
。
因此,更新了两个控制器,以及能力.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
我该如何解决这个问题?