業務でRailsを使って社内用のアプリケーション開発を行なっていた際、ユーザのパスワード管理の部分で色々と調査をしていたのでそこで得られたいくつかの知見を書きます。
アプリケーションにユーザ管理機能を実装する際は、deviseというrubyのgemを使うことで簡単にユーザ管理に必要な機能を実装できます。
ユーザ情報への入力パラメータに対してバリデーションなどを簡単に実現できますが、独自に実装を加えたりする必要も場合によってはあります。
今回はdeviseを使ったユーザ管理を実装していく中でパスワードの更新周りで調べた点をまとめてみます。
Rubyと各gemのバージョン
- ruby 2.5.1p57
- rails (5.2.1.1)
- devise (4.5.0)
パスワード更新のパターン
- ユーザ更新時にパスワードを更新しない
- ユーザ更新時に特定の条件でパスワードの検証をしない
- ユーザ更新時にパスワードフォームの値が空でない場合にパスワードを更新する
ユーザ更新時にパスワードを更新しない
ユーザ更新時にパスワードを更新したくない場合、strong parameterに:password
を含めない方法が簡単です。
params(:user).permit(:first_name, :last_name, :address)
上記は独自のコントローラー内でupdateを行う場合になりますが、Devise::RegistrationsControllerを実装したコントローラーに実装する場合は下記のようになります。
update_resourceをoverrideして中でupdate_resourceをresource.update_without_passwordを呼ぶように実装を変更します。
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
protected
def update_resource(resource, params)
resource.update_without_password(params)
end
end
ユーザ更新時に特定の条件でパスワードの検証をしない
deviseのvalidatableを実装することでupdate時にパスワードの検証を行うことができます。
class User < ApplicationRecord
devise :validatable
end
validatableのパスワード検証のロジックはpassword_required内で定義されています。
def password_required?
!persisted? || !password.nil? || !password_confirmation.nil?
end
このメソッドをoverrideすることで任意の条件でパスワード検証を行うことができます。
def password_required?
if do_validate # パスワード検証を行う条件
!persisted? || !password.nil? || !password_confirmation.nil?
else
false
end
end
ユーザ更新時にパスワードの値が空だった場合、パスワードを更新しない
これは同僚から聞いて知ったのですが、controller内で参照できるparamsに含まれるパラメータは全てvalidationの対象となるようです。
なのでupdateメソッド内にパスワードが空だった場合、userをupdateする前にparams[:user].delete(:password)を実行することで
validationを回避することができます。
def update
if params[:user][:password].blank?
params[:user].delete("password")
end
if @user.update(user_params)
end
おわりに
それぞれ簡単にですがdevise利用を踏まえてのパスワード更新周りについてまとめました。
deviseは便利な機能が多いので使う場合はどんな機能があるのかをざっと確認しておくと良いです。
機能の全体像を把握する上で下記の記事が参考になりました。
参考リンク