diff options
Diffstat (limited to 'app/lib/suspicious_sign_in_detector.rb')
-rw-r--r-- | app/lib/suspicious_sign_in_detector.rb | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/app/lib/suspicious_sign_in_detector.rb b/app/lib/suspicious_sign_in_detector.rb new file mode 100644 index 000000000..1af5188c6 --- /dev/null +++ b/app/lib/suspicious_sign_in_detector.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +class SuspiciousSignInDetector + IPV6_TOLERANCE_MASK = 64 + IPV4_TOLERANCE_MASK = 16 + + def initialize(user) + @user = user + end + + def suspicious?(request) + !sufficient_security_measures? && !freshly_signed_up? && !previously_seen_ip?(request) + end + + private + + def sufficient_security_measures? + @user.otp_required_for_login? + end + + def previously_seen_ip?(request) + @user.ips.where('ip <<= ?', masked_ip(request)).exists? + end + + def freshly_signed_up? + @user.current_sign_in_at.blank? + end + + def masked_ip(request) + masked_ip_addr = begin + ip_addr = IPAddr.new(request.remote_ip) + + if ip_addr.ipv6? + ip_addr.mask(IPV6_TOLERANCE_MASK) + else + ip_addr.mask(IPV4_TOLERANCE_MASK) + end + end + + "#{masked_ip_addr}/#{masked_ip_addr.prefix}" + end +end |