LoginSignup
5
8

More than 5 years have passed since last update.

[Rails5+Sorcery] Sorcery ログインで users.status をチェックする

Last updated at Posted at 2017-04-13

まえがき

Rails のログイン機能を簡単に実装できる gem である Sorcery ですが、たとえば users.status や users.disabled など、ユーザーの特定の状態を考慮したログインチェックを行いたい場合、どのようにすべきでしょうか。
この記事では、カスタマイズのために自分が行った方法を記載します。

Sorcery
https://github.com/Sorcery/sorcery

どう書くか

app/controllers/application_controller.rb など、ログイン後に共通で使用するコントローラーを対象とします。
そこに not_authenticated を定義していたりなどしていたら、その近くにでも下記の記述を追加してみましょう。

app/controllers/application_controller.rb

    def not_authenticated
      redirect_to login_path
    end

    def logged_in? # <-- 追記するメソッド
      (current_user && current_user[:status] != Settings.user_status_retired)
    end

カスタマイズなどと大げさに言いましたが、見ての通り単に Sorcery の呼び出す logged_in? メソッドをオーバーライドしているだけです。

おまけと注意点

オリジナルのソースはこちら。
https://github.com/Sorcery/sorcery/blob/7c5fee441e03779ee2888ecef317440cd10a17e7/lib/sorcery/controller.rb#L76-L78

Settings.user_status_retired としている部分は、規模やお好みで変更して下さい。
上記の場合は config/settings.yml に判定値を記載した場合の呼び出し例です。
config/initializers/constants.rb に記載してもいいかもしれません。

また、応用的に複数のカラムを参照する場合には、以下のようにすれば良いでしょう。

app/controllers/application_controller.rb

    def not_authenticated
      redirect_to login_path
    end

    def logged_in?
      (
        current_user \
        && current_user[:status] != Settings.user_status_retired \
        && current_user[:hoge] == "piyo" # <-- ふたつ目の条件
      )
    end

この処理は、以下の流れにそっています。

  1. Sorcery で通常のログイン処理が行われ、@current_user などがセットされる。
  2. application_controller.rbbefore_action メソッドが、Sorcery の require_login メソッドを呼び出す。
  3. Sorcery の require_login メソッドが、同 logged_in? メソッドを呼び出す。

つまり @current_user のセットを阻害する働きはありませんし、ログイン時にセッションを発行している場合には、別途それを destroy してやる必要があるかもしれません。

自分の対応例

app/controllers/application_controller.rb

    def not_authenticated
      reset_sorcery_session if !!current_user
      redirect_to login_path
    end

User.active_for_authentication? との違い

(※2017年4月14日追記)
投稿後「 User.active_for_authentication? を使うと良いのでは」とご指摘をいただきました。
恥ずかしながら devise に明るくなく active_for_authentication? を知らなかったので、まず試してみて、もしそれで済むならこの記事をこっそり消そうと思っていました。

devise
https://github.com/plataformatec/devise

具体的には、

app/models/user.rb

def active_for_authentication?
  self.status != Settings.user_status_retired
end

こういう記述を追加してみました。
その後動作を確認したところ active_for_authentication? はログイン時にのみ評価が行われ、すでにログインしているユーザーを強制的にログアウトさせることはできませんでした。

とはいえ、ログイン時にのみ評価して、ログインを拒否するという動作を実装する場合には app/models/user.rb に追記するほうがより簡潔に記述でき良いのではないかと思います(教えてくださった twitter@libkenta さん、ありがとうございます!)。

5
8
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
5
8