tidus 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ef15fa25eadfd7fd12896aa48d5106c10c2d743
4
- data.tar.gz: 2e9e30f4a43c97913a518b13f0efaa987bb30dbf
3
+ metadata.gz: 16d22e9b2bf400af04c3c38e0d230a19134edf46
4
+ data.tar.gz: c8c0389b398d87c9b440efc68eb2586263137241
5
5
  SHA512:
6
- metadata.gz: 6359526ca259d737809d0161f1800f067ea626e7231302b0f892114f7d011496f0e807040cf55c7a775bacba1c3d276d4d66e3adacd92663fba7821921683175
7
- data.tar.gz: 41dd5744e5290b3fd8752710f664a7afeba92f6dec2ba8bfe03b301b9c1a1a9f6e413be15c4764af51ff39e575ce8738001bfea4d1768f78c5cc6fadd8bb5699
6
+ metadata.gz: 2633f5e90d829abb8e8a598302f54f5dc22def128e1b74d48b94300992fb3e80f85008f456d1906b40c36edef3e5400bb13035eeffca2c6e873854745d59eb48
7
+ data.tar.gz: 11cdfd7de96c1d7ad031d452b8c5c9f100e6dfbaeba35a5524bc709f86b083a6e9c7720f04b70ff931fc22f7ff87f2c5950d260e95d581a735689f062b8fe242
data/lib/tasks/views.rake CHANGED
@@ -6,9 +6,7 @@ namespace :db do
6
6
  next if c.table_name == "schema_migrations"
7
7
  puts "Clearing view '#{c.view_name}' for table '#{c.table_name}'"
8
8
 
9
- ActiveRecord::Base.connection.execute(
10
- "DROP VIEW IF EXISTS #{c.view_name}"
11
- )
9
+ c.clear_view
12
10
  end
13
11
  end
14
12
 
@@ -21,11 +19,7 @@ namespace :db do
21
19
  if ActiveRecord::Base.connection.table_exists? c.table_name
22
20
  puts "Generating view '#{c.view_name}' for table '#{c.table_name}'"
23
21
 
24
- ActiveRecord::Base.connection.execute(
25
- "CREATE VIEW #{c.view_name} AS " +
26
- "(SELECT #{c.view_columns.join(', ')} " +
27
- "FROM #{c.table_name})"
28
- )
22
+ c.create_view
29
23
  end
30
24
  end
31
25
  end
data/lib/tidus.rb CHANGED
@@ -1,14 +1,13 @@
1
+ # encoding: utf-8
2
+
1
3
  require "rake"
2
4
  require "active_record"
3
5
 
4
6
  require "tidus/version"
7
+ require "tidus/query"
5
8
  require "tidus/anonymization"
6
- require "tidus/strategies/cond_anonymizer.rb"
7
- require "tidus/strategies/email_anonymizer.rb"
8
- require "tidus/strategies/null_anonymizer.rb"
9
- require "tidus/strategies/overlay_anonymizer.rb"
10
- require "tidus/strategies/static_anonymizer.rb"
11
- require "tidus/strategies/text_anonymizer.rb"
9
+ require "tidus/strategies/base_selector"
10
+ Dir["#{File.dirname(__FILE__)}/tidus/strategies/**/*.rb"].each { |f| require f }
12
11
 
13
12
  load "active_record/railties/databases.rake"
14
13
  load "tasks/views.rake"
@@ -1,5 +1,9 @@
1
+ # encoding: utf-8
2
+
1
3
  module Tidus
2
4
  module Anonymization
5
+ include Tidus::Query
6
+
3
7
  def view_postfix
4
8
  @view_postfix || "anonymized"
5
9
  end
@@ -37,8 +41,8 @@ module Tidus
37
41
  options = attributes.extract_options!.dup
38
42
  columns = attributes - [options]
39
43
 
40
- raise ArgumentError, "You need to supply at least one attribute" if attributes.empty?
41
- raise ArgumentError, "You need to supply a strategy" if options[:strategy].blank?
44
+ raise ArgumentError, "Must have at least one attribute" if attributes.empty?
45
+ raise ArgumentError, "Must have a strategy" if options[:strategy].blank?
42
46
 
43
47
  columns.each do |column|
44
48
  key = options[:strategy].to_s.camelize
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ module Tidus
4
+ module Query
5
+ def create_query
6
+ "CREATE VIEW #{view_name} AS " +
7
+ "SELECT #{view_columns.join(', ')} " +
8
+ "FROM #{table_name}"
9
+ end
10
+
11
+ def create_view
12
+ connection.execute(create_query)
13
+ end
14
+
15
+ def clear_query
16
+ "DROP VIEW IF EXISTS #{view_name}"
17
+ end
18
+
19
+ def clear_view
20
+ connection.execute(clear_query)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ module Tidus
4
+ class BaseSelector
5
+ def self.anonymize(table_name, column_name, options = {})
6
+ adapter = ActiveRecord::Base.connection.instance_values["config"][:adapter]
7
+
8
+ begin
9
+ klass = Kernel.const_get("Tidus::#{adapter.camelize}::#{self.name.demodulize}")
10
+ klass.anonymize(table_name, column_name, options)
11
+ rescue NameError
12
+ raise "#{self.name} not implemented for #{adapter}"
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -1,44 +1,6 @@
1
- module Tidus
2
- class CondAnonymizer
3
- def self.anonymize(table_name, column_name, options = {})
4
- adapter = ActiveRecord::Base.connection.instance_values["config"][:adapter]
5
- case adapter
6
- when "postgresql"
7
- name = "#{table_name}.#{column_name}"
8
-
9
- type = options[:result_type] || "text"
10
- default = options[:default].nil? ? "#{name}::#{type}" : "'#{options[:default]}'::#{type}"
11
-
12
- if options[:conditions].blank?
13
- raise "Missing option :conditions for CondAnonymizer on #{name}"
14
- elsif options[:conditions].kind_of?(Array)
15
- conditions = options[:conditions]
16
- else
17
- conditions = [options[:conditions]]
18
- end
19
-
20
- command = "CASE "
1
+ # encoding: utf-8
21
2
 
22
- conditions.each do |cond|
23
- raise ":column for condition must be set" if cond[:column].blank?
24
- raise ":value for condition must be set" if cond[:value].nil?
25
- raise ":result for condition must be set" if cond[:result].nil?
26
- cond_column = cond[:column]
27
- cond_value = cond[:value]
28
- cond_type = cond[:type] || "text"
29
- comparator = cond[:comparator] || "="
30
- cond_result = cond[:result]
31
-
32
- command += "WHEN ((#{table_name}.#{cond_column})::#{cond_type} #{comparator} " +
33
- "'#{cond_value}'::#{cond_type}) THEN '#{cond_result}'::#{type} "
34
- end
35
-
36
- command += "ELSE #{default} END"
37
-
38
- return command
39
- else
40
- raise "#{self.name} not implemented for #{adapter}"
41
- end
42
- end
3
+ module Tidus
4
+ class CondAnonymizer < Tidus::BaseSelector
43
5
  end
44
6
  end
@@ -1,20 +1,7 @@
1
- module Tidus
2
- class EmailAnonymizer
3
- def self.anonymize(table_name, column_name, options = {})
4
- adapter = ActiveRecord::Base.connection.instance_values["config"][:adapter]
5
- case adapter
6
- when "postgresql"
7
- name = "#{table_name}.#{column_name}"
8
- options[:length] ||= 15
1
+ # encoding: utf-8
9
2
 
10
- return "CASE WHEN ((#{name})::text ~~ '%@%'::text) " +
11
- "THEN (((\"left\"(md5((#{name})::text), #{options[:length]}) || '@'::text) " +
12
- "|| split_part((#{name})::text, '@'::text, 2)))::character varying " +
13
- "ELSE #{name} END"
14
- else
15
- raise "#{self.name} not implemented for #{adapter}"
16
- end
17
- end
3
+ module Tidus
4
+ class EmailAnonymizer < Tidus::BaseSelector
18
5
  end
19
6
  end
20
7
 
@@ -1,13 +1,6 @@
1
+ # encoding: utf-8
2
+
1
3
  module Tidus
2
- class NullAnonymizer
3
- def self.anonymize(table_name, column_name, options = {})
4
- adapter = ActiveRecord::Base.connection.instance_values["config"][:adapter]
5
- case adapter
6
- when "postgresql"
7
- return "NULL::unknown"
8
- else
9
- raise "#{self.name} not implemented for #{adapter}"
10
- end
11
- end
4
+ class NullAnonymizer < Tidus::BaseSelector
12
5
  end
13
6
  end
@@ -1,21 +1,6 @@
1
- module Tidus
2
- class OverlayAnonymizer
3
- def self.anonymize(table_name, column_name, options = {})
4
- adapter = ActiveRecord::Base.connection.instance_values["config"][:adapter]
5
- case adapter
6
- when "postgresql"
7
- name = "#{table_name}.#{column_name}"
8
-
9
- raise "Missing option :start for OverlayAnonymizer on #{name}" if options[:start].blank?
10
- raise "Missing option :length for OverlayAnonymizer on #{name}" if options[:length].blank?
1
+ # encoding: utf-8
11
2
 
12
- overlay_char = options[:char] || "X"
13
- overlay = overlay_char * options[:length]
14
- return "\"overlay\"((#{name})::text, " +
15
- "'#{overlay}'::text, #{options[:start]})"
16
- else
17
- raise "#{self.name} not implemented for #{adapter}"
18
- end
19
- end
3
+ module Tidus
4
+ class OverlayAnonymizer < Tidus::BaseSelector
20
5
  end
21
6
  end
@@ -0,0 +1,40 @@
1
+ module Tidus
2
+ module Postgresql
3
+ class CondAnonymizer
4
+ def self.anonymize(table_name, column_name, options = {})
5
+ name = "#{table_name}.#{column_name}"
6
+
7
+ type = options[:result_type] || "text"
8
+ default = options[:default].nil? ? "#{name}::#{type}" : "'#{options[:default]}'::#{type}"
9
+
10
+ if options[:conditions].blank?
11
+ raise "Missing option :conditions for CondAnonymizer on #{name}"
12
+ elsif options[:conditions].kind_of?(Array)
13
+ conditions = options[:conditions]
14
+ else
15
+ conditions = [options[:conditions]]
16
+ end
17
+
18
+ command = "CASE "
19
+
20
+ conditions.each do |cond|
21
+ raise ":column for condition must be set" if cond[:column].blank?
22
+ raise ":value for condition must be set" if cond[:value].nil?
23
+ raise ":result for condition must be set" if cond[:result].nil?
24
+ cond_column = cond[:column]
25
+ cond_value = cond[:value]
26
+ cond_type = cond[:type] || "text"
27
+ comparator = cond[:comparator] || "="
28
+ cond_result = cond[:result]
29
+
30
+ command += "WHEN ((#{table_name}.#{cond_column})::#{cond_type} #{comparator} " +
31
+ "'#{cond_value}'::#{cond_type}) THEN '#{cond_result}'::#{type} "
32
+ end
33
+
34
+ command += "ELSE #{default} END"
35
+
36
+ return command
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,15 @@
1
+ module Tidus
2
+ module Postgresql
3
+ class EmailAnonymizer
4
+ def self.anonymize(table_name, column_name, options = {})
5
+ name = "#{table_name}.#{column_name}"
6
+ options[:length] ||= 15
7
+
8
+ return "CASE WHEN ((#{name})::text ~~ '%@%'::text) " +
9
+ "THEN (((\"left\"(md5((#{name})::text), #{options[:length]}) || '@'::text) " +
10
+ "|| split_part((#{name})::text, '@'::text, 2)))::character varying " +
11
+ "ELSE #{name} END"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Tidus
2
+ module Postgresql
3
+ class NullAnonymizer
4
+ def self.anonymize(table_name, column_name, options = {})
5
+ return "NULL::unknown"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module Tidus
2
+ module Postgresql
3
+ class OverlayAnonymizer
4
+ def self.anonymize(table_name, column_name, options = {})
5
+ name = "#{table_name}.#{column_name}"
6
+
7
+ raise "Missing option :start for OverlayAnonymizer on #{name}" if options[:start].blank?
8
+ raise "Missing option :length for OverlayAnonymizer on #{name}" if options[:length].blank?
9
+
10
+ overlay_char = options[:char] || "X"
11
+ overlay = overlay_char * options[:length]
12
+ return "\"overlay\"((#{name})::text, " +
13
+ "'#{overlay}'::text, #{options[:start]})"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ module Tidus
2
+ module Postgresql
3
+ class TextAnonymizer
4
+ def self.anonymize(table_name, column_name, options = {})
5
+ base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZCßüäöÜÄÖ"
6
+ return "translate((#{table_name}.#{column_name})::text, " +
7
+ "'#{base}'::text, '#{generate_mapping(base)}'::text)"
8
+ end
9
+
10
+ private
11
+ def self.generate_mapping(base)
12
+ upper = ("A".."Z").to_a
13
+ lower = ("a".."z").to_a
14
+ result = base.split("").map do |letter|
15
+ if letter == letter.upcase
16
+ upper.sample
17
+ else
18
+ lower.sample
19
+ end
20
+ end
21
+ result.join("")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ module Tidus
2
+ module Sqlite3
3
+ class NullAnonymizer
4
+ def self.anonymize(table_name, column_name, options = {})
5
+ return "NULL"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,15 +1,12 @@
1
+ # encoding: utf-8
2
+
1
3
  module Tidus
2
4
  class StaticAnonymizer
3
5
  def self.anonymize(table_name, column_name, options = {})
4
- adapter = ActiveRecord::Base.connection.instance_values["config"][:adapter]
5
- case adapter
6
- when "postgresql"
7
- raise "Missing option :value for StaticAnonymizer on #{table_name}.#{column_name}" if options[:value].blank?
6
+ raise "Missing option :value for StaticAnonymizer on #{table_name}.#{column_name}" if options[:value].blank?
7
+ type = options[:type] || "unknown"
8
8
 
9
- return "'#{options[:value]}'"
10
- else
11
- raise "#{self.name} not implemented for #{adapter}"
12
- end
9
+ return "'#{options[:value]}'::#{type}"
13
10
  end
14
11
  end
15
12
  end
@@ -1,28 +1,6 @@
1
- module Tidus
2
- class TextAnonymizer
3
- def self.anonymize(table_name, column_name, options = {})
4
- base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZCßüäöÜÄÖ"
5
- adapter = ActiveRecord::Base.connection.instance_values["config"][:adapter]
6
- case adapter
7
- when "postgresql"
8
- return "translate((#{table_name}.#{column_name})::text, " +
9
- "'#{base}'::text, '#{generate_mapping(base)}'::text)"
10
- else
11
- raise "#{self.name} not implemented for #{adapter}"
12
- end
13
- end
1
+ # encoding: utf-8
14
2
 
15
- private
16
- def self.generate_mapping(base)
17
- result = ""
18
- base.split("").each do |letter|
19
- if letter == letter.upcase
20
- result += ("A".."Z").to_a.shuffle.first
21
- else
22
- result += ("a".."z").to_a.shuffle.first
23
- end
24
- end
25
- result
26
- end
3
+ module Tidus
4
+ class TextAnonymizer < Tidus::BaseSelector
27
5
  end
28
6
  end
data/lib/tidus/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Tidus
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tidus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Schoknecht
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-09 00:00:00.000000000 Z
11
+ date: 2015-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -76,10 +76,18 @@ files:
76
76
  - lib/tasks/views.rake
77
77
  - lib/tidus.rb
78
78
  - lib/tidus/anonymization.rb
79
+ - lib/tidus/query.rb
80
+ - lib/tidus/strategies/base_selector.rb
79
81
  - lib/tidus/strategies/cond_anonymizer.rb
80
82
  - lib/tidus/strategies/email_anonymizer.rb
81
83
  - lib/tidus/strategies/null_anonymizer.rb
82
84
  - lib/tidus/strategies/overlay_anonymizer.rb
85
+ - lib/tidus/strategies/postgresql/cond_anonymizer.rb
86
+ - lib/tidus/strategies/postgresql/email_anonymizer.rb
87
+ - lib/tidus/strategies/postgresql/null_anonymizer.rb
88
+ - lib/tidus/strategies/postgresql/overlay_anonymizer.rb
89
+ - lib/tidus/strategies/postgresql/text_anonymizer.rb
90
+ - lib/tidus/strategies/sqlite3/null_anonymizer.rb
83
91
  - lib/tidus/strategies/static_anonymizer.rb
84
92
  - lib/tidus/strategies/text_anonymizer.rb
85
93
  - lib/tidus/version.rb
@@ -103,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
111
  version: '0'
104
112
  requirements: []
105
113
  rubyforge_project:
106
- rubygems_version: 2.4.5
114
+ rubygems_version: 2.4.6
107
115
  signing_key:
108
116
  specification_version: 4
109
117
  summary: Gem for creating anonymization views.