【问题标题】:devise_for: How should we do so that only admin can create normal users?devise_for:我们应该怎么做才能只有管理员才能创建普通用户?
【发布时间】:2016-04-29 22:27:01
【问题描述】:

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

让我给你我现在拥有的东西:

app/policies/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

app/controllers/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 

config/routes.rb:

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

附:我试着看看我可以为原始代码 devise/registrations_controller.rb [link] 做些什么,但没有看到任何明显足以让我改变的东西......

【问题讨论】:

  • SO Link 提供了一个很好的例子来说明如何做到这一点。

标签: ruby-on-rails ruby devise


【解决方案1】:

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

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! 方法,但仅当正在执行的操作是new 或create 时。虽然派生控制器没有定义create 方法,但它可以从基本控制器获得。 (旁注:new 方法不会在此处添加任何内容,可以随时删除)。

authorize_user! 方法被声明为私有的,因此它不会被意外地从控制器外部调用 - 这是为了防止安全漏洞。

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

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

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

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

要使用这个 sn-p,您需要更新 link_to 标记以使用应用程序的语义(链接文本、路由、HTML 属性等)。

一旦您准备好这些项目,非管理员类型将无法访问您的 signup 页面,并且尝试访问它会导致相应的错误消息。

【讨论】:

  • 谢谢迈克尔,60% 即将完成。现在普通用户没有创建新用户的权限。但是当管理员创建用户时,它会自动切换到新的用户身份,这是不希望的:即使在创建新用户之后,管理员也始终是管理员。有办法解决吗?
  • 此链接到Allow a user to add new users in Devise, and remain logged in as themselves 的 SO 答案可能会为您提供所需的答案。这可能是一个路由问题,您的routes.rb 文件中的devise_for :users 和resources :users 之间的路由发生冲突。建议的解决方法是改为使用resources :users_admin。我还没有尝试过,但你也许可以很快做到。
  • 我仔细检查了您所指的 SO,但我认为我的问题和这个 SO 的要求是正交的。在这个 SO 中,它采用绕过设计模块的方法,但我故意在设计中使用注册页面,因为我认为它更安全。也就是说,Devise::RegistrationController (github.com/plataformatec/devise/blob/master/app/controllers/…) 必须做一些事情来改变用户,但我找不到它的作用。
  • 我仔细研究了设计代码,发现了一个从第 103 行开始要被覆盖的方法Devise::RegistrationsController。我已经更新了答案以包括被覆盖的方法和一个简短的解释。看看这是否有助于管理员创建用户后的意外登录。
  • 如此简单!我太笨了......答案是如此优雅并且达到目的!不知道该用什么词来感谢你,在我快要放弃的时候,你是我的救命稻草,谢谢你的耐心!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-04
  • 2018-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多