trackguard 0.16.0 → 0.17.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: a4acea93b885f29862fb335806a5f378f63497793fff3e6a57cdb3eb2f0de255
4
- data.tar.gz: 0aa85cf87c159a589960c253ae5bb96b4ae095093b4b2963a7f4b96590e3b065
3
+ metadata.gz: 79ebac148a49b2b6df9f280c3a8e8e624fa82910ccf0e3d4c608a04ac7f73ced
4
+ data.tar.gz: a0a0648dacb35df737e19413603d658b1c015f6e5fa60d0a6adc72da497082da
5
5
  SHA512:
6
- metadata.gz: 1f770cb91aedabae79a1195b075a68d690eb730fb1ca55529c68b37ce156aebd42217174efc32beb8296d0a4bd6f45a67f94d56a3b9d8ca6103c5bc2b389bd42
7
- data.tar.gz: 67b00fa4e4f2500fc2145650871f973808f0c7e6af12b0e2b212dd700c8f35b8dae9e521c4a5719ead55dd5911e43db2e428e072e7e84ed514b18a0e35a4cd40
6
+ metadata.gz: 59d2f2a7dde041da4cc0acf29249c77d9f911a76c498f9381293c838a29bd6ac5fec3c875645c7be60b686d77cb99e4731032b45eb7a2a93464dadaac81b04cb
7
+ data.tar.gz: 5c1bf529774f1af5e8a7e83154e7e21b94e468c95702ac00bed7f0b133b85c092359e544e7f2f615d4e364d904e4512d16ad42d42e3c712d8f8dcb4b60cb81ae
@@ -11,11 +11,13 @@ module Trackguard
11
11
  end
12
12
  end
13
13
 
14
+ # rubocop:disable Metrics/AbcSize
14
15
  def flag
15
16
  if @visitor.update(
16
17
  flagged_at: Time.current,
17
18
  flag_reason: params[:flag_reason].presence,
18
- flagged_by: params[:flagged_by].presence || Visitor::FLAGGED_BY.first
19
+ flagged_by: params[:flagged_by].presence || Visitor::FLAGGED_BY.first,
20
+ name: params[:name].presence || BlockedUserAgent.matching_pattern(@visitor.user_agent)
19
21
  )
20
22
  respond_to do |format|
21
23
  format.html { redirect_back_or_to dashboard_path }
@@ -28,6 +30,7 @@ module Trackguard
28
30
  end
29
31
  end
30
32
  end
33
+ # rubocop:enable Metrics/AbcSize
31
34
 
32
35
  def unflag
33
36
  @visitor.update!(flagged_at: nil, flag_reason: nil, flagged_by: nil)
@@ -43,13 +43,15 @@ module Trackguard
43
43
  return if count.zero?
44
44
  return if visitor.whitelisted_ip&.active?
45
45
 
46
+ name = name_from_ua(visitor.user_agent)
47
+
46
48
  if count >= HARD_FLAG_THRESHOLD
47
- flag!(visitor, "#{count} page views in 24h (hard flag threshold)")
49
+ flag!(visitor, "#{count} page views in 24h (hard flag threshold)", name: name)
48
50
  return
49
51
  end
50
52
 
51
53
  if (reason = ua_flag_reason(visitor.user_agent))
52
- flag!(visitor, reason)
54
+ flag!(visitor, reason, name: name)
53
55
  return
54
56
  end
55
57
 
@@ -58,7 +60,7 @@ module Trackguard
58
60
  return if count < MIN_VIEWS
59
61
 
60
62
  if views.all? { |pv| pv.session_id.nil? && pv.referer.nil? && pv.path == "/" }
61
- flag!(visitor, "no session, no referrer, single root hit")
63
+ flag!(visitor, "no session, no referrer, single root hit", name: name)
62
64
  return
63
65
  end
64
66
 
@@ -85,7 +87,7 @@ module Trackguard
85
87
 
86
88
  return if score < FLAG_SCORE_THRESHOLD
87
89
 
88
- flag!(visitor, reasons.join("; "))
90
+ flag!(visitor, reasons.join("; "), name: name)
89
91
  end
90
92
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
91
93
 
@@ -107,7 +109,8 @@ module Trackguard
107
109
  .where("wi.id IS NULL OR wi.expires_at <= ?", Time.current)
108
110
  .distinct
109
111
  .each do |visitor|
110
- flag!(visitor, "trace_id shared across multiple visitors (cross-visitor bot detected)")
112
+ flag!(visitor, "trace_id shared across multiple visitors (cross-visitor bot detected)",
113
+ name: name_from_ua(visitor.user_agent))
111
114
  end
112
115
  end
113
116
 
@@ -115,8 +118,12 @@ module Trackguard
115
118
  "blank or minimal user-agent" if user_agent.blank? || user_agent.to_s.length < 10
116
119
  end
117
120
 
118
- def flag!(visitor, reason)
119
- visitor.update!(flagged_at: Time.current, flag_reason: reason, flagged_by: "claw:auto")
121
+ def flag!(visitor, reason, name: nil)
122
+ visitor.update!(flagged_at: Time.current, flag_reason: reason, flagged_by: "claw:auto", name: name)
123
+ end
124
+
125
+ def name_from_ua(user_agent)
126
+ BlockedUserAgent.matching_pattern(user_agent)
120
127
  end
121
128
 
122
129
  def blank_ratio(views, attr)
@@ -12,5 +12,12 @@ module Trackguard
12
12
  end
13
13
  patterns.any? { |p| user_agent.to_s.downcase.include?(p.downcase) }
14
14
  end
15
+
16
+ def self.matching_pattern(user_agent)
17
+ patterns = Rails.cache.fetch(CACHE_KEY, expires_in: 10.minutes) do
18
+ pluck(:pattern)
19
+ end
20
+ patterns.find { |p| user_agent.to_s.downcase.include?(p.downcase) }
21
+ end
15
22
  end
16
23
  end
@@ -151,6 +151,7 @@
151
151
  <%= hidden_field_tag :id, visitor.id %>
152
152
  <%= f.submit "Flag", class: "tg-btn tg-btn--danger" %>
153
153
  <%= f.text_field :flag_reason, placeholder: "Flag reason (optional)", class: "tg-input", autocomplete: "off" %>
154
+ <%= f.text_field :name, placeholder: "Name (optional, auto-detected if blank)", class: "tg-input", autocomplete: "off" %>
154
155
  <% end %>
155
156
  <% end %>
156
157
  </div>
@@ -175,6 +176,10 @@
175
176
  <span class="tg-dl__term">User agent</span>
176
177
  <span class="tg-dl__def tg-dl__def--break"><%= visitor&.user_agent.presence || "—" %></span>
177
178
  </div>
179
+ <div class="tg-dl__row">
180
+ <span class="tg-dl__term">Name</span>
181
+ <span class="tg-dl__def"><%= visitor&.name.presence || "—" %></span>
182
+ </div>
178
183
  <div class="tg-dl__row">
179
184
  <span class="tg-dl__term">Flag status</span>
180
185
  <% if flagged %>
@@ -63,6 +63,7 @@
63
63
  <%= hidden_field_tag :id, visitor.id %>
64
64
  <%= f.submit "Flag", class: "tg-btn tg-btn--danger" %>
65
65
  <%= f.text_field :flag_reason, placeholder: "Flag reason (optional)", class: "tg-input", autocomplete: "off" %>
66
+ <%= f.text_field :name, placeholder: "Name (optional, auto-detected if blank)", class: "tg-input", autocomplete: "off" %>
66
67
  <% end %>
67
68
  <% end %>
68
69
  </div>
@@ -87,6 +88,10 @@
87
88
  <span class="tg-dl__term">User agent</span>
88
89
  <span class="tg-dl__def tg-dl__def--break"><%= visitor&.user_agent.presence || "—" %></span>
89
90
  </div>
91
+ <div class="tg-dl__row">
92
+ <span class="tg-dl__term">Name</span>
93
+ <span class="tg-dl__def"><%= visitor&.name.presence || "—" %></span>
94
+ </div>
90
95
  <div class="tg-dl__row">
91
96
  <span class="tg-dl__term">Flag status</span>
92
97
  <% if flagged %>
@@ -0,0 +1,5 @@
1
+ class AddNameToTrackguardVisitors < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_column :trackguard_visitors, :name, :string
4
+ end
5
+ end
@@ -15,10 +15,6 @@ 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
-
22
18
  def print_next_steps
23
19
  say "\nNext steps:", :green
24
20
  say " 1. rails db:migrate"
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddVisitorName < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
4
+ def change
5
+ add_column :trackguard_visitors, :name, :string
6
+ end
7
+ end
@@ -13,20 +13,25 @@ class CreateTrackguardTables < ActiveRecord::Migration[<%= ActiveRecord::Migrati
13
13
 
14
14
  add_index :trackguard_visitors, :ip, unique: true
15
15
 
16
- create_table :trackguard_page_views do |t|
17
- t.string :path, null: false
16
+ create_table :trackguard_visits do |t|
17
+ t.string :type
18
+ t.string :path, null: false
18
19
  t.string :user_agent
19
20
  t.string :referer
20
21
  t.string :session_id
21
22
  t.string :trace_id
22
23
  t.string :source
23
- t.references :visitor, null: false, foreign_key: { to_table: :trackguard_visitors }
24
- t.datetime :created_at, null: false
24
+ t.string :block_reason
25
+ t.string :http_method
26
+ t.references :visitor, null: false, foreign_key: { to_table: :trackguard_visitors }
27
+ t.datetime :created_at, null: false
25
28
  end
26
29
 
27
- add_index :trackguard_page_views, :path
28
- add_index :trackguard_page_views, :created_at
29
- add_index :trackguard_page_views, :source
30
+ add_index :trackguard_visits, :type
31
+ add_index :trackguard_visits, :path
32
+ add_index :trackguard_visits, :created_at
33
+ add_index :trackguard_visits, :source
34
+ add_index :trackguard_visits, :block_reason
30
35
 
31
36
  create_table :trackguard_whitelisted_ips do |t|
32
37
  t.string :ip, null: false
@@ -0,0 +1,27 @@
1
+ require "rails/generators"
2
+ require "rails/generators/active_record"
3
+
4
+ module Trackguard
5
+ class UpgradeGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ def self.next_migration_number(dirname)
11
+ ActiveRecord::Generators::Base.next_migration_number(dirname)
12
+ end
13
+
14
+ def create_visits_migration_file
15
+ migration_template "add_trackguard_visits.rb", "db/migrate/add_trackguard_visits.rb"
16
+ end
17
+
18
+ def create_visitor_name_migration_file
19
+ migration_template "add_visitor_name.rb", "db/migrate/add_visitor_name.rb"
20
+ end
21
+
22
+ def print_next_steps
23
+ say "\nNext steps:", :green
24
+ say " 1. rails db:migrate"
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module Trackguard
2
- VERSION = "0.16.0".freeze
2
+ VERSION = "0.17.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.16.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krzysztof Rygielski
@@ -72,9 +72,12 @@ files:
72
72
  - app/views/trackguard/admin/visits/index.html.erb
73
73
  - config/importmap.rb
74
74
  - config/routes.rb
75
+ - db/migrate/20260505191009_add_name_to_trackguard_visitors.rb
75
76
  - lib/generators/trackguard/install_generator.rb
76
77
  - lib/generators/trackguard/templates/add_trackguard_visits.rb
78
+ - lib/generators/trackguard/templates/add_visitor_name.rb
77
79
  - lib/generators/trackguard/templates/create_trackguard_tables.rb
80
+ - lib/generators/trackguard/upgrade_generator.rb
78
81
  - lib/tasks/trackguard.rake
79
82
  - lib/trackguard.rb
80
83
  - lib/trackguard/engine.rb