【问题标题】:Ability: conditions dependent on the object (allow :create only for team_members)能力:取决于对象的条件(允许:仅为团队成员创建)
【发布时间】:2018-08-22 06:44:06
【问题描述】:

设置

一个基本的酒店设置,其中usershotel 的团队成员。它在 Rails 5.2 中使用 cancancandevise

rails g scaffold User name
rails g scaffold Hotel name
rails g scaffold TeamMembership user:references hotel:references
rails g scaffold Reservation starts_on:date ends_on:date hotel:references
rails g scaffold CheckIn hotel:references reservation:references

hotels 通过has_many :users, through: :team_memberships 连接到users。反之亦然 usershotels

config/routes.rb

resources :hotels do
  resources :reservations
  resources :check_ins
end

app/controllers/check_ins_controller.rb

class CheckInsController < ApplicationController
  before_action :authenticate_user!
  load_and_authorize_resource :hotel
  load_and_authorize_resource :check_in, :through => :hotel
[...]

app/models/ability.rb

[...]
can [:read, :destroy], CheckIn, hotel_id: user.hotel_ids
can [:create], CheckIn
[...]

问题/疑问

在某个视图中我有这个代码:

<% if can? :create, CheckIn %>
  <%= link_to 'Create Check-In', new_hotel_check_in_path(@hotel) %>
<% end %>

它应该只对@hotel 的团队成员可见。

ability.rb 的第一行工作正常,但第二行不起作用,因为任何人都可以创建一个新的check_in,但只有team_memberships 应该能够为他们的酒店创建一个新的check_in .

解决此问题的最佳方法是什么?显然,该链接不应显示,但/hotels/:hotel_id/check_ins/new URL 应该可供非团队成员的任何人访问。

【问题讨论】:

    标签: ruby-on-rails authorization ruby-on-rails-5 cancan cancancan


    【解决方案1】:

    这是一个常见问题,这是business 逻辑与authorization 逻辑相交的地方。

    关于这个问题有很多意见。

    1) 很多人认为这种交叉是不可接受的。他们会建议您以这种方式做您需要的事情(分离业务和授权逻辑)

    <% if can?(:create, CheckIn) && current_user.member_of?(@hotel) %>
      <%= link_to 'Create Check-In', new_hotel_check_in_path(@hotel) %>
    <% end %>
    

    2) 如果你确定你需要这个,你可以这样做:

    Hotel模型添加新权限:

    can [:check_in], Hotel do |hotel|
      user.member_of?(hotel)
    end
    

    然后在视图中:

    <% if can?(:create, CheckIn) && can?(:check_in, @hotel) %>
      <%= link_to 'Create Check-In', new_hotel_check_in_path(@hotel) %>
    <% end %>
    

    在控制器中:

    class CheckInsController < ApplicationController
      # ...
      def new
        authorize! :check_in, @hotel
        # ...
      end
    end
    

    【讨论】:

    • 我了解视图中 can?() 链接的解决方案,但如何确保对纯 URL 的访问安全?即使非团队成员看不到链接,他/她也可以猜到 URL,因为它是 RESTful。
    • 我不希望非团队成员创建CheckIn
    • 编辑了答案。添加了有关控制器的更多信息
    【解决方案2】:

    试试这个:

    can [:create], CheckIn if user.team_memberships.present?
    

    can [:create], CheckIn if user.hotels.present?
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-31
      • 2021-09-01
      相关资源
      最近更新 更多