在我的Rails应用程序中,有3个模型,由has_many :through
关联定义:
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
加入Administration
模型具有role
属性,我们用它来定义给定user
的给定calendar
的角色 - 所有者,编辑者或查看者
实际上,在应用程序中,用户可以是日历的所有者,也可以是其他日历的查看者。
我使用Devise实现了身份验证。
我还开始使用Pundit实施授权:授权目前适用于calendars
,其中users
可以根据roles
执行不同的操作。
更新:这是当前的CalendarPolicy
:
class CalendarPolicy < ApplicationPolicy
attr_reader :user, :calendar
def initialize(user, calendar)
@user = user
@calendar = calendar
end
def index?
user.owner?(calendar) || user.editor?(calendar) || user.viewer?(calendar)
end
def create?
true
end
def show?
user.owner?(calendar) || user.editor?(calendar) || user.viewer?(calendar)
end
def update?
user.owner?(calendar) || user.editor?(calendar)
end
def edit?
user.owner?(calendar) || user.editor?(calendar)
end
def destroy?
user.owner?(calendar)
end
end
现在,我想为管理模型实施Pundit策略,如下所示:
Index
,Show
,Create
,New
,Edit
,{{1} }和Update
对此日历管理的操作。Destroy
操作以查看日历的所有用户,然后执行Index
对他自己的政府采取行动,以及#34;离开日历&#34;。我的问题如下:
Destroy
和user
之间的连接存在,如上所述。calendar
,administration_id
和user_id
。calendar_id
和实际user
(这里是管理)。在Pundit的GitHub页面上,在Additional context部分,我们可以阅读以下内容:
附加背景
Pundit强烈建议您以这种方式为应用程序建模 您授权所需的唯一上下文是用户对象和 要检查授权的域模型。如果你找到了 你需要更多的背景,考虑一下你自己 授权正确的域模型,也许是另一个域模型(或者 围绕多个域模型的包装器)可以提供您的上下文 需要。
Pundit不允许您将其他参数传递给策略 正是这个原因。
但是,在极少数情况下,您可能需要根据更多内容进行授权 上下文,而不仅仅是当前已验证的用户。假设为 例如,授权依赖于IP地址 经过身份验证的用户。在这种情况下,一个选项是创建一个 包含用户和IP并将其传递给的特殊类 政策。
record
关联是否构成了非常罕见的情况之一&#34;上面提到过或者是否有更简单的方法来实现我的has_many :through
联接模型的授权?
答案 0 :(得分:1)
是的,这是极少数情况之一。
# calendar controller show
@calendar = something
@administration = @calendar.administration_of_current_user
authorize CalendarAdministrationContext
# pundit CalendarAdministrationContext
def initialize(user, administration, calendar)
@user = user
@administration = administration
@calendar = calendar
end
答案 1 :(得分:1)
我不认为,这是一个例外情况。 打破良好做法的原因是什么,所以在您提供的链接中明确说明了什么?
您只需在CalendarController中添加add_viewer
,add_editor
,remove_viewer
,remove_editor
个动作即可。
可以使用旧的CalendarPolicy
授权前两个。
class CalendarPolicy
# old staff here
def add_viewer?
user.is_owner?(calendar)
end
def add_editor?
user.is_owner?(calendar)
end
end
对于删除操作,您需要AdministrationPolicy
(我错了,说日历策略是enogh):
class AdministrationPolicy
attr_reader :user, :authorization
def remove_viwer?
authorization.viewer? and authorization.user == user
end
def remove_editor?
authorization.editor? and authorization.user == user
end
end