rails_surrogate_key_logging 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d4508c5a982897fd625ce7ee7625cedd7a78691b42a6562f9e036e2577f54b91
4
+ data.tar.gz: 5d5b0395a7cb737fd5f1dc90f0dbbf74a493fcdb91ad8644a9e802584b649e9a
5
+ SHA512:
6
+ metadata.gz: 3201bc7f7e84b36813141a3c9e24883d1fd3a416ec4f05d6e6345fd46d063ebf494bcf39ca333f5292eed7ca845e0604d80f4907064b3db78aac6a496a477a08
7
+ data.tar.gz: 105d8ed9be27bf5e3f633f230b5836668793c45960628749b09e71570279d7f754207ce4275542fd886129975a6e342da0ac221c32c7ba4b81d27ddc49e12d68
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # rails-surrogate-key-logging
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'surrogate_key_logging'
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_controller/log_subscriber'
4
+
5
+ module SurrogateKeyLogging
6
+ module ActionController
7
+ class LogSubscriber < ::ActionController::LogSubscriber
8
+
9
+ def start_processing(event)
10
+ event.payload[:params] = SurrogateKeyLogging.filter_parameters event.payload[:params]
11
+ super
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ module ActionController
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :LogSubscriber
8
+
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ module ActionDispatch
5
+ module Request
6
+
7
+ def filtered_query_string
8
+ super.gsub(::ActionDispatch::Request::PAIR_RE) do |_|
9
+ SurrogateKeyLogging.filter_parameters(::Regexp.last_match(1) => ::Regexp.last_match(2)).first.join('=')
10
+ end
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ module ActionDispatch
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Request
8
+
9
+ end
10
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+
5
+ module SurrogateKeyLogging
6
+ module ActiveRecord
7
+ module Attributes
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ surrogate_parent_names model_name.singular, model_name.plural
12
+ end
13
+
14
+ class_methods do
15
+ def surrogate_parent_names(*names)
16
+ @surrogate_parent_names ||= []
17
+ names.each do |name|
18
+ @surrogate_parent_names << name.to_sym
19
+ surrogate_attributes.each do |attr|
20
+ SurrogateKeyLogging.add_param_to_filter(attr, name)
21
+ end
22
+ end
23
+ @surrogate_parent_names
24
+ end
25
+
26
+ def surrogate_attributes(*attrs)
27
+ @surrogate_attributes ||= []
28
+ attrs.each do |attr|
29
+ @surrogate_attributes << attr.to_sym
30
+ surrogate_parent_names.each do |parent|
31
+ SurrogateKeyLogging.add_param_to_filter(attr, parent)
32
+ end
33
+ end
34
+ @surrogate_attributes
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ module ActiveRecord
5
+ class LogSubscriber < ::ActiveRecord::LogSubscriber
6
+
7
+ def sql(event) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
8
+ self.class.runtime += event.duration
9
+ return unless logger.debug?
10
+
11
+ payload = event.payload
12
+
13
+ return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
14
+
15
+ name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
16
+ name = "CACHE #{name}" if payload[:cached]
17
+ sql = payload[:sql]
18
+ binds = nil
19
+
20
+ name_match = /([A-Za-z]+) (Load|Update|Cache)/.match(payload[:name])
21
+ model = if name_match && name_match[1] && ::ActiveRecord::Base.descendants.map(&:to_s).include?(name_match[1])
22
+ name_match[1].safe_constantize
23
+ end
24
+
25
+ if payload[:binds]&.any?
26
+ casted_params = type_casted_binds(payload[:type_casted_binds])
27
+
28
+ binds = []
29
+ payload[:binds].each_with_index do |attr, i|
30
+ binds << render_bind(attr, casted_params[i], payload, model)
31
+ end
32
+ binds = binds.inspect
33
+ binds.prepend(' ')
34
+ end
35
+
36
+ name = colorize_payload_name(name, payload[:name])
37
+ sql = color(sql, sql_color(sql), true) if colorize_logging
38
+
39
+ debug " #{name} #{sql}#{binds}"
40
+ end
41
+
42
+ private
43
+
44
+ def basic_parameter_filter
45
+ @basic_parameter_filter ||= ::ActiveSupport::ParameterFilter.new(Rails.application.config.filter_parameters)
46
+ end
47
+
48
+ def type_casted_binds(casted_binds)
49
+ casted_binds.respond_to?(:call) ? casted_binds.call : casted_binds
50
+ end
51
+
52
+ def render_bind(attr, value, _payload, model) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
53
+ case attr
54
+ when ActiveModel::Attribute
55
+ value = "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>" if attr.type.binary? && attr.value
56
+ when Array
57
+ attr = attr.first
58
+ else
59
+ attr = nil
60
+ end
61
+
62
+ attr_name = attr&.name
63
+ if model && attr_name && model.respond_to?(:surrogate_attributes) && model.surrogate_attributes.include?(attr_name.to_sym)
64
+ value = SurrogateKeyLogging.key_manager.call(attr_name, value, model.to_s.underscore)
65
+ elsif attr_name
66
+ value = basic_parameter_filter.filter(attr_name => value)[attr_name]
67
+ end
68
+ [attr_name, value]
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ module ActiveRecord
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Attributes
8
+ autoload :LogSubscriber
9
+
10
+ end
11
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/parameter_filter'
4
+
5
+ # Add ability for @mask to be a class/instance/lambda/proc
6
+ module ActiveSupport
7
+ module ParameterFilter
8
+ class CompiledFilter
9
+
10
+ def value_for_key(key, value, parents = [], original_params = nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
11
+ parents.push(key) if deep_regexps
12
+ if regexps.any? { |r| r.match?(key.to_s) }
13
+ value = @mask.respond_to?(:call) ? @mask.call(key, value, parents, original_params) : @mask
14
+ elsif deep_regexps && (joined = parents.join('.')) && deep_regexps.any? { |r| r.match?(joined) } # rubocop:disable Lint/DuplicateBranch
15
+ value = @mask.respond_to?(:call) ? @mask.call(key, value, parents, original_params) : @mask
16
+ elsif value.is_a?(Hash)
17
+ value = call(value, parents, original_params)
18
+ elsif value.is_a?(Array)
19
+ # If we don't pop the current parent it will be duplicated as we
20
+ # process each array value.
21
+ parents.pop if deep_regexps
22
+ value = value.map { |v| value_for_key(key, v, parents, original_params) }
23
+ # Restore the parent stack after processing the array.
24
+ parents.push(key) if deep_regexps
25
+ elsif blocks.any?
26
+ key = key.dup if key.duplicable?
27
+ value = value.dup if value.duplicable?
28
+ blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
29
+ end
30
+ parents.pop if deep_regexps
31
+ value
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ class KeyManager
5
+
6
+ def call(key, value, _parents = [], _original_params = nil)
7
+ surrogate = "SK#{Digest::SHA512.hexdigest(value.to_s)}"
8
+ puts "surrogate for key: `#{key}`, value: `#{value}`, surrogate: `#{surrogate}`"
9
+ surrogate
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ class Middleware
5
+ attr_reader :app
6
+
7
+ def initialize(app)
8
+ @app = app
9
+ puts 'surrogate new'
10
+ end
11
+
12
+ def call(env)
13
+ SurrogateKeyLogging.reset
14
+ @app.call(env)
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails'
4
+
5
+ module SurrogateKeyLogging
6
+ class Railtie < Rails::Railtie
7
+ railtie_name :surrogate_key_logging
8
+
9
+ initializer 'surrogate_key_logging.filter_parameters' do
10
+ puts 'surrogate_key_logging.filter_parameters'
11
+ end
12
+
13
+ initializer 'surrogate_key_logging.logs' do
14
+ puts 'surrogate_key_logging.logs'
15
+ ::ActiveRecord::LogSubscriber.detach_from(:active_record)
16
+ ::SurrogateKeyLogging::ActiveRecord::LogSubscriber.attach_to(:active_record)
17
+ ::ActiveSupport::LogSubscriber.detach_from(:action_controller)
18
+ ::SurrogateKeyLogging::ActionController::LogSubscriber.attach_to(:action_controller)
19
+ ::ActionDispatch::Request.include SurrogateKeyLogging::ActionDispatch::Request
20
+ end
21
+
22
+ initializer 'surrogate_key_logging.middleware' do
23
+ puts 'surrogate_key_logging.middleware'
24
+ Rails.application.config.middleware.insert_before 0, Middleware
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+
5
+ module Version
6
+ MAJOR = 0
7
+ MINOR = 0
8
+ PATCH = 1
9
+
10
+ end
11
+
12
+ VERSION = [
13
+ Version::MAJOR,
14
+ Version::MINOR,
15
+ Version::PATCH,
16
+ ].join('.').freeze
17
+
18
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ # Container Module
6
+ module SurrogateKeyLogging
7
+ extend ActiveSupport::Autoload
8
+
9
+ autoload :Railtie
10
+ autoload :Version
11
+ autoload :ActionController
12
+ autoload :ActionDispatch
13
+ autoload :ActiveSupport
14
+ autoload :ActiveRecord
15
+ autoload :KeyManager
16
+ autoload :Middleware
17
+
18
+ class << self
19
+
20
+ def surrogate_attributes(*attrs)
21
+ @surrogate_attributes ||= []
22
+ attrs.each do |attr|
23
+ @surrogate_attributes << attr.to_s
24
+ end
25
+ @surrogate_attributes
26
+ end
27
+
28
+ def reset
29
+ @key_manager = @parameter_filter = nil
30
+ end
31
+
32
+ def key_manager
33
+ @key_manager ||= KeyManager.new
34
+ end
35
+
36
+ def parameter_filter
37
+ @parameter_filter ||= ::ActiveSupport::ParameterFilter.new(surrogate_attributes, mask: key_manager)
38
+ end
39
+
40
+ def filter_parameters(params)
41
+ parameter_filter.filter params
42
+ end
43
+
44
+ def add_param_to_filter(attr, parent = nil)
45
+ if parent.nil?
46
+ surrogate_attributes attr.to_s
47
+ else
48
+ surrogate_attributes(
49
+ "#{parent}.#{attr}",
50
+ "#{parent}[#{attr}]",
51
+ "[#{parent}][#{attr}]"
52
+ )
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ require 'surrogate_key_logging/railtie'
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
4
+ require 'surrogate_key_logging/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'rails_surrogate_key_logging'
8
+ s.version = SurrogateKeyLogging::VERSION
9
+ s.authors = ['Taylor Yelverton']
10
+ s.email = 'rubygems@yelvert.io'
11
+ s.homepage = 'https://github.com/ComplyMD/rails_surrogate_key_logging'
12
+ s.summary = ''
13
+ s.license = 'MIT'
14
+ s.description = ''
15
+ s.metadata = {
16
+ 'bug_tracker_uri' => 'https://github.com/ComplyMD/rails_surrogate_key_logging/issues',
17
+ 'changelog_uri' => 'https://github.com/ComplyMD/rails_surrogate_key_logging/commits/master',
18
+ 'documentation_uri' => 'https://github.com/ComplyMD/rails_surrogate_key_logging/wiki',
19
+ 'homepage_uri' => 'https://github.com/ComplyMD/rails_surrogate_key_logging',
20
+ 'source_code_uri' => 'https://github.com/ComplyMD/rails_surrogate_key_logging',
21
+ 'rubygems_mfa_required' => 'true',
22
+ }
23
+
24
+ s.files = Dir['lib/**/*', 'README.md', 'MIT-LICENSE', 'rails_surrogate_key_logging.gemspec']
25
+
26
+ s.require_paths = %w[ lib ]
27
+
28
+ s.required_ruby_version = '>= 2.7.0'
29
+
30
+ s.add_dependency('actionpack', '>= 6.0.0')
31
+ s.add_dependency('activerecord', '>= 6.0.0')
32
+ s.add_dependency('activesupport', '>= 6.0.0')
33
+ s.add_dependency('railties', '>= 6.0.0')
34
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_surrogate_key_logging
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Taylor Yelverton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionpack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 6.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 6.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 6.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 6.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 6.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 6.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: railties
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 6.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 6.0.0
69
+ description: ''
70
+ email: rubygems@yelvert.io
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - README.md
76
+ - lib/rails_surrogate_key_logging.rb
77
+ - lib/surrogate_key_logging.rb
78
+ - lib/surrogate_key_logging/action_controller.rb
79
+ - lib/surrogate_key_logging/action_controller/log_subscriber.rb
80
+ - lib/surrogate_key_logging/action_dispatch.rb
81
+ - lib/surrogate_key_logging/action_dispatch/request.rb
82
+ - lib/surrogate_key_logging/active_record.rb
83
+ - lib/surrogate_key_logging/active_record/attributes.rb
84
+ - lib/surrogate_key_logging/active_record/log_subscriber.rb
85
+ - lib/surrogate_key_logging/active_support.rb
86
+ - lib/surrogate_key_logging/key_manager.rb
87
+ - lib/surrogate_key_logging/middleware.rb
88
+ - lib/surrogate_key_logging/railtie.rb
89
+ - lib/surrogate_key_logging/version.rb
90
+ - rails_surrogate_key_logging.gemspec
91
+ homepage: https://github.com/ComplyMD/rails_surrogate_key_logging
92
+ licenses:
93
+ - MIT
94
+ metadata:
95
+ bug_tracker_uri: https://github.com/ComplyMD/rails_surrogate_key_logging/issues
96
+ changelog_uri: https://github.com/ComplyMD/rails_surrogate_key_logging/commits/master
97
+ documentation_uri: https://github.com/ComplyMD/rails_surrogate_key_logging/wiki
98
+ homepage_uri: https://github.com/ComplyMD/rails_surrogate_key_logging
99
+ source_code_uri: https://github.com/ComplyMD/rails_surrogate_key_logging
100
+ rubygems_mfa_required: 'true'
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 2.7.0
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 3.1.4
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: ''
120
+ test_files: []