trackguard 0.15.2 → 0.16.1
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 +4 -4
- data/app/controllers/concerns/trackguard/page_tracker.rb +2 -1
- data/app/controllers/trackguard/page_views_controller.rb +2 -1
- data/app/jobs/trackguard/detect_suspicious_visitors_job.rb +1 -1
- data/app/jobs/trackguard/track_blocked_request_job.rb +24 -0
- data/app/jobs/trackguard/track_page_view_job.rb +3 -2
- data/app/models/trackguard/blocked_request.rb +13 -0
- data/app/models/trackguard/page_view.rb +1 -8
- data/app/models/trackguard/visit.rb +13 -0
- data/app/models/trackguard/visitor.rb +3 -2
- data/app/services/trackguard/page_view_recorder.rb +13 -10
- data/lib/generators/trackguard/templates/add_trackguard_visits.rb +27 -0
- data/lib/generators/trackguard/templates/create_trackguard_tables.rb +12 -7
- data/lib/generators/trackguard/upgrade_generator.rb +23 -0
- data/lib/trackguard/rack_attack.rb +20 -0
- data/lib/trackguard/version.rb +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b4c12f652065f915f2b4b906869a232738d8cf96632e6676f7107e84c442ea9d
|
|
4
|
+
data.tar.gz: a50ce6042ea670cb43486972f7a47a8187273aebd2947bd42f2ccfd4aba67225
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4eb185b4afe7cd71d3347afac5d203625a3348ff812647fc3ea6b04cff52bb2ded026d2601d546945900bd5f9a05bb0154fcb78a590ae6f5ec3249f283254b04
|
|
7
|
+
data.tar.gz: 18a0b707b1c085cab5c43a7249c4a6ed8bf753ba30a3b1e4e5bee00283381de4f2f511af06651009b587e9eeada7d69a860d4664f914adf92dfd2307e16d84f2
|
|
@@ -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(
|
|
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 <
|
|
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,
|
|
11
|
-
|
|
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
|
-
|
|
13
|
-
@
|
|
14
|
-
@
|
|
15
|
-
@
|
|
16
|
-
@
|
|
17
|
-
@
|
|
18
|
-
@
|
|
19
|
-
@
|
|
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
|
|
@@ -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
|
|
@@ -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 :
|
|
17
|
-
t.string :
|
|
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.
|
|
24
|
-
t.
|
|
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 :
|
|
28
|
-
add_index :
|
|
29
|
-
add_index :
|
|
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,23 @@
|
|
|
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 print_next_steps
|
|
19
|
+
say "\nNext steps:", :green
|
|
20
|
+
say " 1. rails db:migrate"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
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
|
data/lib/trackguard/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.16.1
|
|
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,7 +73,9 @@ 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
|
|
78
|
+
- lib/generators/trackguard/upgrade_generator.rb
|
|
74
79
|
- lib/tasks/trackguard.rake
|
|
75
80
|
- lib/trackguard.rb
|
|
76
81
|
- lib/trackguard/engine.rb
|