3

我有一个具有以下模型的 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

对于每个日历,用户只能具有以下三个角色之一OwnerEditorViewer

这些角色目前没有存储在字典或常量中,只是通过不同的方法作为字符串(“Ower”、“Editor”、“Viewer”)分配给管理部门。

模型上的身份验证User是通过 Devise 处理的,并且该current_user方法正在运行。

为了只允许登录用户访问应用内资源,我已经在和控制器中添加了该before_action :authenticate_user!方法。calendarsadministrations

现在,我需要实现一个基于角色的授权系统,所以我只是安装了CanCanCangem。

这是我想要实现的目标:

  • 所有(登录的)users 都可以创建新calendar的s。
  • 如果 auser是 a 的 the ownercalendar那么他可以managethecalendar和所有administration属于 this 的 s calendar,包括他自己的administration
  • 如果一个用户是editor一个calendar,那么他可以readupdate这个日历,并销毁他的administration.
  • 如果 auserviewera calendar,那么他可以readthiscalendardestroyhis 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,所以我对我的代码不是很有信心,希望得到一些验证或改进建议。

那么,这段代码会起作用吗,它能让我实现我所需要的吗?

更新:使用当前代码,当我以用户身份登录并访问另一个用户日历的 calendars#show 页面时,我实际上可以访问日历,这是我不应该的。

所以,显然,我的代码不起作用。

知道我做错了什么吗?

更新 2:我认为我的代码中有错误,因为我使用:model而不是Model允许users 对给定的model.

但是,代码仍然无法正常工作。

知道这里可能有什么问题吗?

更新 3:问题可能是由于我if user.role?(:owner)用来检查用户的角色是否设置为所有者,而在数据库中角色实际上被定义为“所有者”(作为字符串)?

更新4:我继续做一些研究,我意识到我犯了两个错误。

  1. 我没有添加load_and_authorize_resourcecalendarsadministrations控制器。

  2. 我在我的方法中定义了两个属性和两个参数——<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

我该如何解决这个问题?

4

1 回答 1

1

role?用户模型没有这样的方法。Cancancan 文档假定示例中存在这种方法是错误的。

要解决此问题,您应该改为:

if user.role == 'Owner'
  ...
elsif user.role == 'Editor'
  ...
elsif user.role == 'Viewer'
  ...
于 2015-09-22T20:11:31.050 回答