Rails - 将 Pundit 与单独的管理命名空间一起使用
Rails - using Pundit with a separate admin namespace
我目前让 Devise 和 Pundit 在一个封闭的系统中工作得很好,需要用户登录才能看到任何东西。
新目标:如何使用 Pundit 要求 AdminUser 登录以访问 Admin 命名空间?
我有一个单独的 AdminUser 模型、单独的管理控制器、策略和命名空间:
routes.rb
namespace :admin do
root to: 'home#index'
resources :users
end
devise_for :admin_users, skip: [:sessions]
as :admin_user do
get 'admin/signin', to: 'admin/devise/sessions#new', as: :new_admin_user_session
post 'admin/signin', to: 'admin/devise/sessions#create', as: :admin_user_session
delete 'admin/signout', to: 'admin/devise/sessions#destroy', as: :destroy_admin_user_session
end
controllers/admin/admin_controller.rb
class Admin::AdminController < ApplicationController
end
controllers/admin/home_controller.rb
class Admin::HomeController < Admin::AdminController
def index
authorize [:admin, :home]
end
end
policies/admin/admin_policy.rb(封闭系统,目前寻找User而不是AdminUser)
class Admin::AdminPolicy
attr_reader :user, :record
def initialize(user, record)
# Must be logged in
raise Pundit::NotAuthorizedError, "You must be logged in to perform this action" unless user
@user = user
@record = record
end
def index?
false
end
def show?
false
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
raise Pundit::NotAuthorizedError, "You must be logged in to perform this action" unless user
@user = user
@scope = scope
end
def resolve
scope.all
end
end
end
policies/admin/home_policy.rb(Admin 命名空间的示例子策略)
class Admin::HomePolicy < Admin::AdminPolicy
def index?
user.present?
end
end
这两个策略的设置方式与我的用户策略相同,因此不是在寻找 AdminUser。我怎样才能使这些适用于我的 AdminUser 模型?
我认为您的方向是正确的。您已经为您的管理控制器创建了一个命名空间,它继承自 Admin::AdminController
。 Pundit 在你的 ApplicationController
中注入了一个名为 pundit_user
的辅助方法,默认情况下只是 returns current_user
.
虽然您可以考虑不为管理员使用单独的模型,而是使用适当的授权设置,但这可能并不适合所有情况。我只是想把它放在那里供你考虑。
我能想到的解决此问题的最简单方法是简单地覆盖 Admin::AdminController
中的辅助方法,如下所示:
class Admin::AdminController < ApplicationController
def pundit_user
current_admin_user
end
end
请注意,这确实假设 AdminUser 模型是在 this convention
的某处设置的
我目前让 Devise 和 Pundit 在一个封闭的系统中工作得很好,需要用户登录才能看到任何东西。
新目标:如何使用 Pundit 要求 AdminUser 登录以访问 Admin 命名空间?
我有一个单独的 AdminUser 模型、单独的管理控制器、策略和命名空间:
routes.rb
namespace :admin do
root to: 'home#index'
resources :users
end
devise_for :admin_users, skip: [:sessions]
as :admin_user do
get 'admin/signin', to: 'admin/devise/sessions#new', as: :new_admin_user_session
post 'admin/signin', to: 'admin/devise/sessions#create', as: :admin_user_session
delete 'admin/signout', to: 'admin/devise/sessions#destroy', as: :destroy_admin_user_session
end
controllers/admin/admin_controller.rb
class Admin::AdminController < ApplicationController
end
controllers/admin/home_controller.rb
class Admin::HomeController < Admin::AdminController
def index
authorize [:admin, :home]
end
end
policies/admin/admin_policy.rb(封闭系统,目前寻找User而不是AdminUser)
class Admin::AdminPolicy
attr_reader :user, :record
def initialize(user, record)
# Must be logged in
raise Pundit::NotAuthorizedError, "You must be logged in to perform this action" unless user
@user = user
@record = record
end
def index?
false
end
def show?
false
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
raise Pundit::NotAuthorizedError, "You must be logged in to perform this action" unless user
@user = user
@scope = scope
end
def resolve
scope.all
end
end
end
policies/admin/home_policy.rb(Admin 命名空间的示例子策略)
class Admin::HomePolicy < Admin::AdminPolicy
def index?
user.present?
end
end
这两个策略的设置方式与我的用户策略相同,因此不是在寻找 AdminUser。我怎样才能使这些适用于我的 AdminUser 模型?
我认为您的方向是正确的。您已经为您的管理控制器创建了一个命名空间,它继承自 Admin::AdminController
。 Pundit 在你的 ApplicationController
中注入了一个名为 pundit_user
的辅助方法,默认情况下只是 returns current_user
.
虽然您可以考虑不为管理员使用单独的模型,而是使用适当的授权设置,但这可能并不适合所有情况。我只是想把它放在那里供你考虑。
我能想到的解决此问题的最简单方法是简单地覆盖 Admin::AdminController
中的辅助方法,如下所示:
class Admin::AdminController < ApplicationController
def pundit_user
current_admin_user
end
end
请注意,这确实假设 AdminUser 模型是在 this convention
的某处设置的