trackguard 0.15.2 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae9f9bf943f2d35552e716b36c5a0fe3034ec1c950897ca8600063b5ae957e1e
4
- data.tar.gz: fefa54219e288aeaca10e3fd2e5ba7533e06e50b197182980dfe7179fedb5118
3
+ metadata.gz: a4acea93b885f29862fb335806a5f378f63497793fff3e6a57cdb3eb2f0de255
4
+ data.tar.gz: 0aa85cf87c159a589960c253ae5bb96b4ae095093b4b2963a7f4b96590e3b065
5
5
  SHA512:
6
- metadata.gz: a79523a214364741d689519ac4aba172661b3634bda347b433544b6a9e49a655c569c5b0bbde41573038dc53bdfe262fac8735d2b98f84cfb7b8659e23b57bed
7
- data.tar.gz: def6dacf4f57e4c7380a1ade1cec4c8ae421127bbe047b8276b3bbe0c0f1dd212e5b58dc68ef9dfe270f4b2299d0a9f959b5040b2fb146974ec57e8cdfdbe904
6
+ metadata.gz: 1f770cb91aedabae79a1195b075a68d690eb730fb1ca55529c68b37ce156aebd42217174efc32beb8296d0a4bd6f45a67f94d56a3b9d8ca6103c5bc2b389bd42
7
+ data.tar.gz: 67b00fa4e4f2500fc2145650871f973808f0c7e6af12b0e2b212dd700c8f35b8dae9e521c4a5719ead55dd5911e43db2e428e072e7e84ed514b18a0e35a4cd40
@@ -29,7 +29,8 @@ module Trackguard
29
29
  referer: request.referer,
30
30
  session_id: session.id.to_s,
31
31
  trace_id: @trace_id,
32
- source: extract_source
32
+ source: extract_source,
33
+ http_method: request.request_method
33
34
  )
34
35
  end
35
36
 
@@ -9,7 +9,8 @@ module Trackguard
9
9
  session_id: session.id.to_s,
10
10
  trace_id: params[:trace_id].to_s.presence,
11
11
  source: params[:ref].to_s.strip.downcase.first(64).presence,
12
- initial: params[:initial] == true
12
+ initial: params[:initial] == true,
13
+ http_method: "GET"
13
14
  )
14
15
 
15
16
  head :no_content
@@ -103,7 +103,7 @@ module Trackguard
103
103
  .unflagged
104
104
  .joins("LEFT OUTER JOIN trackguard_whitelisted_ips wi ON wi.visitor_id = trackguard_visitors.id")
105
105
  .joins(:page_views)
106
- .where(trackguard_page_views: { trace_id: shared, created_at: cutoff.. })
106
+ .where(trackguard_visits: { trace_id: shared, created_at: cutoff.. })
107
107
  .where("wi.id IS NULL OR wi.expires_at <= ?", Time.current)
108
108
  .distinct
109
109
  .each do |visitor|
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trackguard
4
+ class TrackBlockedRequestJob < ApplicationJob
5
+ queue_as :default
6
+
7
+ def perform(ip:, user_agent:, path:, http_method:, block_reason:)
8
+ visitor = Visitor.find_or_create_by!(ip: ip) do |v|
9
+ v.user_agent = user_agent
10
+ v.first_seen_at = Time.current
11
+ v.last_seen_at = Time.current
12
+ end
13
+ visitor.update!(last_seen_at: Time.current, user_agent: user_agent)
14
+
15
+ BlockedRequest.create!(
16
+ path: path,
17
+ user_agent: user_agent,
18
+ http_method: http_method,
19
+ block_reason: block_reason,
20
+ visitor: visitor
21
+ )
22
+ end
23
+ end
24
+ end
@@ -2,7 +2,8 @@ module Trackguard
2
2
  class TrackPageViewJob < ApplicationJob
3
3
  queue_as :default
4
4
 
5
- def perform(path:, ip:, user_agent:, referer:, session_id: nil, trace_id: nil, source: nil, initial: false)
5
+ def perform(path:, ip:, user_agent:, referer:, session_id: nil, trace_id: nil, source: nil, initial: false,
6
+ http_method: nil)
6
7
  hashed_session_id = Digest::SHA256.hexdigest(session_id) if session_id.present?
7
8
 
8
9
  visitor = Visitor.find_or_create_by!(ip: ip) do |v|
@@ -22,7 +23,7 @@ module Trackguard
22
23
  end
23
24
  end
24
25
 
25
- PageView.create_with(source:, referer:)
26
+ PageView.create_with(source:, referer:, http_method:)
26
27
  .find_or_create_by!(path:, user_agent:, session_id: hashed_session_id, trace_id:, visitor:)
27
28
  end
28
29
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trackguard
4
+ class BlockedRequest < Visit
5
+ REASON_SCANNER = "trackguard/block known scanners"
6
+ REASON_FLAGGED = "trackguard/flagged visitors"
7
+
8
+ validates :path, :block_reason, presence: true
9
+
10
+ scope :scanners, -> { where(block_reason: REASON_SCANNER) }
11
+ scope :flagged, -> { where(block_reason: REASON_FLAGGED) }
12
+ end
13
+ end
@@ -1,16 +1,9 @@
1
1
  module Trackguard
2
- class PageView < ApplicationRecord
3
- self.table_name = "trackguard_page_views"
4
-
5
- belongs_to :visitor, class_name: "Trackguard::Visitor"
6
-
2
+ class PageView < Visit
7
3
  validates :path, presence: true
8
4
 
9
- scope :today, -> { where(created_at: Time.current.beginning_of_day..) }
10
5
  scope :this_week, -> { where(created_at: 1.week.ago..) }
11
6
  scope :this_month, -> { where(created_at: 1.month.ago..) }
12
- scope :last_30, -> { where(created_at: 30.days.ago..) }
13
- scope :last_24h, -> { where(created_at: 24.hours.ago..) }
14
7
  scope :with_referrer, -> { where.not(referer: [ nil, "" ]) }
15
8
  scope :with_source, -> { where.not(source: [ nil, "" ]) }
16
9
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trackguard
4
+ class Visit < ApplicationRecord
5
+ self.table_name = "trackguard_visits"
6
+
7
+ belongs_to :visitor, class_name: "Trackguard::Visitor"
8
+
9
+ scope :today, -> { where(created_at: Time.current.beginning_of_day..) }
10
+ scope :last_24h, -> { where(created_at: 24.hours.ago..) }
11
+ scope :last_30, -> { where(created_at: 30.days.ago..) }
12
+ end
13
+ end
@@ -7,8 +7,9 @@ module Trackguard
7
7
 
8
8
  validates :flagged_by, inclusion: { in: FLAGGED_BY }, allow_blank: true
9
9
 
10
- has_many :page_views, class_name: "Trackguard::PageView", foreign_key: "visitor_id"
11
- has_one :whitelisted_ip, class_name: "Trackguard::WhitelistedIp", foreign_key: "visitor_id"
10
+ has_many :page_views, class_name: "Trackguard::PageView", foreign_key: "visitor_id"
11
+ has_many :blocked_requests, class_name: "Trackguard::BlockedRequest", foreign_key: "visitor_id"
12
+ has_one :whitelisted_ip, class_name: "Trackguard::WhitelistedIp", foreign_key: "visitor_id"
12
13
 
13
14
  scope :unflagged, -> { where(flagged_at: nil) }
14
15
  scope :flagged, -> { where.not(flagged_at: nil) }
@@ -8,15 +8,17 @@ module Trackguard
8
8
  bot|crawl|spider
9
9
  /ix
10
10
 
11
- def initialize(path:, ip:, user_agent:, referer:, session_id:, trace_id:, source: nil, initial: false)
12
- @path = path.to_s
13
- @ip = ip
14
- @user_agent = user_agent.to_s
15
- @referer = referer
16
- @session_id = session_id
17
- @trace_id = trace_id
18
- @source = source.presence
19
- @initial = initial
11
+ def initialize(path:, ip:, user_agent:, referer:, session_id:, trace_id:, source: nil, initial: false,
12
+ http_method: nil)
13
+ @path = path.to_s
14
+ @ip = ip
15
+ @user_agent = user_agent.to_s
16
+ @referer = referer
17
+ @session_id = session_id
18
+ @trace_id = trace_id
19
+ @source = source.presence
20
+ @initial = initial
21
+ @http_method = http_method
20
22
  end
21
23
 
22
24
  def call
@@ -32,7 +34,8 @@ module Trackguard
32
34
  session_id: @session_id,
33
35
  trace_id: @trace_id,
34
36
  source: @source,
35
- initial: @initial
37
+ initial: @initial,
38
+ http_method: @http_method
36
39
  )
37
40
  end
38
41
  end
@@ -15,6 +15,10 @@ module Trackguard
15
15
  migration_template "create_trackguard_tables.rb", "db/migrate/create_trackguard_tables.rb"
16
16
  end
17
17
 
18
+ def create_visits_migration_file
19
+ migration_template "add_trackguard_visits.rb", "db/migrate/add_trackguard_visits.rb"
20
+ end
21
+
18
22
  def print_next_steps
19
23
  say "\nNext steps:", :green
20
24
  say " 1. rails db:migrate"
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddTrackguardVisits < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
4
+ def up
5
+ rename_table :trackguard_page_views, :trackguard_visits
6
+
7
+ add_column :trackguard_visits, :type, :string
8
+ add_column :trackguard_visits, :block_reason, :string
9
+ add_column :trackguard_visits, :http_method, :string
10
+
11
+ add_index :trackguard_visits, :type
12
+ add_index :trackguard_visits, :block_reason
13
+
14
+ execute "UPDATE trackguard_visits SET type = 'Trackguard::PageView'"
15
+ end
16
+
17
+ def down
18
+ remove_index :trackguard_visits, :block_reason
19
+ remove_index :trackguard_visits, :type
20
+
21
+ remove_column :trackguard_visits, :http_method
22
+ remove_column :trackguard_visits, :block_reason
23
+ remove_column :trackguard_visits, :type
24
+
25
+ rename_table :trackguard_visits, :trackguard_page_views
26
+ end
27
+ end
@@ -26,6 +26,26 @@ module Trackguard
26
26
  limit: Trackguard.throttle_limit,
27
27
  period: Trackguard.throttle_period, &:ip
28
28
  )
29
+
30
+ subscribe_to_blocked_requests
31
+ end
32
+
33
+ def self.subscribe_to_blocked_requests
34
+ @subscribe_to_blocked_requests ||= ActiveSupport::Notifications.subscribe("rack.attack") do |*, payload|
35
+ req = payload[:request]
36
+ next unless req.env["rack.attack.match_type"] == :blocklist
37
+
38
+ Trackguard::TrackBlockedRequestJob.perform_later(
39
+ ip: req.ip,
40
+ user_agent: req.user_agent.to_s,
41
+ path: req.path,
42
+ http_method: req.request_method,
43
+ block_reason: req.env["rack.attack.matched"].to_s
44
+ )
45
+ rescue StandardError
46
+ # never let tracking errors surface into the middleware response
47
+ end
29
48
  end
49
+ private_class_method :subscribe_to_blocked_requests
30
50
  end
31
51
  end
@@ -1,3 +1,3 @@
1
1
  module Trackguard
2
- VERSION = "0.15.2".freeze
2
+ VERSION = "0.16.0".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trackguard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.2
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krzysztof Rygielski
@@ -56,9 +56,12 @@ files:
56
56
  - app/controllers/trackguard/page_views_controller.rb
57
57
  - app/helpers/trackguard/application_helper.rb
58
58
  - app/jobs/trackguard/detect_suspicious_visitors_job.rb
59
+ - app/jobs/trackguard/track_blocked_request_job.rb
59
60
  - app/jobs/trackguard/track_page_view_job.rb
61
+ - app/models/trackguard/blocked_request.rb
60
62
  - app/models/trackguard/blocked_user_agent.rb
61
63
  - app/models/trackguard/page_view.rb
64
+ - app/models/trackguard/visit.rb
62
65
  - app/models/trackguard/visitor.rb
63
66
  - app/models/trackguard/whitelisted_ip.rb
64
67
  - app/services/trackguard/application_service.rb
@@ -70,6 +73,7 @@ files:
70
73
  - config/importmap.rb
71
74
  - config/routes.rb
72
75
  - lib/generators/trackguard/install_generator.rb
76
+ - lib/generators/trackguard/templates/add_trackguard_visits.rb
73
77
  - lib/generators/trackguard/templates/create_trackguard_tables.rb
74
78
  - lib/tasks/trackguard.rake
75
79
  - lib/trackguard.rb