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