Class: DatabaseAnonymizer::Metamorphosis

Inherits:
Object
  • Object
show all
Defined in:
lib/database_anonymizer/metamorphosis.rb

Constant Summary collapse

DEFAULT_ASTERISK_LENGTH =
8

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ Metamorphosis

Returns a new instance of Metamorphosis.



60
61
62
# File 'lib/database_anonymizer/metamorphosis.rb', line 60

def initialize(model)
  @model = model
end

Instance Attribute Details

#modelObject (readonly)

Returns the value of attribute model.



5
6
7
# File 'lib/database_anonymizer/metamorphosis.rb', line 5

def model
  @model
end

Class Method Details

.anonymizeObject



44
45
46
47
48
49
50
51
# File 'lib/database_anonymizer/metamorphosis.rb', line 44

def self.anonymize
  fail DangerousRailsEnvError if Rails.env == 'production'
  whitelist.keys.each do |model_name|
    whitelist[model_name].each do |column, details|
      anonymize_log(model_name, column) { eval(details[:anonymized_by]) }
    end
  end
end

.anonymize_log(model_name, column) ⇒ Object



53
54
55
56
57
58
# File 'lib/database_anonymizer/metamorphosis.rb', line 53

def self.anonymize_log(model_name, column)
  ActiveRecord::Migration.say_with_time "anonymize for #{model_name}##{column} start..." do
    yield
    puts "-- anonymize for #{model_name}##{column} completed!"
  end
end

.asteriskizeObject



35
36
37
38
39
40
41
42
# File 'lib/database_anonymizer/metamorphosis.rb', line 35

def self.asteriskize
  case ActiveRecord::Base.configurations[Rails.env]['adapter']
  when 'mysql2'
    targets.each(&:mysql_asteriskize)
  else
    targets.each(&:general_asteriskize)
  end
end

.executeObject



30
31
32
33
# File 'lib/database_anonymizer/metamorphosis.rb', line 30

def self.execute
  asteriskize
  anonymize
end

.prepare_for_rakeObject



7
8
9
10
# File 'lib/database_anonymizer/metamorphosis.rb', line 7

def self.prepare_for_rake
  Rails.application.eager_load!
  ActiveRecord::Base.clear_cache!
end

.table_existing_active_record_inheritorsObject



20
21
22
23
24
# File 'lib/database_anonymizer/metamorphosis.rb', line 20

def self.table_existing_active_record_inheritors
  ActiveRecord::Base.descendants.reject do |d|
    !d.superclass.eql?(ActiveRecord::Base) || d.eql?(ActiveRecord::SchemaMigration) || !d.table_exists?
  end
end

.targetsObject



26
27
28
# File 'lib/database_anonymizer/metamorphosis.rb', line 26

def self.targets
  table_existing_active_record_inheritors.map { |model| new(model) }
end

.whitelistObject



16
17
18
# File 'lib/database_anonymizer/metamorphosis.rb', line 16

def self.whitelist
  YAML.load_file(whitelist_path).respond_to?(:deep_symbolize_keys) ? YAML.load_file(whitelist_path).deep_symbolize_keys : {}
end

.whitelist_pathObject



12
13
14
# File 'lib/database_anonymizer/metamorphosis.rb', line 12

def self.whitelist_path
  File.join(Rails.root, 'config', 'database_anonymizer', 'whitelist.yml')
end

Instance Method Details

#asterisk_length(column_length_validator) ⇒ Object



76
77
78
79
80
81
82
83
84
# File 'lib/database_anonymizer/metamorphosis.rb', line 76

def asterisk_length(column_length_validator)
  length = DEFAULT_ASTERISK_LENGTH
  return length unless column_length_validator
  length = column_length_validator.options[:minimum] if column_length_validator.options[:minimum]
  if column_length_validator.options[:maximum] && length > column_length_validator.options[:maximum]
    length = column_length_validator.options[:maximum]
  end
  length
end

#general_asteriskizeObject



98
99
100
101
# File 'lib/database_anonymizer/metamorphosis.rb', line 98

def general_asteriskize
  fail DangerousRailsEnvError if Rails.env == 'production'
  model.unscoped.find_each { |instance| instance.update!(asteriskize_params(instance)) }
end

#length_validator(column_name) ⇒ Object



72
73
74
# File 'lib/database_anonymizer/metamorphosis.rb', line 72

def length_validator(column_name)
  model.validators_on(column_name).find { |validator| validator.class.eql?(ActiveModel::Validations::LengthValidator) }
end

#mysql_asteriskizeObject



91
92
93
94
95
96
# File 'lib/database_anonymizer/metamorphosis.rb', line 91

def mysql_asteriskize
  fail DangerousRailsEnvError if Rails.env == 'production'
  unwhitelist_column_names.each do |column_name|
    ActiveRecord::Base.connection.execute(mysql_update_query(column_name))
  end
end

#mysql_update_query(column_name) ⇒ Object



86
87
88
89
# File 'lib/database_anonymizer/metamorphosis.rb', line 86

def mysql_update_query(column_name)
  # NOTE: If a column name is same as MySQL reserved words, backquote is needed.
  "UPDATE #{model.table_name} SET `#{column_name}`='#{'*' * asterisk_length(length_validator(column_name))}' WHERE `#{column_name}` LIKE '%_%'"
end

#string_or_text_column_namesObject



64
65
66
# File 'lib/database_anonymizer/metamorphosis.rb', line 64

def string_or_text_column_names
  model.columns.select { |column| [:string, :text].include?(column.type) }.map { |c| c.name.to_sym }
end

#unwhitelist_column_namesObject



68
69
70
# File 'lib/database_anonymizer/metamorphosis.rb', line 68

def unwhitelist_column_names
  string_or_text_column_names.select { |column_name| self.class.whitelist[model.to_s.to_sym].try!(:[], column_name).nil? }
end