ankane / authtrail

Track Devise login activity

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

before_fail doesn't track which user, so an alternative has_many is:..

RobertLowe opened this issue · comments

https://github.com/ankane/authtrail/blob/master/lib/auth_trail/manager.rb#L20-L33

before_fail doesn't track which user, so an alternative has_many is:

has_many :login_activities, class_name: "LoginActivity", primary_key: 'email', foreign_key: "identity"

the docs should mention this, I think it's a reasonable addition

Hey @RobertLowe, thanks for the suggestion, but it's typically better to record the user directly (documented in the readme), since many apps allow users to change email addresses.

Thanks, Im not sure those calls would cover it.

Existing:

      def before_failure(env, opts)
        AuthTrail.safely do
          request = ActionDispatch::Request.new(env)

          AuthTrail.track(
            strategy: detect_strategy(env["warden"]),
            scope: opts[:scope].to_s,
            identity: AuthTrail.identity_method.call(request, opts, nil),
            success: false,
            request: request,
            failure_reason: opts[:message].to_s
          )
        end
      end

Ugly POC Idea, there's probably much more elegant way to handle this:

      def before_failure(env, opts)
        AuthTrail.safely do
          request = ActionDispatch::Request.new(env)

          user_input = env["rack.request.form_hash"][opts[:scope].to_s]
          if(user_input && user_input["email"])
            user_klass = env["devise.mapping"].class_name
            klass = eval(user_klass);
            user = klass.where(email: user_input["email"]).limit(1).first
          end

          AuthTrail.track(
            strategy: detect_strategy(env["warden"]),
            scope: opts[:scope].to_s,
            identity: AuthTrail.identity_method.call(request, opts, nil),
            user: user,
            success: false,
            request: request,
            failure_reason: opts[:message].to_s
          )
        end
      end

At the time of failure we could at least do a look up to match it with the user that current holds that email. So even if they change it in the future it will still track to the user.

Additionally, while user is polymorphic, it does not work with polymorphic user models, always appearing as User, even if the polymorphic model was Employee < User for example, while technically still correct it feels like another area of improvement.

Cheers

My bad, it looks like it never made it to the docs. I just added it and pushed out a new release, so users can do:

AuthTrail.transform_method = lambda do |data, request|
  data[:user] ||= User.find_by(email: data[:identity])
end

Re polymorphic issue: AuthTrail just sets the user attribute on the LoginActivity model, so the behavior you're seeing should just be standard Rails.

login_activity = LoginActivity.new
data.each do |k, v|
login_activity.try("#{k}=", v)
end

Sweet, thanks, closing.