【问题标题】:CanCan allow actions only if the current_user was associated with a project可以仅当 current_user 与项目关联时才允许操作
【发布时间】:2023-08-01 05:52:01
【问题描述】:

我使用cancan 进行授权,我想根据多对多关系做一些限制。

实体

 User - has_many project_assignments
 User - has_many projects, through: :project_assignments

 User - has_many roles, through: :project_assignments

ProjectAssignment:user_id、project_id、role_id

我想让用户能够在Project and Toy 模型上执行完整的CRUD,前提是该项目是由用户创建的。 Toy 嵌套在 Project 下

Toy has many ProjectsProject has many ToyProjectToy

 if user.role? :moderator
   can :crud, [Project, Toy]
 end

我想我只需要限制project,因为toy 取决于project_id,我可以这样做吗?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 cancan


    【解决方案1】:

    我会尝试对第二个多对多使用某种 if 语句:

    can :crud, Project do |project|
      ProjectAssignment.where(user_id: user.id, project_id: project.id).any?
    end
    
    can :crud, ProjectToy do |project_toy|
      ProjectAssignment.where(user_id: user.id, project_id: project_toy.project.id).any?
      if can? :crud, ProjectToy
        can :crud, Toy do |toy|
          ProjectToy.where(toy_id: toy.id).any?
        end
      end
    end
    

    PS - 您可能需要小心 :crud 并将其替换为 [:edit, :update, :destroy, :delete] 然后给 :create 一个单独的罐子,因为如果用户正在创建一个项目/玩具第一次时,系统将找不到与他/她相关的任何玩具或项目,并且不提供访问权限。

    【讨论】:

    • 不能那样做,因为玩具和项目是多对多的关系
    • 原来是这样的?用户 -> 有很多 -> 项目分配 -> 属于 -> 项目 -> 有很多 -> 项目关键字 -> 属于 -> 玩具
    • 是的就是这样.. ProjectToy,而不是 ProjectKeywords 我刚刚编辑过...对不起
    • 谢谢,但我找到了一个更清洁的解决方案,也许更好。
    【解决方案2】:

    我找到了解决办法:

    在我的项目控制器中我添加了:

    load_and_authorize_resource through: :current_user

    在我的玩具控制器中我添加了:

    load_and_authorize_resource project, through: :current_user load_and_authorize_resource :toy, through: :project

    在我的技能文件中:

    if user.role? :moderator
       can :crud, :all or [Project, Toy]
    end
    

    一切正常,我已将一个用户分配给多个项目,并且它可以访问每个项目。

    【讨论】: