如何实现授权?
How to implement authorization?
假设,我有一个名为 Animal 的模型。此模型包含具有两种可能状态的枚举属性。
class Animal < ActiveRecord::Base
enum kind: [ :cat, :dog ]
end
然后在我的控制器中创建不同的实例变量。
class AnimalsController < ApplicationController
def index
@cats = Animal.cat
@dogs = Animal.dog
end
end
在我看来,我得到了两个独立的集合。
<h1>Animals</h1>
<%= render partial: 'animals/cat', collection: @cats, as: :cat %>
<%= render partial: 'animals/dog', collection: @dogs, as: :dog %>
如何才能授权能够编辑第一个集合的资源而不能编辑第二个?
以下方法行不通,因为它完全只对一个动作有效。
before_action :current_user_only, except: [:edit]
那么,我该如何实现这种授权呢?
提前致谢!
授权 - 以任何身份 - 通常由两种模式表示:
record/object
基于
role/user
基于
您似乎需要的是基于 record/object
的授权;如果对象符合特定条件,则用户可以编辑该对象。
在 Rails 中执行此操作的最有效方法是使用名为 Pundit
, although I prefer CanCanCan
(originally CanCan
的 gem):
#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
然后您可以在 front-end:
上验证
<% if policy(animal).update? %>
<%= link_to "Edit", animal %>
<% end %>
--
这使您能够允许用户执行您认为合适的任何操作。
更新
由于您希望评估用户和对象,您很幸运 Pundit
和 CanCanCan
默认都支持 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
要记住的最后一点是授权是一个布尔模式 - unless true deny access
。这意味着您只需在授权系统中(如上所述)向 return true
或 false
.
提供条件逻辑
假设,我有一个名为 Animal 的模型。此模型包含具有两种可能状态的枚举属性。
class Animal < ActiveRecord::Base
enum kind: [ :cat, :dog ]
end
然后在我的控制器中创建不同的实例变量。
class AnimalsController < ApplicationController
def index
@cats = Animal.cat
@dogs = Animal.dog
end
end
在我看来,我得到了两个独立的集合。
<h1>Animals</h1>
<%= render partial: 'animals/cat', collection: @cats, as: :cat %>
<%= render partial: 'animals/dog', collection: @dogs, as: :dog %>
如何才能授权能够编辑第一个集合的资源而不能编辑第二个?
以下方法行不通,因为它完全只对一个动作有效。
before_action :current_user_only, except: [:edit]
那么,我该如何实现这种授权呢?
提前致谢!
授权 - 以任何身份 - 通常由两种模式表示:
record/object
基于role/user
基于
您似乎需要的是基于 record/object
的授权;如果对象符合特定条件,则用户可以编辑该对象。
在 Rails 中执行此操作的最有效方法是使用名为 Pundit
, although I prefer CanCanCan
(originally CanCan
的 gem):
#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
然后您可以在 front-end:
上验证<% if policy(animal).update? %>
<%= link_to "Edit", animal %>
<% end %>
--
这使您能够允许用户执行您认为合适的任何操作。
更新
由于您希望评估用户和对象,您很幸运 Pundit
和 CanCanCan
默认都支持 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
要记住的最后一点是授权是一个布尔模式 - unless true deny access
。这意味着您只需在授权系统中(如上所述)向 return true
或 false
.