Der*_*cni 4 ruby-on-rails pundit
我的创建、更新和销毁“喜欢”的政策要求用户登录。
我对该政策的措辞如下:
class LikePolicy < ApplicationPolicy
def create?
user && record.user_id == user.id
end
def update?
create?
end
def destroy?
create?
end
end
Run Code Online (Sandbox Code Playgroud)
我的 like#create 控制器操作如下:
def create
@article = Article.find(params[:article_id])
@like = @article.likes.new(user_id: current_user.id, value: params[:value] == 1 : 1 ? -1)
authorize(@like)
@like.save
redirect_to @article
end
Run Code Online (Sandbox Code Playgroud)
然而,使用策略来确认用户已登录是不合逻辑的,因为代码将在前面的代码中失败,例如引用 current_user 的地方。
这是如何授权包含 user_id 的记录的公认做法吗?
通常,我会使用单独的身份验证检查来检查用户是否已登录。如果您的应用程序主要需要用户登录,那么在授权之前进行身份验证检查将确保您始终拥有current_user.
另外,对于创建,我发现我不喜欢调用 new/authorize/save 只是为了确保用户正在创建属于他们的对象的想法。这是与授权实际上无关的应用程序逻辑。相反,对于创建,您可以简单地传递类,Pundit 不介意。
根据您是否首先进行身份验证检查,您的授权可以简单地返回 true,或者您可以检查!user.nil.
我发现 Pundit 的最后一件事是尝试将逻辑抽象为某种自记录方法。它使阅读专家策略变得更容易,还允许您将逻辑片段抽象到 ApplicationPolicy 或通过模块包含它们。在下面的示例中,is_owner?可以很容易地进行抽象,因为它在许多情况下都可用。
示例 1:先进行身份验证,然后再授权
class LikesController
# Either from devise, or define in ApplicationController
before_action :authenticate_user!
def create
authorize(Like)
article = Article.find(params[:article_id])
article.likes.create(user_id: current_user.id, ...)
redirect_to article
end
end
class LikePolicy < ApplicationPolicy
def create?
true
end
def update?
is_owner?
end
def destroy?
is_owner?
end
private
def is_owner?
user == record.user
end
end
Run Code Online (Sandbox Code Playgroud)
示例 2:仅授权
class LikesController
def create
authorize(Like)
article = Article.find(params[:article_id])
article.likes.create(user_id: current_user.id, ...)
redirect_to article
end
end
class LikePolicy < ApplicationPolicy
def create?
!user.nil?
end
def update?
is_owner?
end
def destroy?
is_owner?
end
private
def is_owner?
user && user == record.user
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5117 次 |
| 最近记录: |