简体   繁体   English

如何执行授权?

[英]How to implement authorization?

Suppose, I have a model called Animal. 假设我有一个叫做Animal的模型。 This model contains enum attribute with two possible states. 该模型包含具有两个可能状态的enum属性。

class Animal < ActiveRecord::Base
  enum kind: [ :cat, :dog ]
end

Then in my controller I create different instance variables. 然后在我的控制器中创建不同的实例变量。

class AnimalsController < ApplicationController
  def index
    @cats = Animal.cat
    @dogs = Animal.dog
  end
end

In my view I got two separate collections. 我认为我有两个单独的收藏。

<h1>Animals</h1>

<%= render partial: 'animals/cat', collection: @cats, as: :cat %>
<%= render partial: 'animals/dog', collection: @dogs, as: :dog %>

How can I make an authorization to be able to edit the first collection's resources and not to be able to edit the second ones? 我该如何授权才能编辑第一个集合的资源而不能编辑第二个集合的资源?

The following approach won't work because it works only for one action entirely. 以下方法将不起作用,因为它仅完全适用于一项操作。

before_action :current_user_only, except: [:edit]

So, how do I implement that kind of authorization? 那么,如何实现这种授权?

Thanks in advance! 提前致谢!

Authorization - in any capacity - is typically denoted by two patterns: 授权(以任何身份)通常由两种模式表示:

  • record/object based 基于record/object
  • role/user based 基于role/user

What you seem to need is record/object based authorization; 您似乎需要的是基于record/object的授权; whereby a user can edit an object if it matches certain criteria. 因此,如果对象符合特定条件,则用户可以编辑该对象。

The most efficient way to do this in Rails is with a gem called Pundit , although I prefer CanCanCan (originally CanCan ): 在Rails中,最有效的方法是使用名为Pundit的gem,尽管我更喜欢CanCanCan (最初是CanCan ):

#Gemfile 
gem "pundit"

#app/policies/animal.rb
class AnimalPolicy
  attr_reader :user, :animal

  def initialize(user, animal)
    @user   = user
    @animal = animal
  end

  def edit?
    animal.cat?
  end

  def update?
    animal.cat?
  end
end

#app/controllers/animals_controller.rb
class AnimalsController < ApplicationController
   def edit
      @animal = Animal.find params[:id]
      authorize @animal
   end

   def update
      @animal = Animal.find params[:id]
      authorize @animal
   end
end

You can then validate on the front-end: 然后,您可以在前端进行验证:

<% if policy(animal).update? %>
   <%= link_to "Edit", animal %>
<% end %>

-- -

This gives you the ability to allow the user to perform whichever actions you deem appropriate. 这使您能够允许用户执行您认为适当的任何操作。


Update 更新资料

Since you wish to evaluate users as well as objects, you're quite fortunate that both Pundit and CanCanCan support users by default: 由于您希望评估用户和对象,因此很幸运, PunditCanCanCan都默认支持users

#app/policies/animal.rb
class AnimalPolicy
  attr_reader :user, :animal

  def initialize(user, animal)
    @user   = user
    @animal = animal
  end

  def edit?
    user.moderator? && animal.cat?
  end

  def update?
    user.moderator? && animal.cat?
  end
end

The ultimate point to remember is that authorization is a boolean pattern - unless true deny access . 要记住的最后一点是,授权是一种布尔模式- unless true deny access This means that you just have to provide the conditional logic in your authorization systems (as above), to return either true or false . 这意味着您只需要在授权系统中提供条件逻辑(如上所述)即可返回truefalse

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM