userpattern 0.2.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +518 -0
- data/app/assets/stylesheets/user_pattern/dashboard.css +169 -0
- data/app/controllers/user_pattern/dashboard_controller.rb +58 -0
- data/app/models/user_pattern/request_event.rb +11 -0
- data/app/models/user_pattern/violation.rb +9 -0
- data/app/views/user_pattern/dashboard/index.html.erb +116 -0
- data/app/views/user_pattern/dashboard/violations.html.erb +79 -0
- data/config/routes.rb +7 -0
- data/lib/generators/userpattern/install_generator.rb +46 -0
- data/lib/generators/userpattern/templates/create_userpattern_request_events.rb.erb +23 -0
- data/lib/generators/userpattern/templates/create_userpattern_violations.rb.erb +22 -0
- data/lib/generators/userpattern/templates/initializer.rb +83 -0
- data/lib/tasks/userpattern.rake +9 -0
- data/lib/userpattern/anonymizer.rb +53 -0
- data/lib/userpattern/buffer.rb +70 -0
- data/lib/userpattern/configuration.rb +93 -0
- data/lib/userpattern/controller_tracking.rb +102 -0
- data/lib/userpattern/engine.rb +40 -0
- data/lib/userpattern/path_normalizer.rb +60 -0
- data/lib/userpattern/rate_limiter.rb +68 -0
- data/lib/userpattern/request_event_cleanup.rb +10 -0
- data/lib/userpattern/stats_calculator.rb +102 -0
- data/lib/userpattern/threshold_cache.rb +73 -0
- data/lib/userpattern/threshold_exceeded.rb +25 -0
- data/lib/userpattern/version.rb +5 -0
- data/lib/userpattern/violation_recorder.rb +28 -0
- data/lib/userpattern.rb +66 -0
- metadata +97 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'openssl'
|
|
4
|
+
|
|
5
|
+
module UserPattern
|
|
6
|
+
# Persists threshold violations with an anonymized user identifier.
|
|
7
|
+
# The raw user ID is NEVER stored — only a one-way HMAC hash.
|
|
8
|
+
class ViolationRecorder
|
|
9
|
+
def self.record!(violation)
|
|
10
|
+
Violation.create!(
|
|
11
|
+
model_type: violation.model_type,
|
|
12
|
+
endpoint: violation.endpoint,
|
|
13
|
+
period: violation.period,
|
|
14
|
+
count: violation.count,
|
|
15
|
+
limit: violation.limit,
|
|
16
|
+
user_identifier: anonymize_user_id(violation.user_id, violation.model_type),
|
|
17
|
+
occurred_at: Time.current
|
|
18
|
+
)
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
Rails.logger.error("[UserPattern] Violation record error: #{e.message}")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.anonymize_user_id(user_id, model_type)
|
|
24
|
+
salt = UserPattern.configuration.anonymous_salt
|
|
25
|
+
OpenSSL::HMAC.hexdigest('SHA256', salt, "#{model_type}:#{user_id}")[0, 16]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/userpattern.rb
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'userpattern/version'
|
|
4
|
+
require 'userpattern/configuration'
|
|
5
|
+
|
|
6
|
+
module UserPattern
|
|
7
|
+
class << self
|
|
8
|
+
def configuration
|
|
9
|
+
@configuration ||= Configuration.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def configure
|
|
13
|
+
yield(configuration)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def buffer
|
|
17
|
+
@buffer ||= begin
|
|
18
|
+
require 'userpattern/buffer'
|
|
19
|
+
Buffer.new
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
attr_reader :threshold_cache, :rate_limiter
|
|
24
|
+
|
|
25
|
+
def start_alert_mode!
|
|
26
|
+
require 'userpattern/threshold_cache'
|
|
27
|
+
require 'userpattern/rate_limiter'
|
|
28
|
+
|
|
29
|
+
@threshold_cache = ThresholdCache.new
|
|
30
|
+
store = configuration.rate_limiter_store || default_cache_store
|
|
31
|
+
@rate_limiter = RateLimiter.new(store: store, threshold_cache: @threshold_cache)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def enabled?
|
|
35
|
+
configuration.enabled
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def cleanup!
|
|
39
|
+
require 'userpattern/request_event_cleanup'
|
|
40
|
+
RequestEventCleanup.run!
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def reset!
|
|
44
|
+
@buffer&.shutdown
|
|
45
|
+
@threshold_cache&.shutdown
|
|
46
|
+
@configuration = Configuration.new
|
|
47
|
+
@buffer = nil
|
|
48
|
+
@threshold_cache = nil
|
|
49
|
+
@rate_limiter = nil
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def default_cache_store
|
|
55
|
+
if defined?(Rails) && Rails.respond_to?(:cache) && Rails.cache
|
|
56
|
+
Rails.cache
|
|
57
|
+
else
|
|
58
|
+
ActiveSupport::Cache::MemoryStore.new
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# :nocov:
|
|
65
|
+
require 'userpattern/engine' if defined?(Rails::Engine)
|
|
66
|
+
# :nocov:
|
metadata
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: userpattern
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- UserPattern Contributors
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: concurrent-ruby
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rails
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '7.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '7.0'
|
|
40
|
+
description: Track and analyze endpoint usage patterns of logged-in users with full
|
|
41
|
+
anonymization. Provides a sortable dashboard with per-model-type frequency statistics.
|
|
42
|
+
email: []
|
|
43
|
+
executables: []
|
|
44
|
+
extensions: []
|
|
45
|
+
extra_rdoc_files: []
|
|
46
|
+
files:
|
|
47
|
+
- LICENSE
|
|
48
|
+
- README.md
|
|
49
|
+
- app/assets/stylesheets/user_pattern/dashboard.css
|
|
50
|
+
- app/controllers/user_pattern/dashboard_controller.rb
|
|
51
|
+
- app/models/user_pattern/request_event.rb
|
|
52
|
+
- app/models/user_pattern/violation.rb
|
|
53
|
+
- app/views/user_pattern/dashboard/index.html.erb
|
|
54
|
+
- app/views/user_pattern/dashboard/violations.html.erb
|
|
55
|
+
- config/routes.rb
|
|
56
|
+
- lib/generators/userpattern/install_generator.rb
|
|
57
|
+
- lib/generators/userpattern/templates/create_userpattern_request_events.rb.erb
|
|
58
|
+
- lib/generators/userpattern/templates/create_userpattern_violations.rb.erb
|
|
59
|
+
- lib/generators/userpattern/templates/initializer.rb
|
|
60
|
+
- lib/tasks/userpattern.rake
|
|
61
|
+
- lib/userpattern.rb
|
|
62
|
+
- lib/userpattern/anonymizer.rb
|
|
63
|
+
- lib/userpattern/buffer.rb
|
|
64
|
+
- lib/userpattern/configuration.rb
|
|
65
|
+
- lib/userpattern/controller_tracking.rb
|
|
66
|
+
- lib/userpattern/engine.rb
|
|
67
|
+
- lib/userpattern/path_normalizer.rb
|
|
68
|
+
- lib/userpattern/rate_limiter.rb
|
|
69
|
+
- lib/userpattern/request_event_cleanup.rb
|
|
70
|
+
- lib/userpattern/stats_calculator.rb
|
|
71
|
+
- lib/userpattern/threshold_cache.rb
|
|
72
|
+
- lib/userpattern/threshold_exceeded.rb
|
|
73
|
+
- lib/userpattern/version.rb
|
|
74
|
+
- lib/userpattern/violation_recorder.rb
|
|
75
|
+
homepage: https://github.com/userpattern/userpattern
|
|
76
|
+
licenses:
|
|
77
|
+
- MIT
|
|
78
|
+
metadata:
|
|
79
|
+
rubygems_mfa_required: 'true'
|
|
80
|
+
rdoc_options: []
|
|
81
|
+
require_paths:
|
|
82
|
+
- lib
|
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
|
+
requirements:
|
|
85
|
+
- - ">="
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '3.2'
|
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
|
+
requirements:
|
|
90
|
+
- - ">="
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: '0'
|
|
93
|
+
requirements: []
|
|
94
|
+
rubygems_version: 3.6.7
|
|
95
|
+
specification_version: 4
|
|
96
|
+
summary: Anonymized usage pattern analysis for Rails applications
|
|
97
|
+
test_files: []
|