masking 1.1.0 → 1.1.1
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 +4 -4
- data/.circleci/config.yml +9 -4
- data/.github/workflows/acceptance_test_mariadb.yml +57 -1
- data/.github/workflows/acceptance_test_mysql.yml +1 -1
- data/.rubocop.yml +7 -1
- data/.rubocop_todo.yml +105 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +10 -0
- data/Dockerfile +3 -1
- data/Gemfile +20 -0
- data/Gemfile.lock +67 -51
- data/README.md +18 -8
- data/acceptance/expected_query_result.txt +36 -30
- data/acceptance/import_dumpfile.sql +3 -1
- data/acceptance/masking.yml +2 -0
- data/acceptance/run_test.sh +1 -1
- data/docker-compose/mariadb1010.yml +17 -0
- data/docker-compose/mariadb1011.yml +17 -0
- data/docker-compose/mariadb105.yml +17 -0
- data/docker-compose/mariadb106.yml +17 -0
- data/docker-compose/mariadb107.yml +17 -0
- data/docker-compose/mariadb108.yml +17 -0
- data/docker-compose/mariadb109.yml +17 -0
- data/lib/masking/cli/error_message.rb +1 -1
- data/lib/masking/config/target_columns/column.rb +19 -5
- data/lib/masking/config/target_columns/method/string_binary_distinctor.rb +3 -3
- data/lib/masking/config/target_columns/method/type/base.rb +25 -0
- data/lib/masking/config/target_columns/method/type/binary.rb +19 -0
- data/lib/masking/config/target_columns/method/type/boolean.rb +27 -0
- data/lib/masking/config/target_columns/method/type/date.rb +28 -0
- data/lib/masking/config/target_columns/method/type/extension/ignore_null.rb +24 -0
- data/lib/masking/config/target_columns/method/type/float.rb +19 -0
- data/lib/masking/config/target_columns/method/type/integer.rb +19 -0
- data/lib/masking/config/target_columns/method/{null.rb → type/null.rb} +5 -5
- data/lib/masking/config/target_columns/method/type/string.rb +37 -0
- data/lib/masking/config/target_columns/method/type/time.rb +26 -0
- data/lib/masking/config/target_columns/method.rb +14 -10
- data/lib/masking/insert_statement/sql_builder.rb +2 -2
- data/lib/masking/insert_statement.rb +1 -1
- data/lib/masking/sql_dump_line.rb +1 -0
- data/lib/masking/version.rb +1 -1
- data/masking.gemspec +1 -18
- metadata +24 -181
- data/lib/masking/config/target_columns/method/binary.rb +0 -23
- data/lib/masking/config/target_columns/method/boolean.rb +0 -29
- data/lib/masking/config/target_columns/method/date.rb +0 -30
- data/lib/masking/config/target_columns/method/float.rb +0 -23
- data/lib/masking/config/target_columns/method/integer.rb +0 -23
- data/lib/masking/config/target_columns/method/string.rb +0 -33
- data/lib/masking/config/target_columns/method/time.rb +0 -28
@@ -0,0 +1,17 @@
|
|
1
|
+
version: '3.7'
|
2
|
+
|
3
|
+
services:
|
4
|
+
app:
|
5
|
+
build:
|
6
|
+
target: with-mysql-client
|
7
|
+
depends_on:
|
8
|
+
- mariadb1011
|
9
|
+
entrypoint: docker-compose/wait-for-mysql.sh mariadb1011
|
10
|
+
|
11
|
+
mariadb1011:
|
12
|
+
image: mariadb:10.11
|
13
|
+
environment:
|
14
|
+
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
|
15
|
+
MYSQL_USER: mysqluser
|
16
|
+
MYSQL_PASSWORD: password
|
17
|
+
MYSQL_DATABASE: mydb
|
@@ -0,0 +1,17 @@
|
|
1
|
+
version: '3.7'
|
2
|
+
|
3
|
+
services:
|
4
|
+
app:
|
5
|
+
build:
|
6
|
+
target: with-mysql-client
|
7
|
+
depends_on:
|
8
|
+
- mariadb105
|
9
|
+
entrypoint: docker-compose/wait-for-mysql.sh mariadb105
|
10
|
+
|
11
|
+
mariadb105:
|
12
|
+
image: mariadb:10.5
|
13
|
+
environment:
|
14
|
+
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
|
15
|
+
MYSQL_USER: mysqluser
|
16
|
+
MYSQL_PASSWORD: password
|
17
|
+
MYSQL_DATABASE: mydb
|
@@ -0,0 +1,17 @@
|
|
1
|
+
version: '3.7'
|
2
|
+
|
3
|
+
services:
|
4
|
+
app:
|
5
|
+
build:
|
6
|
+
target: with-mysql-client
|
7
|
+
depends_on:
|
8
|
+
- mariadb106
|
9
|
+
entrypoint: docker-compose/wait-for-mysql.sh mariadb106
|
10
|
+
|
11
|
+
mariadb106:
|
12
|
+
image: mariadb:10.6
|
13
|
+
environment:
|
14
|
+
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
|
15
|
+
MYSQL_USER: mysqluser
|
16
|
+
MYSQL_PASSWORD: password
|
17
|
+
MYSQL_DATABASE: mydb
|
@@ -0,0 +1,17 @@
|
|
1
|
+
version: '3.7'
|
2
|
+
|
3
|
+
services:
|
4
|
+
app:
|
5
|
+
build:
|
6
|
+
target: with-mysql-client
|
7
|
+
depends_on:
|
8
|
+
- mariadb107
|
9
|
+
entrypoint: docker-compose/wait-for-mysql.sh mariadb107
|
10
|
+
|
11
|
+
mariadb107:
|
12
|
+
image: mariadb:10.7
|
13
|
+
environment:
|
14
|
+
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
|
15
|
+
MYSQL_USER: mysqluser
|
16
|
+
MYSQL_PASSWORD: password
|
17
|
+
MYSQL_DATABASE: mydb
|
@@ -0,0 +1,17 @@
|
|
1
|
+
version: '3.7'
|
2
|
+
|
3
|
+
services:
|
4
|
+
app:
|
5
|
+
build:
|
6
|
+
target: with-mysql-client
|
7
|
+
depends_on:
|
8
|
+
- mariadb108
|
9
|
+
entrypoint: docker-compose/wait-for-mysql.sh mariadb108
|
10
|
+
|
11
|
+
mariadb108:
|
12
|
+
image: mariadb:10.8
|
13
|
+
environment:
|
14
|
+
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
|
15
|
+
MYSQL_USER: mysqluser
|
16
|
+
MYSQL_PASSWORD: password
|
17
|
+
MYSQL_DATABASE: mydb
|
@@ -0,0 +1,17 @@
|
|
1
|
+
version: '3.7'
|
2
|
+
|
3
|
+
services:
|
4
|
+
app:
|
5
|
+
build:
|
6
|
+
target: with-mysql-client
|
7
|
+
depends_on:
|
8
|
+
- mariadb109
|
9
|
+
entrypoint: docker-compose/wait-for-mysql.sh mariadb109
|
10
|
+
|
11
|
+
mariadb109:
|
12
|
+
image: mariadb:10.9
|
13
|
+
environment:
|
14
|
+
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
|
15
|
+
MYSQL_USER: mysqluser
|
16
|
+
MYSQL_PASSWORD: password
|
17
|
+
MYSQL_DATABASE: mydb
|
@@ -6,22 +6,36 @@ module Masking
|
|
6
6
|
class Config
|
7
7
|
class TargetColumns
|
8
8
|
class Column
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :table_name, :method_value, :method
|
10
10
|
|
11
11
|
def initialize(name, table_name:, method_value:)
|
12
12
|
raise ColumnNameIsNil if name.nil?
|
13
13
|
|
14
|
-
@
|
15
|
-
@table_name
|
16
|
-
@method_value
|
17
|
-
@method
|
14
|
+
@original_name = name.to_sym
|
15
|
+
@table_name = table_name.to_sym
|
16
|
+
@method_value = method_value
|
17
|
+
@method = Method.new(method_value, ignore_null: ignore_null?)
|
18
18
|
end
|
19
19
|
|
20
20
|
def ==(other)
|
21
21
|
name == other.name && table_name == other.table_name && method_value == other.method_value
|
22
22
|
end
|
23
23
|
|
24
|
+
def name
|
25
|
+
@name ||= ignore_null? ? original_name.to_s.chomp(IGNORE_NULL_SUFFIX).to_sym : original_name
|
26
|
+
end
|
27
|
+
|
28
|
+
def ignore_null?
|
29
|
+
@ignore_null ||= original_name.to_s.end_with?(IGNORE_NULL_SUFFIX)
|
30
|
+
end
|
31
|
+
|
24
32
|
class ColumnNameIsNil < StandardError; end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_reader :original_name
|
37
|
+
|
38
|
+
IGNORE_NULL_SUFFIX = '?'
|
25
39
|
end
|
26
40
|
end
|
27
41
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'masking/config/target_columns/method/binary'
|
4
|
-
require 'masking/config/target_columns/method/string'
|
3
|
+
require 'masking/config/target_columns/method/type/binary'
|
4
|
+
require 'masking/config/target_columns/method/type/string'
|
5
5
|
|
6
6
|
module Masking
|
7
7
|
class Config
|
@@ -10,7 +10,7 @@ module Masking
|
|
10
10
|
module StringBinaryDistinctor
|
11
11
|
class << self
|
12
12
|
def new(value)
|
13
|
-
binary?(value) ? Binary.new(value) : String.new(value)
|
13
|
+
binary?(value) ? Type::Binary.new(value) : Type::String.new(value)
|
14
14
|
end
|
15
15
|
|
16
16
|
private
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Masking
|
4
|
+
class Config
|
5
|
+
class TargetColumns
|
6
|
+
class Method
|
7
|
+
module Type
|
8
|
+
class Base
|
9
|
+
def initialize(value)
|
10
|
+
@value = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(_sql_value)
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'masking/config/target_columns/method/type/base'
|
4
|
+
|
5
|
+
module Masking
|
6
|
+
class Config
|
7
|
+
class TargetColumns
|
8
|
+
class Method
|
9
|
+
module Type
|
10
|
+
class Binary < Base
|
11
|
+
def call(_sql_value)
|
12
|
+
"_binary '#{value}'".b
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'masking/config/target_columns/method/type/base'
|
4
|
+
|
5
|
+
module Masking
|
6
|
+
class Config
|
7
|
+
class TargetColumns
|
8
|
+
class Method
|
9
|
+
module Type
|
10
|
+
class Boolean < Base
|
11
|
+
def call(_sql_value)
|
12
|
+
boolean_format.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# NOTE: 11.1.1 Numeric Type Overview, chapter BOOL, BOOLEAN
|
18
|
+
# https://dev.mysql.com/doc/refman/8.0/en/numeric-type-overview.html
|
19
|
+
def boolean_format
|
20
|
+
value ? 1 : 0
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'masking/config/target_columns/method/type/base'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
module Masking
|
7
|
+
class Config
|
8
|
+
class TargetColumns
|
9
|
+
class Method
|
10
|
+
module Type
|
11
|
+
class Date < Base
|
12
|
+
def call(_sql_value)
|
13
|
+
"'#{date_format}'"
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
FORMAT = '%Y-%m-%d'
|
19
|
+
|
20
|
+
def date_format
|
21
|
+
value.strftime(FORMAT)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Masking
|
4
|
+
class Config
|
5
|
+
class TargetColumns
|
6
|
+
class Method
|
7
|
+
module Type
|
8
|
+
module Extension
|
9
|
+
module IgnoreNull
|
10
|
+
def call(sql_value)
|
11
|
+
if sql_value == 'NULL'
|
12
|
+
sequence! if respond_to?(:sequence!, true)
|
13
|
+
return 'NULL'
|
14
|
+
end
|
15
|
+
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'masking/config/target_columns/method/type/base'
|
4
|
+
|
5
|
+
module Masking
|
6
|
+
class Config
|
7
|
+
class TargetColumns
|
8
|
+
class Method
|
9
|
+
module Type
|
10
|
+
class Float < Base
|
11
|
+
def call(_sql_value)
|
12
|
+
value.to_s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'masking/config/target_columns/method/type/base'
|
4
|
+
|
5
|
+
module Masking
|
6
|
+
class Config
|
7
|
+
class TargetColumns
|
8
|
+
class Method
|
9
|
+
module Type
|
10
|
+
class Integer < Base
|
11
|
+
def call(_sql_value)
|
12
|
+
value.to_s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'masking/config/target_columns/method/type/base'
|
4
|
+
|
5
|
+
module Masking
|
6
|
+
class Config
|
7
|
+
class TargetColumns
|
8
|
+
class Method
|
9
|
+
module Type
|
10
|
+
class String < Base
|
11
|
+
def initialize(value)
|
12
|
+
super(value)
|
13
|
+
@sequence = 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(_sql_value)
|
17
|
+
sequence!
|
18
|
+
"'#{output}'".b
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
SEQUENTIAL_NUMBER_PLACEHOLDER = '%{n}' # rubocop:disable Style/FormatStringToken
|
24
|
+
|
25
|
+
def output
|
26
|
+
value.sub(SEQUENTIAL_NUMBER_PLACEHOLDER, @sequence.to_s)
|
27
|
+
end
|
28
|
+
|
29
|
+
def sequence!
|
30
|
+
@sequence += 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'masking/config/target_columns/method/type/base'
|
4
|
+
|
5
|
+
module Masking
|
6
|
+
class Config
|
7
|
+
class TargetColumns
|
8
|
+
class Method
|
9
|
+
module Type
|
10
|
+
class Time < Base
|
11
|
+
def call(_sql_value)
|
12
|
+
"'#{time_format}'"
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
FORMAT = '%Y-%m-%d %H:%M:%S'
|
18
|
+
def time_format
|
19
|
+
value.strftime(FORMAT)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'forwardable'
|
5
|
-
|
5
|
+
require 'masking/config/target_columns/method/type/extension/ignore_null'
|
6
|
+
require 'masking/config/target_columns/method/string_binary_distinctor'
|
7
|
+
Dir[Pathname(__FILE__).dirname.join('method/type/*.rb').to_s].sort.each(&method(:require))
|
6
8
|
|
7
9
|
module Masking
|
8
10
|
class Config
|
@@ -10,8 +12,10 @@ module Masking
|
|
10
12
|
class Method
|
11
13
|
extend Forwardable
|
12
14
|
|
13
|
-
def initialize(method)
|
14
|
-
@method_type = mapping(method.class).new(method)
|
15
|
+
def initialize(method, ignore_null: false)
|
16
|
+
@method_type = mapping(method.class).new(method).tap do |obj|
|
17
|
+
obj.singleton_class.prepend(Type::Extension::IgnoreNull) if ignore_null
|
18
|
+
end
|
15
19
|
end
|
16
20
|
|
17
21
|
def_delegator :@method_type, :call
|
@@ -21,13 +25,13 @@ module Masking
|
|
21
25
|
# rubocop:disable Layout/HashAlignment
|
22
26
|
MAPPING = {
|
23
27
|
::String => StringBinaryDistinctor,
|
24
|
-
::Integer => Integer,
|
25
|
-
::Float => Float,
|
26
|
-
::Date => Date,
|
27
|
-
::Time => Time,
|
28
|
-
::TrueClass => Boolean,
|
29
|
-
::FalseClass => Boolean,
|
30
|
-
::NilClass => Null
|
28
|
+
::Integer => Type::Integer,
|
29
|
+
::Float => Type::Float,
|
30
|
+
::Date => Type::Date,
|
31
|
+
::Time => Type::Time,
|
32
|
+
::TrueClass => Type::Boolean,
|
33
|
+
::FalseClass => Type::Boolean,
|
34
|
+
::NilClass => Type::Null
|
31
35
|
}.freeze
|
32
36
|
# rubocop:enable Layout/HashAlignment
|
33
37
|
|
@@ -18,11 +18,11 @@ module Masking
|
|
18
18
|
attr_reader :table, :columns, :values
|
19
19
|
|
20
20
|
def columns_section
|
21
|
-
'(' + columns.map { |column| "`#{column}`" }.join(', ') + ')'
|
21
|
+
'(' + columns.map { |column| "`#{column}`" }.join(', ') + ')' # rubocop:disable Style/StringConcatenation
|
22
22
|
end
|
23
23
|
|
24
24
|
def values_section
|
25
|
-
values.map { |value|
|
25
|
+
values.map { |value| "(#{value.join(',')})" }.join(',')
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
data/lib/masking/version.rb
CHANGED
data/masking.gemspec
CHANGED
@@ -25,22 +25,5 @@ Gem::Specification.new do |spec|
|
|
25
25
|
|
26
26
|
spec.required_ruby_version = '>= 2.6'
|
27
27
|
|
28
|
-
spec.
|
29
|
-
spec.add_development_dependency 'rake'
|
30
|
-
spec.add_development_dependency 'rake-notes'
|
31
|
-
spec.add_development_dependency 'ruby-prof'
|
32
|
-
|
33
|
-
# linter/static analyzer
|
34
|
-
spec.add_development_dependency 'mdl'
|
35
|
-
spec.add_development_dependency 'rubocop'
|
36
|
-
|
37
|
-
# test
|
38
|
-
spec.add_development_dependency 'codecov'
|
39
|
-
spec.add_development_dependency 'rspec'
|
40
|
-
spec.add_development_dependency 'simplecov'
|
41
|
-
|
42
|
-
# debug
|
43
|
-
spec.add_development_dependency 'pry'
|
44
|
-
spec.add_development_dependency 'pry-byebug'
|
45
|
-
spec.add_development_dependency 'tapp'
|
28
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
46
29
|
end
|