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

时间:2014-07-21 21:47:20

标签: ruby-on-rails ruby ruby-on-rails-4 devise admin

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

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

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

我更有可能选择仅设计的解决方案。 (一个只是标准的MVC / Rails解决方案加一个)然而,如果确实有一个更好的方法来做不涉及CanCan I 可能也接受它。

注意:

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

4 个答案:

答案 0 :(得分:16)

要实施授权,请使用控制器上的方法

完全按照@ 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 %>

答案 1 :(得分:7)

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

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

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

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

答案 2 :(得分:7)

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

# 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.文件来更改config/locales/devise.en.yml注册Flash消息。

答案 3 :(得分:1)

在处理 Rails 6 应用程序时遇到此问题。

我有一个admin模型,我用它设计来创建管理员。

这是我修复的方式

首先,我为Admin模型生成了一个Devise控制器,该控制器创建了以下文件:

app/controllers/admins/confirmations_controller.rb
app/controllers/admins/omniauth_callbacks_controller.rb
app/controllers/admins/passwords_controller.rb
app/controllers/admins/registrations_controller.rb
app/controllers/admins/sessions_controller.rb
app/controllers/admins/unlocks_controller.rb

接下来,我以这种方式修改了new的{​​{1}}和create操作以使用Devise将注册限制为管理员

app/controllers/admins/registrations_controller.rb

此后,我以这种方式将class Admins::RegistrationsController < Devise::RegistrationsController before_action :configure_sign_up_params, only: [:create] before_action :configure_account_update_params, only: [:update] # GET /resource/sign_up def new if admin_signed_in? super else redirect_to root_path end end # POST /resource def create if admin_signed_in? super else redirect_to root_path end end . . . end 操作添加到skip_before_action :require_no_authentication, only: [:new, :create]中,以允许已存在的管理员在登录时创建新管理员

app/controllers/admins/registrations_controller.rb

您可能还需要隐藏登录表单中的注册忘记密码按钮,以仅由已登录的管理员登录:

class Admins::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]
  before_action :configure_account_update_params, only: [:update]
  skip_before_action :require_no_authentication, only: [:new, :create]
.
.
.
end

(可选)在通过数据库迁移将# app/views/admins/sessions/new.html.erb <% if admin_signed_in? %> <%= render "admins/shared/links" %> <% end %> first_name参数添加到last_name模型之后,我将app/controllers/admins/registrations_controller.rbadmin参数添加到class Admins::RegistrationsController < Devise::RegistrationsController before_action :configure_sign_up_params, only: [:create] before_action :configure_account_update_params, only: [:update] skip_before_action :require_no_authentication, only: [:new, :create] . . . # If you have extra params to permit, append them to the sanitizer. def configure_sign_up_params devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name]) end # If you have extra params to permit, append them to the sanitizer. def configure_account_update_params devise_parameter_sanitizer.permit(:account_update, keys: [:first_name, :last_name]) end . . . end 文件中允许的参数中: / p>

app/views/admin/registrations

注意:您将需要相应地修改index视图以适应此情况

另外,您可能需要创建一个新的控制器,您可以在其中为admins(例如app/controllers/admins/admins_controller.rb)创建class Admins::AdminsController < ApplicationController before_action :set_admin, only: [:show, :edit, :update, :destroy] before_action :authenticate_admin! # GET /admins # GET /admins.json def index @admins = Admin.all end . . . end 操作:

show

注意:如果您需要更多操作,例如通过从信息中心更新和删除其他管理员的信息来管理管理员,则可能需要添加其他操作,例如{{1 }},editupdatedestroy和其他文件。

对于路线

## config/routes.rb

# List of Admins
get 'admins', to: 'admins/admins#index'

namespace :admins do
    resources :admins
end

然后在app/controllers/admins/registrations_controller.rb中修改注册后使用的路径以重定向到admins_path,这将向您显示所有管理员的列表< / strong>已创建:

class Admins::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]
  before_action :configure_account_update_params, only: [:update]
  skip_before_action :require_no_authentication, only: [:new, :create]
.
.
.
  # The path used after sign up.
  def after_sign_up_path_for(resource)
    admins_path
  end

  # The path used after sign up for inactive accounts.
  def after_inactive_sign_up_path_for(resource)
    admins_path
  end
end

最后,您可能需要从以下位置更改在config/locales/devise.en.yml文件中创建用户时Devise发出的通知:

Welcome, You have signed up successfully

说:

Account was created successfully.

仅此而已。

我希望这对您有帮助