んで can_login 列の値でログインを制御したい場合、どう組み込めばいいかなーと悩んでたんですがとりあえずできたのでエントリにしてみます。
devise やコアとなってる warden にそんな機能はありそうなもんだけど、よくわからなかったので自前で仕込みました。
で、認証を行っているメソッドに追加処理をつっこんでやればいいわけです。
devise の lib/devise/controllers/helpers.rb を見ると、authenticate_user! は warden.authenticate! を、current_user は warden.authenticate を呼びだしてる模様。
warden のソースで lib/warden/proxy.rb を見ると、authenticate! も authenticate も _perform_authentication を呼び出しているので、ここで細工してやればよさそう。
んで、最終的には $RAILS_ROOT/config/initializers/extensions/warden_extension.rb を配置して、中身はこんな感じ。
# -*- coding: utf-8 -*- module Warden class Proxy alias_method :original_perform_authentication, :_perform_authentication private def _perform_authentication(*args) user, opts = original_perform_authentication(*args) # このチェックを入れないとリダイレクトループになる unless winning_strategy && winning_strategy.user user = nil if user && !user.can_login? end [user, opts] end end end元メソッド呼び出したあとに、追加でカスタムロジックを追加している。
んで、その内容自体を元メソッドとして上書きってな感じ。
リダイレクトループにさえならなければ、もっとシンプルなソースになったのに、残念だ。