Skip to content

Commit

Permalink
Record User::SignIn#country
Browse files Browse the repository at this point in the history
Record the geolocation country code of the IP at the time of sign in so
that it can be used for misuse detection and filtering.
  • Loading branch information
garethrees committed Apr 28, 2022
1 parent fa059ec commit b1cf0da
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 5 deletions.
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def sign_in(user, remember_me: nil)
session[:remember_me] = remember_me
# Intentionally allow to fail silently so that we don't have to care whether
# sign in recording is enabled.
user.sign_ins.create(ip: user_ip)
user.sign_ins.create(ip: user_ip, country: country_from_ip)
end

# Logout form
Expand Down
4 changes: 3 additions & 1 deletion app/models/user/sign_in.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20220225094330
# Schema version: 20220225214524
#
# Table name: user_sign_ins
#
Expand All @@ -8,6 +8,7 @@
# ip :inet
# created_at :datetime not null
# updated_at :datetime not null
# country :string
#

# Record medadata about User sign in activity
Expand All @@ -25,6 +26,7 @@ def self.purge
def self.search(query)
joins(:user).references(:users).where(<<~SQL, query: query)
lower(user_sign_ins.ip::text) LIKE lower('%'||:query||'%') OR
lower(user_sign_ins.country) LIKE lower('%'||:query||'%') OR
lower(users.name) LIKE lower('%'||:query||'%') OR
lower(users.email) LIKE lower('%'||:query||'%')
SQL
Expand Down
12 changes: 12 additions & 0 deletions app/views/admin/users/_sign_in_table.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@
</tt>
</td>

<td>
<tt>
<% if sign_in.country %>
<%= link_to admin_sign_ins_path(query: sign_in.country) do %>
<%= sign_in.country %>
<% end %>
<% else %>
??
<% end %>
</tt>
</td>

<td><%= admin_date(sign_in.created_at, ago_only: true) %></td>

<td>
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20220225214524_add_country_to_user_sign_ins.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddCountryToUserSignIns < ActiveRecord::Migration[6.1]
def change
add_column :user_sign_ins, :country, :string
end
end
4 changes: 3 additions & 1 deletion spec/factories/user/sign_ins.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20220225094330
# Schema version: 20220225214524
#
# Table name: user_sign_ins
#
Expand All @@ -8,11 +8,13 @@
# ip :inet
# created_at :datetime not null
# updated_at :datetime not null
# country :string
#
FactoryBot.define do
factory :user_sign_in, class: 'User::SignIn' do
user
ip { '0.0.0.0' }
country { 'XX' }

trait :ipv4 do
ip { '0.0.0.0' }
Expand Down
10 changes: 8 additions & 2 deletions spec/models/user/sign_in_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20220225094330
# Schema version: 20220225214524
#
# Table name: user_sign_ins
#
Expand All @@ -8,6 +8,7 @@
# ip :inet
# created_at :datetime not null
# updated_at :datetime not null
# country :string
#
require 'spec_helper'

Expand Down Expand Up @@ -68,7 +69,7 @@

let(:sign_in_2) do
user = FactoryBot.create(:user, name: 'James', email: '[email protected]')
FactoryBot.create(:user_sign_in, ip: '2.2.2.2', user: user)
FactoryBot.create(:user_sign_in, ip: '2.2.2.2', country: 'XY', user: user)
end

let(:sign_in_3) do
Expand Down Expand Up @@ -111,6 +112,11 @@
let(:query) { 'example.com' }
it { is_expected.to match_array([sign_in_2, sign_in_1]) }
end

context 'when given a country' do
let(:query) { 'XY' }
it { is_expected.to match_array([sign_in_2]) }
end
end

describe '#other_users' do
Expand Down

0 comments on commit b1cf0da

Please sign in to comment.