web-dev-qa-db-ja.com

管理者ユーザーのみがRails with Devise(外部モジュールなし)で新しいユーザーを作成できるようにする

現在、私のユーザーデータベースには、ブール値とデフォルトがfalseに設定された「admin」という列があります。 1人の管理者ユーザーがデータベースにシードされています。

are管理者であるユーザーは新しいユーザーを作成できますが、notであるユーザーは作成できないように、アプリケーションを作成するにはどうすればよいですか? (また、ユーザーは管理者によって作成される必要がありますのみ

外部モジュールの使用を伴わない工夫でこれを行う簡単な方法があるはずのようです。しかし、これまでのところ、満足のいく答えを見つけることができませんでした。

考案のみの解決策をマークする可能性が高くなります。 (単に標準のMVC/Railsソリューションがプラスであるもの)ただし、CanCanIを使用しないより良い方法が本当にある場合 五月 それも受け入れてください。

注:

私はしばらく探し回っていましたが、これに非常によく似たスタックオーバーフローの質問が他にもいくつか見つかりましたが、質問に完全に答えていないか、他のデバイス以外のモジュールを使用しています。 (または両方)

14
0112

認証を実装するには、コントローラーのメソッドを使用します

@ 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

Deviseの「すでにログインしている」問題を回避するには、ユーザーを作成するための新しいルートを定義します。

ユーザーの作成を処理するための新しいルートを定義し、フォームがその場所を指すようにするだけです。このように、フォームの送信はデバイスコントローラを通過しないため、通常の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 %>
18
Adam Waselnuk

問題は概念的なものです。 Deviseは認証ライブラリであり、承認ライブラリではありません。これを個別に実装するか、CanCanを使用する必要があります。ただし、役割が1つしかないため、これを実装するのは簡単ではありません。

Beforeフィルターを使用して、ユーザーの作成/更新/破棄アクションを保護します。

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

この単純なアプローチでは、ユーザーが管理者であるかどうかを最初に確認し、管理者でない場合はホームページに追い出すことで、ユーザーレコードに影響を与える可能性のあるコントローラーアクションに対してbeforeフィルターを実行します。

7
DiegoSalazar

これは単純なアプローチのようです。 deviseコントローラーをサブクラス化する必要があるだけです。その方法については、ドキュメントを参照してください。

# 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サインアップフラッシュメッセージを変更できます。
7
Nuclearman