devise_for:我们应该如何做到只有管理员可以创建普通用户?

时间:2016-04-29 22:27:02

标签: ruby-on-rails ruby devise

在我们现在的devise_for模块中,我们至少有两个角色: admin user 。我的目标是在任何给定时间,只有一个管理员,只有管理员可以创建/删除其他用户。我已经关注了这个post,因此我必须登录并拥有创建新用户的权限,因为默认情况下sign_up页面不需要权限。但是,现在管理员和用户之间没有区别,这意味着两个角色都可以创建其他角色,这不是我想要的功能。我应该怎么做才能只有管理员才能创建其他用户,即在用户角色下访问/ users / sign_up时,会弹出错误,例如"没有足够的权限?"

让我告诉你我现在拥有的东西:

应用/策略/ user_policy.rb:

class UserPolicy
  attr_reader :current_user, :model

  def initialize(current_user, model)
    @current_user = current_user
    @user = model
  end

  def index?
    @current_user.admin?
  end

  def new?
    @current_user.admin?
  end

  def show?
    @current_user.admin? or @current_user == @user
  end

  def create?
    @current_user.admin?
  end

  def update?
    @current_user.admin?
  end

  def destroy?
    return false if @current_user == @user
    @current_user.admin?
  end
end

应用/控制器/ registrations_controller.rb

class RegistrationsController < Devise::RegistrationsController
  prepend_before_action :require_no_authentication, only: [:cancel]
  prepend_before_action :authenticate_scope!, only: [:new, :create, :edit, :update, :destroy]

  def new
    super
  end
end 

配置/ routes.rb中:

...
  devise_for :users, :controllers => {:registrations => "registrations"}
  resources :users
...

P.S。我试着看看我能为原始代码devise/registrations_controller.rb [link]做些什么,但没有看到任何明显足以让我改变......

1 个答案:

答案 0 :(得分:2)

这样的事情可能有所帮助:

class RegistrationsController < Devise::RegistrationsController
  prepend_before_action :require_no_authentication, only: [:cancel]
  prepend_before_action :authenticate_scope!, only: [:new, :create, :edit, :update, :destroy]
  before_action :authorize_user!, only: [:new, :create]

  def new
    super
  end

private

  def authorize_user!
    if !current_user || !current_user.admin?
      redirect_to '/', notice: "Your permissions do not allow access to this page"
    end
  end

  # Override from Devise::RegistrationsController to not sign in after sign up
  def sign_up(resource_name, resource)
    # Nothing to do
  end
end

现在代码已经不在了,现在是时候进行一些解释了。第一部分代码添加了before_action处理程序,该处理程序指定调用authorize_user!方法,但仅在正在执行的操作是newcreate时。虽然派生控制器没有定义create方法,但它可以从基本控制器获得。 (旁注:new方法不会在此处添加任何内容,并且可以随时删除。

authorize_user!方法被声明为私有,因此无法从控制器外部意外调用 - 这是专门用于防止安全漏洞。

在该方法中,检查用户以确保首先登录某人,然后登录用户具有管理员权限。如果授权失败,用户将被重定向到主页(到'/'路线),并带有通知消息,告诉他们这些不值得。

从Devise sign_up方法中调用RegistrationsController#create方法,默认实现是立即调用sign_in。由于最好让管理员用户登录,因此会在应用程序的RegistrationsController中覆盖该方法,以省略不需要的sign_in步骤。

在管理员创建用户帐户的情况下,当前用户不是管理员时,省略指向signup页面的链接很有用。像这个片段的东西通常对我有用:

<% if current_user && current_user.admin? %><%= link_to "Sign Up", devise_signup_link %><% end %>

要使用此代码段,您需要更新link_to标记以使用应用程序的语义(链接文本,路由,HTML属性等)。

准备好这些项目后,非管理员类型将无法访问您的signup页面,尝试访问该页面会产生合适的错误消息。