29
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Deviseの機能をカスタマイズする(例えばSNSアカウントでログインしているときはパスワード再発行できないようにする)方法

Last updated at Posted at 2018-06-07

背景

Deviseを用いてログイン機能をつくり、
そしてGoogleログインとGithubログインを作った。
(もちろんググってコピペしながら! deviseとomniauthを使ったGoogle認証の流れを参考にしました!)

そして、GoogleログインとかGithubログインしている場合のみ、
登録してる名前とかアドレスをパスワード無しで変更できるようにしたくなりがち。
ユーザにとって「パスワードってなんや?」ってなるので。
(もちろんググってコピペしながら! Devise+OmniAuthでQiita風の複数プロバイダ認証の下の方を参考にしました!)

基本コピペやで!

問題発生

ということはですよ、
GoogleログインとかGithubログインしている場合のみ、**Forgot your password?**の機能も消したくなりがち。
ユーザにとって「パスワードってなんや?」ってなるので。

コピペばっかしてたからDeviseのカスタマイズ方法わからん。

その時の解決方法を以下に書いてみた。

Deviseの正体

いろいろググってるとDeviseは
https://github.com/plataformatec/devise/tree/master/app/controllers/devise
に基づいて動いているらしい。

うん、確かにomniauth_callbacks_controller.rbとかregistrations_controller.rbをオーバーライドする感じでGoogleログインを作っていた感触はある!

解決までの方針

そこで私は解決までの方針を立てた。

  1. パスワード変更はDeviseのコードのどの部分にあたるのか調べる
  2. そのファイルを上書き

短いなぁ。

パスワード変更はDeviseのコードのどの部分にあたるのか調べる

まずパスワード再発行のときの画面をchromeデベロッパーで見てみる。

https://gyazo.com/14121185a1965a04dfea120e189d6cc2

なるほど、/users/passwordにPOSTでデータを送っているっぽい。
つぎはルーティングを見てみる。

$ rails routes
(省略)
       new_user_password GET      /users/password/new(.:format)         users/passwords#new
            edit_user_password GET      /users/password/edit(.:format)        users/passwords#edit
                 user_password PATCH    /users/password(.:format)             users/passwords#update
                               PUT      /users/password(.:format)             users/passwords#update
                               POST     /users/password(.:format)             users/passwords#create
(省略)

なるほど、つまり、users/passwordsのcreateメソッドがパスワード再発行をつかさどるはず。

つまりパスワード再発行のソースは https://github.com/plataformatec/devise/blob/master/app/controllers/devise/passwords_controller.rb のcreateメソッドであると狙いをつける。

具体的には以下である(はず)

github.com/plataformatec/devise/blob/master/app/controllers/devise/passwords_controller.rb
# 省略
  def create
    self.resource = resource_class.send_reset_password_instructions(resource_params)
    yield resource if block_given?

    if successfully_sent?(resource)
      respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name))
    else
      respond_with(resource)
    end
  end
# 省略

そのファイルを上書き

そう、つぎはこのファイルを上書きせねばならない。
Googleログイン実装時は、omniauth_callbacksコントローラを上書きした(っぽい)。
その手順は、まずルーティング。

config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    # 省略
    omniauth_callbacks: "users/omniauth_callbacks"
  }
end

そして、app/controllers/users/omniauth_callbacks_controller.rbを新規作成し、DeviseのOmniauthCallbacksControllerを継承。

app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google
    # 省略
  end
  # 省略
end

この手法をまねてみよう。
今回はpasswordsコントローラを上書きしたい。

まずルーティング。

config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    # 省略
    omniauth_callbacks: "users/omniauth_callbacks",
    passwords: "users/passwords"
  }
end

つぎは、app/controllers/users/passwords_controller.rbを新規作成。
DeviseのPasswordsControllerを継承させる。
で、いじるのはcreateメソッド!

app/controllers/users/passwords_controller.rb
class Users::PasswordsController < Devise::PasswordsController
  def create
  end
end

それから、指定したメールアドレスのuserのproviderが存在したらリダイレクトでエラーメッセージ。
それ以外は、継承そのまま。
つまり、、

app/controllers/users/passwords_controller.rb
class Users::PasswordsController < Devise::PasswordsController
  def create
  	if User.find_by(email: params["user"]["email"]).provider.present?
      redirect_to new_user_password_path, notice: 'GoogleアカウントもしくはGithubアカウントで登録している場合はパスワードは使用されていません'
    else
      super
    end
  end
end

検証

いけた!おっしゃ!

https://gyazo.com/495270ac4fa8099ad73462ad13eb365d

つまりDeviseの機能のカスタマイズは

  1. どのコントローラのどのメソッドか判断し
  2. そのコントローラを継承した新コントローラ作成し
  3. メソッドを上書きし
  4. ルーティングを書き換える

でいけるのだ!
さあ、アメトーーク!みて寝よ。

29
28
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?