File tree Expand file tree Collapse file tree 4 files changed +70
-2
lines changed
ldap_authenticatable_tiny Expand file tree Collapse file tree 4 files changed +70
-2
lines changed Original file line number Diff line number Diff line change @@ -60,9 +60,9 @@ def authenticate_without_consistent_timing!
6060 ldap_login = PerDistrict . new . ldap_login_for_educator ( educator )
6161 return fail! ( :invalid ) unless is_authorized_by_ldap? ( ldap_login , password_text )
6262
63- # Success, run password checks and store results encrypted and noised,
64- # ignoring any errors in the process.
63+ # Success, run security checks
6564 store_password_check ( password_text )
65+ warn_if_suspicious ( educator )
6666
6767 # Return success
6868 return success! ( educator )
@@ -106,6 +106,10 @@ def store_password_check(password_text)
106106 nil
107107 end
108108
109+ def warn_if_suspicious ( educator )
110+ LoginChecker . new ( educator ) . warn_if_suspicious
111+ end
112+
109113 def logger
110114 Rails . logger
111115 end
Original file line number Diff line number Diff line change 1+ # Check for suspicious bits about the login, for warning.
2+ class LoginChecker
3+ def initialize ( educator , options = { } )
4+ @educator = educator
5+ @time_now = options . fetch ( :time_now , Time . now )
6+ end
7+
8+ def warn_if_suspicious
9+ flags = infer_flags
10+ warn_about ( flags )
11+ flags
12+ end
13+
14+ private
15+ def infer_flags
16+ last_login_at = LoginActivity . last_login_at ( @educator )
17+
18+ flags = [ ]
19+ flags << :first_login_month_after_creation if last_login_at . nil? && @educator . created_at < ( @time_now - 30 . days )
20+ flags << :first_login_after_year if last_login_at . present? && last_login_at < ( @time_now - 1 . year )
21+ flags . sort
22+ end
23+
24+ def warn_about ( flags )
25+ if flags . size > 0
26+ Rollbar . warn ( 'LoginChecker#warn_if_suspicious' , flags : flags )
27+ end
28+ end
29+ end
Original file line number Diff line number Diff line change @@ -14,4 +14,13 @@ class LoginActivity < ApplicationRecord
1414 belongs_to :user ,
1515 polymorphic : true ,
1616 optional : true
17+
18+ # Return ActiveSupport::TimeWithZone or nil
19+ def self . last_login_at ( educator_id )
20+ LoginActivity . where ( user_id : educator_id )
21+ . order ( created_at : :desc )
22+ . limit ( 1 )
23+ . first
24+ . try ( :created_at )
25+ end
1726end
Original file line number Diff line number Diff line change 1+ require 'spec_helper'
2+
3+ RSpec . describe LoginChecker do
4+ let! ( :pals ) { TestPals . create! }
5+
6+ it '#warn_if_suspicious reports to Rollbar on :first_login_after_year' do
7+ LoginActivity . create! ( {
8+ user_id : pals . healey_vivian_teacher . id ,
9+ created_at : pals . time_now - 2 . years
10+ } )
11+
12+ allow ( Rollbar ) . to receive ( :warn )
13+ expect ( Rollbar ) . to receive ( :warn ) . once . with ( 'LoginChecker#warn_if_suspicious' , flags : [ :first_login_after_year ] )
14+ checker = LoginChecker . new ( pals . healey_vivian_teacher , time_now : pals . time_now )
15+ expect ( checker . warn_if_suspicious ) . to eq [ :first_login_after_year ]
16+ end
17+
18+ it '#warn_if_suspicious reports to Rollbar on :first_login_month_after_creation' do
19+ pals . healey_vivian_teacher . update! ( created_at : pals . time_now - 32 . days )
20+
21+ allow ( Rollbar ) . to receive ( :warn )
22+ expect ( Rollbar ) . to receive ( :warn ) . once . with ( 'LoginChecker#warn_if_suspicious' , flags : [ :first_login_month_after_creation ] )
23+ checker = LoginChecker . new ( pals . healey_vivian_teacher , time_now : pals . time_now )
24+ expect ( checker . warn_if_suspicious ) . to eq [ :first_login_month_after_creation ]
25+ end
26+ end
You can’t perform that action at this time.
0 commit comments