active_record_anonymizer 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -1
- data/README.md +2 -2
- data/lib/active_record_anonymizer/attributes_anonymizer.rb +58 -0
- data/lib/active_record_anonymizer/configuration.rb +1 -1
- data/lib/active_record_anonymizer/extensions.rb +9 -43
- data/lib/active_record_anonymizer/{anonymizer.rb → initiator.rb} +2 -2
- data/lib/active_record_anonymizer/version.rb +1 -1
- data/lib/active_record_anonymizer.rb +1 -1
- data/lib/generators/active_record_anonymizer/templates/anonymizer.rb +1 -1
- data/lib/tasks/active_record_anonymizer.rake +8 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a644f35a1b766f9ff29cbc1c8d02f4b8dd521da9af8cb54e3e1ab2056d103af1
|
4
|
+
data.tar.gz: ef0ac08ee8dea107e714ddb22b1c7271f558272421e810556a161d0bb7bb954e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04f40e398b68ba3c74765d550294d6a29f060cc408fec1f7c9e48b22eca5e7fdc3501b7b288f70255ce7b36f1838a368974aa318e1ddd189cac713dc954e9e34
|
7
|
+
data.tar.gz: 3f7430c8b91d50476fd0e52592990814da6827ee13185bb8ce5ee3bf51bd970e96f13f1cae7b98752dde2a92ca899ad7a0b110ccfbb257fe033f1a81fd4d3533
|
data/CHANGELOG.md
CHANGED
@@ -14,4 +14,31 @@
|
|
14
14
|
|
15
15
|
* [GitHub PR](https://github.com/keshavbiswa/active_record_anonymizer/pull/7)
|
16
16
|
|
17
|
-
#### Fixed incorrect generator name in README.md
|
17
|
+
#### Fixed incorrect generator name in README.md
|
18
|
+
|
19
|
+
## Version 0.2.1
|
20
|
+
|
21
|
+
### New Fixes
|
22
|
+
|
23
|
+
#### Fixed validations breaking the anonymization process
|
24
|
+
|
25
|
+
* [GitHub PR](https://github.com/keshavbiswa/active_record_anonymizer/pull/8)
|
26
|
+
|
27
|
+
#### Renamed Anonymizer to Initiater
|
28
|
+
|
29
|
+
* [GitHub PR](https://github.com/keshavbiswa/active_record_anonymizer/pull/8)
|
30
|
+
|
31
|
+
#### Fixed populate:all task not loading models
|
32
|
+
|
33
|
+
* [GitHub PR](https://github.com/keshavbiswa/active_record_anonymizer/pull/9)
|
34
|
+
|
35
|
+
### Fixed configuration not reloading when changed
|
36
|
+
|
37
|
+
* [GitHub PR](https://github.com/keshavbiswa/active_record_anonymizer/pull/10)
|
38
|
+
|
39
|
+
### New Features
|
40
|
+
|
41
|
+
#### Added support for development environment
|
42
|
+
|
43
|
+
* [GitHub PR](https://github.com/keshavbiswa/active_record_anonymizer/pull/11)
|
44
|
+
|
data/README.md
CHANGED
@@ -82,14 +82,14 @@ end
|
|
82
82
|
|
83
83
|
You can configure the gem using the following options:
|
84
84
|
|
85
|
-
- `:environments` - The environments in which the anonymized data should be used. (Defaults to `[:
|
85
|
+
- `:environments` - The environments in which the anonymized data should be used. (Defaults to `[:development]`)
|
86
86
|
- `:skip_update` - Skip updating the anonymized data when the record is updated. This ensures your anonymized data remains the same even if it's updated. (Defaults to `false`)
|
87
87
|
- `:alias_original_columns` - Alias the original columns to the anonymized columns. You can still access the original value of the attribute using the alias `original_#{attribute_name}`(Defaults to `false`)
|
88
88
|
- `:alias_column_name` - The name of the alias column. (Defaults to `original_#{column_name}`)
|
89
89
|
|
90
90
|
```ruby
|
91
91
|
ActiveRecordAnonymizer.configure do |config|
|
92
|
-
config.environments = [:
|
92
|
+
config.environments = [:development, :staging] # The environments in which the anonymized data should be used
|
93
93
|
config.skip_update = true # Skip updating the anonymized data when the record is updated
|
94
94
|
config.alias_original_columns = true # Alias the original columns to the anonymized columns
|
95
95
|
config.alias_column_name = "original" # The original column will be aliased to "original_#{column_name}
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecordAnonymizer
|
4
|
+
class AttributesAnonymizer
|
5
|
+
attr_reader :model
|
6
|
+
|
7
|
+
def initialize(model, skip_update: false)
|
8
|
+
@model = model
|
9
|
+
@skip_update = skip_update
|
10
|
+
end
|
11
|
+
|
12
|
+
def anonymize_columns
|
13
|
+
if model.new_record?
|
14
|
+
anonymize_all_attributes
|
15
|
+
else
|
16
|
+
# Skip updating the record if skip_update is true
|
17
|
+
return if @skip_update
|
18
|
+
|
19
|
+
anonymize_changed_columns
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def populate
|
24
|
+
anonymize_all_attributes
|
25
|
+
model.save!
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def anonymize_all_attributes
|
31
|
+
model.class.anonymized_attributes.each_value do |settings|
|
32
|
+
generate_and_write_fake_value(settings[:column], settings[:with])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def anonymize_changed_columns
|
37
|
+
changes = model.changes.keys.map(&:to_sym)
|
38
|
+
changed_columns = changes & model.class.anonymized_attributes.keys
|
39
|
+
|
40
|
+
changed_columns.each do |column|
|
41
|
+
settings = model.class.anonymized_attributes[column]
|
42
|
+
generate_and_write_fake_value(settings[:column], settings[:with])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def generate_and_write_fake_value(anonymized_attr, with_strategy = nil)
|
47
|
+
fake_value = case with_strategy
|
48
|
+
when Proc
|
49
|
+
with_strategy.call(model)
|
50
|
+
when Symbol
|
51
|
+
model.send(with_strategy)
|
52
|
+
else
|
53
|
+
FakeValue.new(anonymized_attr, model.class.columns_hash[anonymized_attr.to_s]).generate_fake_value
|
54
|
+
end
|
55
|
+
model.write_attribute(anonymized_attr, fake_value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -5,7 +5,7 @@ module ActiveRecordAnonymizer
|
|
5
5
|
attr_accessor :environments, :skip_update, :alias_original_columns, :alias_column_name
|
6
6
|
|
7
7
|
def initialize
|
8
|
-
@environments = %i[
|
8
|
+
@environments = %i[development]
|
9
9
|
@skip_update = false
|
10
10
|
@alias_original_columns = false
|
11
11
|
@alias_column_name = "original"
|
@@ -24,63 +24,29 @@ module ActiveRecordAnonymizer
|
|
24
24
|
cattr_accessor :anonymized_attributes, instance_accessor: false unless respond_to?(:anonymized_attributes)
|
25
25
|
self.anonymized_attributes ||= {}
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
initiator = Initiator.new(self, attributes, with: with, column_name: column_name)
|
28
|
+
initiator.validate
|
29
|
+
initiator.configure_anonymization
|
30
30
|
|
31
31
|
# I'm ensuring that the before_save callback is only added once
|
32
32
|
# Models can call anonymize method multiple times per column
|
33
33
|
@setup_mutex.synchronize do
|
34
34
|
unless @anonymizer_setup_done
|
35
|
-
|
35
|
+
before_validation :anonymizer_anonymize_columns, if: :anonymizer_anonymization_enabled?
|
36
36
|
@anonymizer_setup_done = true
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
# Deliberately using anonymizer_ prefix to avoid conflicts
|
43
|
+
def anonymizer_anonymization_enabled?
|
43
44
|
ActiveRecordAnonymizer.anonymization_enabled?
|
44
45
|
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
anonymize_all_attributes
|
50
|
-
else
|
51
|
-
# For existing records, only apply to attributes that have changed
|
52
|
-
return if ActiveRecordAnonymizer.configuration.skip_update
|
53
|
-
|
54
|
-
anonymize_changed_attributes
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def anonymize_all_attributes
|
59
|
-
self.class.anonymized_attributes.each_value do |settings|
|
60
|
-
generate_and_write_fake_value(settings[:column], settings[:with])
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def anonymize_changed_attributes
|
65
|
-
changes = self.changes.keys.map(&:to_sym)
|
66
|
-
changed_attributes = changes & self.class.anonymized_attributes.keys
|
67
|
-
|
68
|
-
changed_attributes.each do |attribute|
|
69
|
-
settings = self.class.anonymized_attributes[attribute]
|
70
|
-
generate_and_write_fake_value(settings[:column], settings[:with])
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def generate_and_write_fake_value(anonymized_attr, with_strategy = nil)
|
75
|
-
fake_value = case with_strategy
|
76
|
-
when Proc
|
77
|
-
with_strategy.call(self)
|
78
|
-
when Symbol
|
79
|
-
send(with_strategy)
|
80
|
-
else
|
81
|
-
FakeValue.new(anonymized_attr, self.class.columns_hash[anonymized_attr.to_s]).generate_fake_value
|
82
|
-
end
|
83
|
-
write_attribute(anonymized_attr, fake_value)
|
47
|
+
# Deliberately using anonymizer_ prefix to avoid conflicts
|
48
|
+
def anonymizer_anonymize_columns
|
49
|
+
AttributesAnonymizer.new(self, skip_update: ActiveRecordAnonymizer.configuration.skip_update).anonymize_columns
|
84
50
|
end
|
85
51
|
end
|
86
52
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecordAnonymizer
|
4
|
-
class
|
4
|
+
class Initiator
|
5
5
|
attr_reader :model, :attributes, :with, :column_name
|
6
6
|
|
7
7
|
def initialize(model, attributes, with: nil, column_name: nil)
|
@@ -17,7 +17,7 @@ module ActiveRecordAnonymizer
|
|
17
17
|
check_for_missing_anonymized_columns(attributes)
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def configure_anonymization
|
21
21
|
attributes.each do |attribute|
|
22
22
|
anonymized_column = anonymized_column_name(attribute)
|
23
23
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
ActiveRecordAnonymizer.configure do |config|
|
4
4
|
# Configure the environments in which anonymization is allowed.
|
5
|
-
config.environments = %i[
|
5
|
+
config.environments = %i[development]
|
6
6
|
|
7
7
|
# Uncomment the following line to skip updating anonymized_columns when updating the original columns.
|
8
8
|
# config.skip_update = true
|
@@ -16,16 +16,22 @@ namespace :anonymizer do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
puts "Anonymize columns for #{klass_name}..."
|
19
|
-
model.
|
19
|
+
model.find_each do |record|
|
20
|
+
ActiveRecordAnonymizer::AttributesAnonymizer.new(record).populate
|
21
|
+
end
|
20
22
|
puts "Anonymize columns for #{klass_name} done!"
|
21
23
|
end
|
22
24
|
|
23
25
|
namespace :populate do
|
24
26
|
desc "populate anonymize columns for all models"
|
25
27
|
task all: :environment do
|
28
|
+
Rails.application.eager_load!
|
29
|
+
|
26
30
|
ActiveRecordAnonymizer.models.each do |model|
|
27
31
|
puts "Anonymizing #{model.name}..."
|
28
|
-
model.find_each
|
32
|
+
model.find_each do |record|
|
33
|
+
ActiveRecordAnonymizer::AttributesAnonymizer.new(record).populate
|
34
|
+
end
|
29
35
|
end
|
30
36
|
puts "Anonymize columns for all models done!"
|
31
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_anonymizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keshav Biswa
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-03-
|
11
|
+
date: 2024-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -81,11 +81,12 @@ files:
|
|
81
81
|
- README.md
|
82
82
|
- Rakefile
|
83
83
|
- lib/active_record_anonymizer.rb
|
84
|
-
- lib/active_record_anonymizer/
|
84
|
+
- lib/active_record_anonymizer/attributes_anonymizer.rb
|
85
85
|
- lib/active_record_anonymizer/configuration.rb
|
86
86
|
- lib/active_record_anonymizer/encryptor.rb
|
87
87
|
- lib/active_record_anonymizer/extensions.rb
|
88
88
|
- lib/active_record_anonymizer/fake_value.rb
|
89
|
+
- lib/active_record_anonymizer/initiator.rb
|
89
90
|
- lib/active_record_anonymizer/railtie.rb
|
90
91
|
- lib/active_record_anonymizer/version.rb
|
91
92
|
- lib/generators/active_record_anonymizer/USAGE
|