仅允许管理员用户使用Devise在Rails中创建新用户(无外部模块)

目前,我的Users数据库有一个名为“admin”的列,其中包含一个布尔值,默认设置为false。 我有一个管理员用户播种到数据库中。

如何编写我的应用程序,以便管理员用户可以创建新用户,但不是的用户不能? (另外,用户只能由管理员创建)

似乎应该有一个简单的方法来设计,不涉及使用一些外部模块。 但到目前为止,我还没有找到满意的答案。

我更有可能标记出只有设计的解决方案。 (其中一个只是标准的MVC / Rails解决方案加一个)然而,如果真的有更好的方法来做不涉及CanCan我也可以接受。

注意:

我一直在寻找一段时间,我发现了其他几个与此问题非常类似的stackoverflow问题,但要么没有完全回答问题,要么使用其他非设计模块。 (或两者)

要实现授权,请在控制器上使用方法

完全按照@ diego.greyrobot的建议

class UsersController < ApplicationController before_filter :authorize_admin, only: :create def create # admins only end private # This should probably be abstracted to ApplicationController # as shown by diego.greyrobot def authorize_admin return unless !current_user.admin? redirect_to root_path, alert: 'Admins only!' end end 

为了回避设计'已经登录'的问题,定义一个用于创建用户的新路由。

我们将简单地定义一个新路由来处理用户的创建,然后将表单指向该位置。 这样,表单提交不会通过设计控制器,因此您可以随意在正常的Rails方式中随意使用它。

 # routes.rb Rails.application.routes.draw do devise_for :users resources :users, except: :create # Name it however you want post 'create_user' => 'users#create', as: :create_user end # users/new.html.erb # notice the url argument <%= form_for User.new, url: create_user_path do |f| %> # The form content <% end %> 

问题是概念性的。 Devise只是一个身份validation库而不是授权库。 您必须单独实现或使用CanCan。 但是,不要担心,因为你只有一个角色,所以你很容易实现这一点。

使用之前的filter保护您的用户创建/更新/销毁操作:

 class UsersController < ApplicationController before_filter :authorize_admin, except [:index, :show] def create # user create code (can't get here if not admin) end end class ApplicationController < ActionController::Base def authorize_admin redirect_to root_path, alert: 'Access Denied' unless current_user.admin? end end 

通过这种简单的方法,您可以在任何可能影响用户记录的控制器操作上运行前置filter,方法是首先检查用户是否为管理员,如果不是,则将其踢出主页。

这似乎是简单的方法。 它只需要对设计控制器进行子类化。 请参阅文档以了解如何执行此操作。

 # app/controllers/registrations_controller.rb class RegistrationsController < Devise::RegistrationsController before_action :authenticate_user!, :redirect_unless_admin, only: [:new, :create] skip_before_action :require_no_authentication private def redirect_unless_admin unless current_user.try(:admin?) flash[:error] = "Only admins can do that" redirect_to root_path end end def sign_up(resource_name, resource) true end end # config/routes.rb Rails.application.routes.draw do devise_for :users, :controllers => { :registrations => 'registrations'} end 

阐释:

  • 对注册控制器进行子类化并为其创建路由。
  • before_action确保用户登录,并重定向,除非他们是管理员,如果他们尝试注册。
  • 已经登录的问题是由Devise的require_no_authentication方法引起的,跳过它可以解决问题。
  • 接下来是新创建的用户自动登录。执行此操作的sign_up帮助程序方法被覆盖以防止自动注册。
  • 最后, Welcome! You have signed up successfully. Welcome! You have signed up successfully. 如果需要,可以通过编辑config/locales/devise.en.yml文件来更改注册flash消息。