LoginSignup
0
0

More than 3 years have passed since last update.

「omniauth」とDevise「recoverableモジュール」を同時に使う時の挙動分岐

Posted at

タイトルがいまいち意味不明ですが、下記のやりたいことを実装する上で調べたことが非常に勉強になったので記録しておきます。

前提条件

・認証にdeviseを使用。googleなどの外部サービスのログインも実装している

やりたいこと

①通常のemail、passwordでログインした場合、ユーザー情報を変更する(edit_user_registration_path)時にパスワード変更フォームを表示。情報変更の際に現在のパスワードの入力を要求するように設定。

②外部サービスログインを使った場合は(edit_user_registration_path)でパスワード変更フォーム、現在のパスワード入力欄を非表示。情報変更の際に現在のパスワード入力も不要な設定にする。

こういった挙動を実装したい。

実装

①ログイン認証の方式によって、Viewの表示を変更する。

app/views/devise/registrations/edit.html.erb


    <%if current_user.uid == nil %>  
      <div class="field">
        <%= f.label :password %> <br />
        <%= f.password_field :password, autocomplete: "new-password" , class: "form-control form-control-comment" %>
        <% if @minimum_password_length %>
          <br />
          <em><%= @minimum_password_length %> characters minimum</em>
        <% end %>
      </div>
        <p class="comment">(変更したくない場合は空白のままにしてください)</p>

      <div class="field">
        <%= f.label :current_password %> <br />
        <%= f.password_field :current_password, autocomplete: "current-password", class: "form-control form-control-comment" %>
      </div>
        <p class="comment">(変更するには現在のパスワード入力が必要です)</p> 
    <% end %>

通常のメールアドレスとパスワードのログインの場合はプロバイダから返ってくる、uidはnilになっている。

それをif文でViewの表示を分岐させた。

②ユーザー情報を更新する時にパスワード要否を分岐させる

deviseの初期設定ではユーザー情報を更新する時は現在のパスワード入力を求められる。

app/controllers/users/registrations_controller.rb

class Users::RegistrationsController < Devise::RegistrationsController
.
.
.

 protected
  def update_resource(resource, params)
    if current_user.uid == nil
      resource.update_with_password(params)
    else
      resource.update_without_password(params)
    end
  end
end

どういうことだろう?

rails gで自作したUsers::RegistrationsControllerDevise::RegistrationsControllerを継承している。

情報を更新する時の仕組みは
Devise::RegistrationsControllerのupdateメソッドを読んでいる。
色々辿っていくと、

  def update_resource(resource, params)
    resource.update_with_password(params)
  end

このupdate_with_passwordメソッドにつながる。

require 'devise/strategies/database_authenticatable'

module Devise
  module Models
.
.
.

      def update_with_password(params, *options)

      ...

      current_password = params.delete(:current_password)

        if params[:password].blank?
          params.delete(:password)
          params.delete(:password_confirmation) if params[:password_confirmation].blank?
        end

        result = if valid_password?(current_password)
          update(params, *options)
        else
          assign_attributes(params, *options)
          valid?
          errors.add(:current_password, current_password.blank? ? :blank : :invalid)
          false
        end


.
.
.
  end
end

このメソッドは現在のパスワードが入力されていない、もしくは間違っている場合は情報を更新しないようになっている。

このupdate_with_passwordと同じところにupdate_without_passwordメソッドもある。
これこそがパスワードなしで情報を変更できるメソッド。

仕組みがわかればUsers::RegistrationsControllerupdate_resourceメソッドを上書きする。
やりたいことはViewと同じであり、現在のユーザーがプロバイダから返ってくるuidを保持しているかnilかで発火させるメソッドを分岐させた。

学び

ググれば色んな方が情報発信してくれているが、一次情報を見る癖もつけないといけない

参考

0
0
0

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
0
0