tidus 1.0.9 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b3221716efdbd435ff2ebef41c745eb240690c5
4
- data.tar.gz: 0fa789680f7cdd82e2e50ef591ab04f053b8c34d
3
+ metadata.gz: 2abe2b87088b2b0c6b190b31dd6deaa8db0fcbe5
4
+ data.tar.gz: 1816fedc56bf0c901745eb49db0ae6d9df71c87e
5
5
  SHA512:
6
- metadata.gz: 16242730fc087732b8d679e234b3da8c65846fde0aafa1be2ddb1ce238c5707876453bc6169e0ccc223932b1fd0a1a2c0168d9d811dccfe054a3705341175ad9
7
- data.tar.gz: 0e5a14be005c1494c20fa885bfc7fb51403c012ad2d49bdc13c64051a646ef7886ab23b23ba35fd81232e20e3c13c8cdb0bd1d88d26c98daf9ee9279861aedec
6
+ metadata.gz: 506f5b3c3f53586e3c9bdc909fc4cddb01b3b3c22ab85110a744e0478b38a504dc57ae5112fbb282b59d23b9decbc85518917b74fd4025a52336e11eb6fe907d
7
+ data.tar.gz: 3ed54eb937f1be9ee00d96764b5e6636386a75ad4c6e861077ef1d43ecc4f1158e37e9cc7a98acb27d2ddd560bd5100fbc21eec3a78d9555636a28857232e59e
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ module Tidus
4
+ class EanAnonymizer < Tidus::BaseSelector
5
+ end
6
+ end
@@ -0,0 +1,147 @@
1
+ module Tidus
2
+ module Postgresql
3
+ class EanAnonymizer
4
+ BASE_MAPPING = '0123456789'.freeze
5
+ DEFAULT_MAPPING_START = 1.freeze
6
+
7
+ def self.anonymize(table_name, column_name, options = {})
8
+ mapping_snippet = build_mapped_digit_snippet(column_name, options)
9
+
10
+ query = <<-SQL
11
+ (
12
+ SELECT
13
+ string_agg(new_digits.digit::TEXT, ''::TEXT)
14
+ FROM (
15
+ (
16
+ SELECT
17
+ pos,
18
+ digit
19
+ FROM (
20
+ #{mapping_snippet}
21
+ ) AS where_sub
22
+ ORDER BY pos ASC
23
+ )
24
+ UNION ALL
25
+ (
26
+ SELECT
27
+ LENGTH(#{column_name}::TEXT) AS pos,
28
+ (
29
+ 10
30
+ -
31
+ (
32
+ (
33
+ SELECT
34
+ SUM(digit)
35
+ FROM (
36
+ #{mapping_snippet}
37
+ ) AS where_sub
38
+ WHERE pos % 2 = LENGTH(#{column_name}::TEXT) % 2
39
+ )
40
+ +
41
+ (
42
+ SELECT
43
+ SUM(digit)
44
+ FROM (
45
+ #{mapping_snippet}
46
+ ) AS where_sub
47
+ WHERE pos % 2 = (LENGTH(#{column_name}::TEXT) - 1) % 2
48
+ ) * 3
49
+ ) % 10
50
+ ) % 10 AS digit
51
+ )
52
+ ) new_digits
53
+ )
54
+ SQL
55
+
56
+ return query.gsub!(/\n/, '').gsub!(/\ +/, ' ')
57
+ end
58
+
59
+ # Generates a new mapping if no cache_key is given
60
+ # Generates a new mapping if the cache_key is unknown
61
+ # Reuses the found mapping if the cache_key is known
62
+ def self.retrieve_mapping(cache_key)
63
+ @cached_mappings ||= {}
64
+ mapping = @cached_mappings[cache_key]
65
+
66
+ if mapping == nil
67
+ mapping = {
68
+ base: BASE_MAPPING,
69
+ replacement: BASE_MAPPING.split('').shuffle.join('')
70
+ }
71
+ end
72
+
73
+ if cache_key != nil
74
+ @cached_mappings[cache_key] = mapping
75
+ end
76
+
77
+ return mapping
78
+ end
79
+
80
+ def self.build_mapped_digit_snippet(column_name, options)
81
+ substrings = build_digit_mapping(column_name, options)
82
+
83
+ return <<-SQL
84
+ SELECT
85
+ *
86
+ FROM (
87
+ SELECT
88
+ ROW_NUMBER() over () AS pos,
89
+ digit::INT
90
+ FROM (
91
+ SELECT
92
+ REGEXP_SPLIT_TO_TABLE(
93
+ #{substrings.join(' || ')},
94
+ ''
95
+ ) AS digit
96
+ ) AS sub
97
+ ) AS sub
98
+ WHERE pos < LENGTH(#{column_name}::TEXT)
99
+ SQL
100
+ end
101
+
102
+ def self.build_digit_mapping(column_name, options)
103
+ mapping = retrieve_mapping(options[:cache_key])
104
+
105
+ options[:start] ||= DEFAULT_MAPPING_START
106
+
107
+ # reduce length by 1 to take away the check digit
108
+ total_length = "LENGTH(#{column_name}::TEXT) - 1"
109
+ length = options[:length] || total_length
110
+
111
+ substrings = []
112
+
113
+ if options[:start] != DEFAULT_MAPPING_START
114
+ substrings << build_substring_snippet(
115
+ column_name,
116
+ DEFAULT_MAPPING_START,
117
+ options[:start] - DEFAULT_MAPPING_START
118
+ )
119
+ end
120
+
121
+ translate_part = <<-SNIPPET
122
+ TRANSLATE(
123
+ #{build_substring_snippet(column_name, options[:start], length)},
124
+ '#{mapping[:base]}',
125
+ '#{mapping[:replacement]}'
126
+ )
127
+ SNIPPET
128
+
129
+ substrings << translate_part.gsub(/\n/, '').gsub(/\ +/, ' ')
130
+
131
+ if options[:length] != nil
132
+ substrings << build_substring_snippet(
133
+ column_name,
134
+ "#{options[:start]} + #{options[:length]}",
135
+ "#{total_length} - #{options[:start]}"
136
+ )
137
+ end
138
+
139
+ return substrings
140
+ end
141
+
142
+ def self.build_substring_snippet(column_name, start, length)
143
+ return "SUBSTRING(#{column_name}::TEXT, #{start}, #{length})"
144
+ end
145
+ end
146
+ end
147
+ end
@@ -1,3 +1,3 @@
1
1
  module Tidus
2
- VERSION = "1.0.9"
2
+ VERSION = "1.1.0"
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.9
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Schoknecht
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-08 00:00:00.000000000 Z
11
+ date: 2019-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -79,10 +79,12 @@ files:
79
79
  - lib/tidus/query.rb
80
80
  - lib/tidus/strategies/base_selector.rb
81
81
  - lib/tidus/strategies/cond_anonymizer.rb
82
+ - lib/tidus/strategies/ean_anonymizer.rb
82
83
  - lib/tidus/strategies/email_anonymizer.rb
83
84
  - lib/tidus/strategies/null_anonymizer.rb
84
85
  - lib/tidus/strategies/overlay_anonymizer.rb
85
86
  - lib/tidus/strategies/postgresql/cond_anonymizer.rb
87
+ - lib/tidus/strategies/postgresql/ean_anonymizer.rb
86
88
  - lib/tidus/strategies/postgresql/email_anonymizer.rb
87
89
  - lib/tidus/strategies/postgresql/null_anonymizer.rb
88
90
  - lib/tidus/strategies/postgresql/overlay_anonymizer.rb