symmetric-encryption 4.0.0 → 4.0.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.
Files changed (42) hide show
  1. checksums.yaml +5 -5
  2. data/Rakefile +2 -2
  3. data/bin/symmetric-encryption +1 -1
  4. data/lib/symmetric-encryption.rb +1 -1
  5. data/lib/symmetric_encryption.rb +2 -2
  6. data/lib/symmetric_encryption/cipher.rb +15 -18
  7. data/lib/symmetric_encryption/cli.rb +30 -36
  8. data/lib/symmetric_encryption/coerce.rb +3 -4
  9. data/lib/symmetric_encryption/config.rb +30 -34
  10. data/lib/symmetric_encryption/encoder.rb +0 -1
  11. data/lib/symmetric_encryption/exception.rb +0 -2
  12. data/lib/symmetric_encryption/extensions/active_record/base.rb +5 -2
  13. data/lib/symmetric_encryption/extensions/mongo_mapper/plugins/encrypted_key.rb +3 -5
  14. data/lib/symmetric_encryption/extensions/mongoid/encrypted.rb +0 -2
  15. data/lib/symmetric_encryption/generator.rb +3 -3
  16. data/lib/symmetric_encryption/header.rb +9 -4
  17. data/lib/symmetric_encryption/key.rb +3 -4
  18. data/lib/symmetric_encryption/keystore.rb +9 -9
  19. data/lib/symmetric_encryption/keystore/environment.rb +6 -7
  20. data/lib/symmetric_encryption/keystore/file.rb +5 -6
  21. data/lib/symmetric_encryption/keystore/memory.rb +2 -2
  22. data/lib/symmetric_encryption/railtie.rb +4 -7
  23. data/lib/symmetric_encryption/railties/symmetric_encryption_validator.rb +2 -1
  24. data/lib/symmetric_encryption/reader.rb +28 -39
  25. data/lib/symmetric_encryption/symmetric_encryption.rb +10 -8
  26. data/lib/symmetric_encryption/utils/re_encrypt_files.rb +5 -8
  27. data/lib/symmetric_encryption/version.rb +2 -2
  28. data/lib/symmetric_encryption/writer.rb +12 -17
  29. data/test/active_record_test.rb +237 -200
  30. data/test/cipher_test.rb +12 -6
  31. data/test/encoder_test.rb +1 -3
  32. data/test/header_test.rb +0 -4
  33. data/test/key_test.rb +0 -2
  34. data/test/keystore/environment_test.rb +10 -11
  35. data/test/keystore/file_test.rb +9 -10
  36. data/test/keystore_test.rb +2 -3
  37. data/test/mongoid_test.rb +37 -40
  38. data/test/reader_test.rb +24 -32
  39. data/test/symmetric_encryption_test.rb +17 -18
  40. data/test/test_db.sqlite3 +0 -0
  41. data/test/writer_test.rb +0 -1
  42. metadata +23 -23
@@ -8,7 +8,6 @@ require 'erb'
8
8
  # The symmetric key is protected using the private key below and must
9
9
  # be distributed separately from the application
10
10
  module SymmetricEncryption
11
-
12
11
  # Defaults
13
12
  @@cipher = nil
14
13
  @@secondary_ciphers = []
@@ -26,7 +25,7 @@ module SymmetricEncryption
26
25
  # :date => Date
27
26
  # :json => Uses JSON serialization, useful for hashes and arrays
28
27
  # :yaml => Uses YAML serialization, useful for hashes and arrays
29
- COERCION_TYPES = [:string, :integer, :float, :decimal, :datetime, :time, :date, :boolean, :json, :yaml]
28
+ COERCION_TYPES = %i[string integer float decimal datetime time date boolean json yaml].freeze
30
29
 
31
30
  # Set the Primary Symmetric Cipher to be used
32
31
  #
@@ -48,10 +47,15 @@ module SymmetricEncryption
48
47
  # Returns the primary cipher if no match was found and version == 0
49
48
  # Returns nil if no match was found and version != 0
50
49
  def self.cipher(version = nil)
51
- raise(SymmetricEncryption::ConfigError, 'Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data') unless cipher?
50
+ unless cipher?
51
+ raise(
52
+ SymmetricEncryption::ConfigError,
53
+ 'Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data'
54
+ )
55
+ end
52
56
 
53
57
  return @@cipher if version.nil? || (@@cipher.version == version)
54
- secondary_ciphers.find { |c| c.version == version } || (@@cipher if version == 0)
58
+ secondary_ciphers.find { |c| c.version == version } || (@@cipher if version.zero?)
55
59
  end
56
60
 
57
61
  # Returns whether a primary cipher has been set
@@ -139,9 +143,7 @@ module SymmetricEncryption
139
143
  end
140
144
 
141
145
  # Try to force result to UTF-8 encoding, but if it is not valid, force it back to Binary
142
- unless decrypted.force_encoding(SymmetricEncryption::UTF8_ENCODING).valid_encoding?
143
- decrypted.force_encoding(SymmetricEncryption::BINARY_ENCODING)
144
- end
146
+ decrypted.force_encoding(SymmetricEncryption::BINARY_ENCODING) unless decrypted.force_encoding(SymmetricEncryption::UTF8_ENCODING).valid_encoding?
145
147
  Coerce.coerce_from_string(decrypted, type)
146
148
  end
147
149
 
@@ -155,7 +157,7 @@ module SymmetricEncryption
155
157
  return if decoded.nil? || decoded.empty?
156
158
 
157
159
  h = Header.new
158
- h.parse(decoded) == 0 ? nil : h
160
+ h.parse(decoded).zero? ? nil : h
159
161
  end
160
162
 
161
163
  # AES Symmetric Encryption of supplied string
@@ -39,7 +39,7 @@ module SymmetricEncryption
39
39
 
40
40
  # Re-encrypt the supplied encrypted value with the new cipher
41
41
  def re_encrypt(encrypted)
42
- if unencrypted = SymmetricEncryption.try_decrypt(encrypted)
42
+ if (unencrypted = SymmetricEncryption.try_decrypt(encrypted))
43
43
  cipher.encrypt(unencrypted)
44
44
  else
45
45
  encrypted
@@ -72,9 +72,7 @@ module SymmetricEncryption
72
72
  line
73
73
  end
74
74
  end
75
- if hits > 0
76
- File.open(file_name, 'wb') { |file| file.write(output_lines) }
77
- end
75
+ File.open(file_name, 'wb') { |file| file.write(output_lines) } if hits.positive?
78
76
  hits
79
77
  end
80
78
 
@@ -86,7 +84,7 @@ module SymmetricEncryption
86
84
  end
87
85
  File.delete(file_name)
88
86
  File.rename(temp_file_name, file_name)
89
- rescue
87
+ rescue StandardError
90
88
  File.delete(temp_file_name) if temp_file_name && File.exist?(temp_file_name)
91
89
  raise
92
90
  end
@@ -101,7 +99,7 @@ module SymmetricEncryption
101
99
  Dir[path].each do |file_name|
102
100
  next if File.directory?(file_name)
103
101
 
104
- if v = encrypted_file_version(file_name)
102
+ if (v = encrypted_file_version(file_name))
105
103
  if v == version
106
104
  puts "Skipping already re-encrypted file: #{file_name}"
107
105
  else
@@ -111,7 +109,7 @@ module SymmetricEncryption
111
109
  else
112
110
  begin
113
111
  count = re_encrypt_contents(file_name)
114
- puts "Re-encrypted #{count} encrypted value(s) in: #{file_name}" if count > 0
112
+ puts "Re-encrypted #{count} encrypted value(s) in: #{file_name}" if count.positive?
115
113
  rescue StandardError => exc
116
114
  puts "Failed re-encrypting the file contents of: #{file_name}. #{exc.class.name}: #{exc.message}"
117
115
  end
@@ -135,7 +133,6 @@ module SymmetricEncryption
135
133
  rescue OpenSSL::Cipher::CipherError
136
134
  nil
137
135
  end
138
-
139
136
  end
140
137
  end
141
138
  end
@@ -1,3 +1,3 @@
1
- module SymmetricEncryption #:nodoc
2
- VERSION = '4.0.0'
1
+ module SymmetricEncryption
2
+ VERSION = '4.0.1'.freeze
3
3
  end
@@ -51,7 +51,7 @@ module SymmetricEncryption
51
51
  ios = file_name_or_stream.is_a?(String) ? ::File.open(file_name_or_stream, 'wb') : file_name_or_stream
52
52
 
53
53
  begin
54
- file = self.new(ios, compress: compress, **args)
54
+ file = new(ios, compress: compress, **args)
55
55
  file = Zlib::GzipWriter.new(file) if compress
56
56
  block_given? ? yield(file) : file
57
57
  ensure
@@ -64,7 +64,7 @@ module SymmetricEncryption
64
64
  # Notes:
65
65
  # * Do not use this method for writing large files.
66
66
  def self.write(file_name_or_stream, data, **args)
67
- open(file_name_or_stream, **args) { |f| f.write(data) }
67
+ self.open(file_name_or_stream, **args) { |f| f.write(data) }
68
68
  end
69
69
 
70
70
  # Encrypt an entire file.
@@ -89,17 +89,15 @@ module SymmetricEncryption
89
89
  #
90
90
  # Notes:
91
91
  # * The file contents are streamed so that the entire file is _not_ loaded into memory.
92
- def self.encrypt(source:, target:, block_size: 65535, **args)
92
+ def self.encrypt(source:, target:, block_size: 65_535, **args)
93
93
  source_ios = source.is_a?(String) ? ::File.open(source, 'rb') : source
94
94
  bytes_written = 0
95
- open(target, **args) do |output_file|
96
- while !source_ios.eof?
97
- bytes_written += output_file.write(source_ios.read(block_size))
98
- end
95
+ self.open(target, **args) do |output_file|
96
+ bytes_written += output_file.write(source_ios.read(block_size)) until source_ios.eof?
99
97
  end
100
98
  bytes_written
101
99
  ensure
102
- source_ios.close if source_ios && source_ios.respond_to?(:closed?) && !source_ios.closed?
100
+ source_ios.close if source_ios&.respond_to?(:closed?) && !source_ios.closed?
103
101
  end
104
102
 
105
103
  # Encrypt data before writing to the supplied stream
@@ -114,9 +112,7 @@ module SymmetricEncryption
114
112
  raise(SymmetricEncryption::CipherError, "Cipher with version:#{version} not found in any of the configured SymmetricEncryption ciphers") unless cipher
115
113
 
116
114
  # Force header if compressed or using random iv, key
117
- if (header == true) || compress || random_key || random_iv
118
- header = Header.new(version: cipher.version, compress: compress, cipher_name: cipher_name)
119
- end
115
+ header = Header.new(version: cipher.version, compress: compress, cipher_name: cipher_name) if (header == true) || compress || random_key || random_iv
120
116
 
121
117
  @stream_cipher = ::OpenSSL::Cipher.new(cipher_name || cipher.cipher_name)
122
118
  @stream_cipher.encrypt
@@ -129,8 +125,8 @@ module SymmetricEncryption
129
125
 
130
126
  if random_iv
131
127
  header.iv = @stream_cipher.iv = @stream_cipher.random_iv
132
- else
133
- @stream_cipher.iv = cipher.iv if cipher.iv
128
+ elsif cipher.iv
129
+ @stream_cipher.iv = cipher.iv
134
130
  end
135
131
 
136
132
  @ios.write(header.to_s) if header
@@ -153,9 +149,9 @@ module SymmetricEncryption
153
149
  # ensure that the encrypted stream is closed before the stream itself is closed.
154
150
  def close(close_child_stream = true)
155
151
  return if closed?
156
- if size > 0
152
+ if size.positive?
157
153
  final = @stream_cipher.final
158
- @ios.write(final) if final.length > 0
154
+ @ios.write(final) unless final.empty?
159
155
  end
160
156
  @ios.close if close_child_stream
161
157
  @closed = true
@@ -170,7 +166,7 @@ module SymmetricEncryption
170
166
  bytes = data.to_s
171
167
  @size += bytes.size
172
168
  partial = @stream_cipher.update(bytes)
173
- @ios.write(partial) if partial.length > 0
169
+ @ios.write(partial) unless partial.empty?
174
170
  data.length
175
171
  end
176
172
 
@@ -201,6 +197,5 @@ module SymmetricEncryption
201
197
  # Returns [Integer] the number of unencrypted and uncompressed bytes
202
198
  # written to the file so far.
203
199
  attr_reader :size
204
-
205
200
  end
206
201
  end
@@ -1,9 +1,9 @@
1
1
  require_relative 'test_helper'
2
2
 
3
- ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read('test/config/database.yml')).result)
3
+ ActiveRecord::Base.configurations = YAML.safe_load(ERB.new(IO.read('test/config/database.yml')).result)
4
4
  ActiveRecord::Base.establish_connection(:test)
5
5
 
6
- #@formatter:off
6
+ # @formatter:off
7
7
  ActiveRecord::Schema.define version: 0 do
8
8
  create_table :users, force: true do |t|
9
9
  t.string :encrypted_bank_account_number
@@ -59,7 +59,7 @@ class User < ActiveRecord::Base
59
59
  attr_encrypted :text, type: :string
60
60
  attr_encrypted :number, type: :integer
61
61
 
62
- validates :text, format: { with: /\A[a-zA-Z ]+\z/, message: 'only allows letters' }, presence: true
62
+ validates :text, format: {with: /\A[a-zA-Z ]+\z/, message: 'only allows letters'}, presence: true
63
63
  validates :number, presence: true
64
64
  end
65
65
 
@@ -71,11 +71,11 @@ class UniqueUser < ActiveRecord::Base
71
71
  validates_uniqueness_of :encrypted_username, allow_blank: true, if: :encrypted_username_changed?
72
72
 
73
73
  validates :username,
74
- length: {in: 3..20},
75
- format: {with: /\A[\w\-]+\z/},
76
- allow_blank: true
74
+ length: {in: 3..20},
75
+ format: {with: /\A[\w\-]+\z/},
76
+ allow_blank: true
77
77
  end
78
- #@formatter:on
78
+ # @formatter:on
79
79
 
80
80
  #
81
81
  # Unit Test for attr_encrypted extensions in ActiveRecord
@@ -84,31 +84,45 @@ class ActiveRecordTest < Minitest::Test
84
84
  describe 'ActiveRecord' do
85
85
  INTEGER_VALUE = 12
86
86
  FLOAT_VALUE = 88.12345
87
- DECIMAL_VALUE = BigDecimal.new('22.51')
88
- DATETIME_VALUE = DateTime.new(2001, 11, 26, 20, 55, 54, "-5")
89
- TIME_VALUE = Time.new(2013, 01, 01, 22, 30, 00, "-04:00")
90
- DATE_VALUE = Date.new(1927, 04, 02)
91
- STRING_VALUE = 'A string containing some data to be encrypted with a random initialization vector'
92
- LONG_STRING_VALUE = 'A string containing some data to be encrypted with a random initialization vector and compressed since it takes up so much space in plain text form'
87
+ DECIMAL_VALUE = BigDecimal('22.51')
88
+ DATETIME_VALUE = DateTime.new(2001, 11, 26, 20, 55, 54, '-5')
89
+ TIME_VALUE = Time.new(2013, 1, 1, 22, 30, 0, '-04:00')
90
+ DATE_VALUE = Date.new(1927, 4, 2)
91
+ STRING_VALUE = 'A string containing some data to be encrypted with a random initialization vector'.freeze
92
+ LONG_STRING_VALUE = 'A string containing some data to be encrypted with a random initialization vector and compressed since it takes up so much space in plain text form'.freeze
93
93
  BINARY_STRING_VALUE = "Non-UTF8 Binary \x92 string".force_encoding('BINARY')
94
94
 
95
- before do
96
- @bank_account_number = '1234567890'
97
- @bank_account_number_encrypted = 'QEVuQwIAL94ArJeFlJrZp6SYsvoOGA=='
95
+ let :bank_account_number do
96
+ '1234567890'
97
+ end
98
98
 
99
- @social_security_number = '987654321'
100
- @social_security_number_encrypted = 'QEVuQwIAS+8X1NRrqdfEIQyFHVPuVA=='
99
+ let :bank_account_number_encrypted do
100
+ 'QEVuQwIAL94ArJeFlJrZp6SYsvoOGA=='
101
+ end
101
102
 
102
- @name = 'Joe Bloggs'
103
+ let :social_security_number do
104
+ '987654321'
105
+ end
103
106
 
104
- @h = {a: 'A', b: 'B'}
107
+ let :social_security_number_encrypted do
108
+ 'QEVuQwIAS+8X1NRrqdfEIQyFHVPuVA=='
109
+ end
105
110
 
106
- @user = User.new(
111
+ let :person_name do
112
+ 'Joe Bloggs'
113
+ end
114
+
115
+ let :hash_data do
116
+ {a: 'A', b: 'B'}
117
+ end
118
+
119
+ let :user do
120
+ User.new(
107
121
  # Encrypted Attribute
108
- bank_account_number: @bank_account_number,
122
+ bank_account_number: bank_account_number,
109
123
  # Encrypted Attribute
110
- social_security_number: @social_security_number,
111
- name: @name,
124
+ social_security_number: social_security_number,
125
+ name: person_name,
112
126
  # data type specific fields
113
127
  string_value: STRING_VALUE,
114
128
  long_string_value: LONG_STRING_VALUE,
@@ -121,127 +135,127 @@ class ActiveRecordTest < Minitest::Test
121
135
  date_value: DATE_VALUE,
122
136
  true_value: true,
123
137
  false_value: false,
124
- data_yaml: @h.dup,
125
- data_json: @h.dup,
138
+ data_yaml: hash_data.dup,
139
+ data_json: hash_data.dup,
126
140
  text: 'hello',
127
141
  number: '21'
128
142
  )
129
143
  end
130
144
 
131
145
  it 'has encrypted methods' do
132
- assert_equal true, @user.respond_to?(:encrypted_bank_account_number)
133
- assert_equal true, @user.respond_to?(:bank_account_number)
134
- assert_equal true, @user.respond_to?(:encrypted_social_security_number)
135
- assert_equal true, @user.respond_to?(:social_security_number)
136
- assert_equal true, @user.respond_to?(:data_yaml)
137
- assert_equal true, @user.respond_to?(:data_json)
138
- assert_equal false, @user.respond_to?(:encrypted_name)
139
- assert_equal true, @user.respond_to?(:encrypted_bank_account_number_changed?)
140
- assert_equal true, @user.respond_to?(:bank_account_number_changed?)
146
+ assert_equal true, user.respond_to?(:encrypted_bank_account_number)
147
+ assert_equal true, user.respond_to?(:bank_account_number)
148
+ assert_equal true, user.respond_to?(:encrypted_social_security_number)
149
+ assert_equal true, user.respond_to?(:social_security_number)
150
+ assert_equal true, user.respond_to?(:data_yaml)
151
+ assert_equal true, user.respond_to?(:data_json)
152
+ assert_equal false, user.respond_to?(:encrypted_name)
153
+ assert_equal true, user.respond_to?(:encrypted_bank_account_number_changed?)
154
+ assert_equal true, user.respond_to?(:bank_account_number_changed?)
141
155
  end
142
156
 
143
157
  it 'has unencrypted values' do
144
- assert_equal @bank_account_number, @user.bank_account_number
145
- assert_equal @social_security_number, @user.social_security_number
158
+ assert_equal bank_account_number, user.bank_account_number
159
+ assert_equal social_security_number, user.social_security_number
146
160
  end
147
161
 
148
162
  it 'has encrypted values' do
149
- assert_equal @bank_account_number_encrypted, @user.encrypted_bank_account_number
150
- assert_equal @social_security_number_encrypted, @user.encrypted_social_security_number
163
+ assert_equal bank_account_number_encrypted, user.encrypted_bank_account_number
164
+ assert_equal social_security_number_encrypted, user.encrypted_social_security_number
151
165
  end
152
166
 
153
167
  describe ':random_iv' do
154
168
  it 'false' do
155
- @user.social_security_number = @social_security_number
156
- assert first_value = @user.social_security_number
169
+ user.social_security_number = social_security_number
170
+ assert first_value = user.social_security_number
157
171
  # Assign the same value
158
- @user.social_security_number = @social_security_number
159
- assert_equal first_value, @user.social_security_number
172
+ user.social_security_number = social_security_number
173
+ assert_equal first_value, user.social_security_number
160
174
  end
161
175
 
162
176
  it 'true' do
163
- @user.string_value = STRING_VALUE
164
- assert first_value = @user.encrypted_string_value
165
- @user.string_value = 'blah'
166
- @user.string_value = STRING_VALUE
167
- refute_equal first_value, @user.encrypted_string_value
177
+ user.string_value = STRING_VALUE
178
+ assert first_value = user.encrypted_string_value
179
+ user.string_value = 'blah'
180
+ user.string_value = STRING_VALUE
181
+ refute_equal first_value, user.encrypted_string_value
168
182
  end
169
183
 
170
184
  it 'true and compress: true' do
171
- @user.string_value = STRING_VALUE
172
- @user.long_string_value = STRING_VALUE
185
+ user.string_value = STRING_VALUE
186
+ user.long_string_value = STRING_VALUE
173
187
 
174
- refute_equal @user.encrypted_long_string_value, @user.encrypted_string_value
188
+ refute_equal user.encrypted_long_string_value, user.encrypted_string_value
175
189
  end
176
190
 
177
191
  describe 'changed?' do
178
192
  it 'true for a new instance' do
179
- assert @user.string_value_changed?
193
+ assert user.string_value_changed?
180
194
  end
181
195
 
182
196
  it 'clears after save' do
183
- @user.save!
184
- refute @user.string_value_changed?
197
+ user.save!
198
+ refute user.string_value_changed?
185
199
  end
186
200
 
187
201
  it 'does not change when equal' do
188
- @user.save!
189
- before = @user.encrypted_string_value
190
- @user.string_value = STRING_VALUE
191
- refute @user.string_value_changed?
192
- assert_equal before, @user.encrypted_string_value
202
+ user.save!
203
+ before = user.encrypted_string_value
204
+ user.string_value = STRING_VALUE
205
+ refute user.string_value_changed?
206
+ assert_equal before, user.encrypted_string_value
193
207
  end
194
208
  end
195
209
  end
196
210
 
197
211
  describe 'attribute=' do
198
212
  it 'handles nil' do
199
- @user.string_value = nil
200
- assert_nil @user.string_value
201
- assert_nil @user.encrypted_string_value
202
- @user.save!
203
- @user.reload
204
- assert_nil @user.string_value
205
- assert_nil @user.encrypted_string_value
213
+ user.string_value = nil
214
+ assert_nil user.string_value
215
+ assert_nil user.encrypted_string_value
216
+ user.save!
217
+ user.reload
218
+ assert_nil user.string_value
219
+ assert_nil user.encrypted_string_value
206
220
  end
207
221
 
208
222
  it 'handles empty string' do
209
- @user.string_value = ''
210
- assert_equal '', @user.string_value
211
- assert_equal '', @user.encrypted_string_value
212
- @user.save!
213
- @user.reload
214
- assert_equal '', @user.string_value
215
- assert_equal '', @user.encrypted_string_value
223
+ user.string_value = ''
224
+ assert_equal '', user.string_value
225
+ assert_equal '', user.encrypted_string_value
226
+ user.save!
227
+ user.reload
228
+ assert_equal '', user.string_value
229
+ assert_equal '', user.encrypted_string_value
216
230
  end
217
231
 
218
232
  it 'encrypt' do
219
233
  user = User.new
220
- user.bank_account_number = @bank_account_number
221
- assert_equal @bank_account_number, user.bank_account_number
222
- assert_equal @bank_account_number_encrypted, user.encrypted_bank_account_number
234
+ user.bank_account_number = bank_account_number
235
+ assert_equal bank_account_number, user.bank_account_number
236
+ assert_equal bank_account_number_encrypted, user.encrypted_bank_account_number
223
237
  end
224
238
 
225
239
  it 'all paths it lead to the same result' do
226
- assert_equal @bank_account_number_encrypted, (@user.encrypted_social_security_number = @bank_account_number_encrypted)
227
- assert_equal @bank_account_number, @user.social_security_number
228
- assert_equal @bank_account_number_encrypted, @user.encrypted_social_security_number
240
+ assert_equal bank_account_number_encrypted, (user.encrypted_social_security_number = bank_account_number_encrypted)
241
+ assert_equal bank_account_number, user.social_security_number
242
+ assert_equal bank_account_number_encrypted, user.encrypted_social_security_number
229
243
  end
230
244
 
231
245
  it 'all paths it lead to the same result 2' do
232
- assert_equal @bank_account_number, (@user.social_security_number = @bank_account_number)
233
- assert_equal @bank_account_number_encrypted, @user.encrypted_social_security_number
234
- assert_equal @bank_account_number, @user.social_security_number
246
+ assert_equal bank_account_number, (user.social_security_number = bank_account_number)
247
+ assert_equal bank_account_number_encrypted, user.encrypted_social_security_number
248
+ assert_equal bank_account_number, user.social_security_number
235
249
  end
236
250
 
237
251
  it 'all paths it lead to the same result, check uninitialized' do
238
252
  user = User.new
239
253
  assert_nil user.social_security_number
240
- assert_equal @bank_account_number, (user.social_security_number = @bank_account_number)
241
- assert_equal @bank_account_number, user.social_security_number
242
- assert_equal @bank_account_number_encrypted, user.encrypted_social_security_number
254
+ assert_equal bank_account_number, (user.social_security_number = bank_account_number)
255
+ assert_equal bank_account_number, user.social_security_number
256
+ assert_equal bank_account_number_encrypted, user.encrypted_social_security_number
243
257
 
244
- assert_nil (user.social_security_number = nil)
258
+ user.social_security_number = nil
245
259
  assert_nil user.social_security_number
246
260
  assert_nil user.encrypted_social_security_number
247
261
  end
@@ -249,11 +263,11 @@ class ActiveRecordTest < Minitest::Test
249
263
 
250
264
  describe '.new' do
251
265
  it 'allows unencrypted values to be passed to the constructor' do
252
- user = User.new(bank_account_number: @bank_account_number, social_security_number: @social_security_number)
253
- assert_equal @bank_account_number, user.bank_account_number
254
- assert_equal @social_security_number, user.social_security_number
255
- assert_equal @bank_account_number_encrypted, user.encrypted_bank_account_number
256
- assert_equal @social_security_number_encrypted, user.encrypted_social_security_number
266
+ user = User.new(bank_account_number: bank_account_number, social_security_number: social_security_number)
267
+ assert_equal bank_account_number, user.bank_account_number
268
+ assert_equal social_security_number, user.social_security_number
269
+ assert_equal bank_account_number_encrypted, user.encrypted_bank_account_number
270
+ assert_equal social_security_number_encrypted, user.encrypted_social_security_number
257
271
  end
258
272
  end
259
273
 
@@ -261,13 +275,13 @@ class ActiveRecordTest < Minitest::Test
261
275
  it 'returns encrypted attributes for the class' do
262
276
  expect = {social_security_number: :encrypted_social_security_number, bank_account_number: :encrypted_bank_account_number}
263
277
  result = User.encrypted_attributes
264
- expect.each_pair { |k, v| assert_equal expect[k], result[k] }
278
+ expect.each_pair { |k, _v| assert_equal expect[k], result[k] }
265
279
  end
266
280
  end
267
281
 
268
282
  describe '.encrypted_keys' do
269
283
  it 'return encrypted keys for the class' do
270
- expect = [:social_security_number, :bank_account_number]
284
+ expect = %i[social_security_number bank_account_number]
271
285
  result = User.encrypted_keys
272
286
  expect.each { |val| assert result.include?(val) }
273
287
 
@@ -278,7 +292,7 @@ class ActiveRecordTest < Minitest::Test
278
292
 
279
293
  describe '.encrypted_columns' do
280
294
  it 'return encrypted columns for the class' do
281
- expect = [:encrypted_social_security_number, :encrypted_bank_account_number]
295
+ expect = %i[encrypted_social_security_number encrypted_bank_account_number]
282
296
  result = User.encrypted_columns
283
297
  expect.each { |val| assert result.include?(val) }
284
298
 
@@ -288,123 +302,152 @@ class ActiveRecordTest < Minitest::Test
288
302
  end
289
303
 
290
304
  describe '#valid?' do
291
- it 'validate encrypted data' do
292
- assert @user.valid?
293
- @user.encrypted_bank_account_number = '123'
294
- assert_equal false, @user.valid?
295
- assert_equal ['must be a value encrypted using SymmetricEncryption.encrypt'], @user.errors[:encrypted_bank_account_number]
296
- @user.encrypted_bank_account_number = SymmetricEncryption.encrypt('123')
297
- assert @user.valid?
298
- @user.bank_account_number = '123'
299
- assert @user.valid?
305
+ before do
306
+ assert user.valid?
307
+ end
308
+
309
+ it 'fails invalid data' do
310
+ user.encrypted_bank_account_number = '123'
311
+ assert_equal false, user.valid?
312
+ assert_equal ['must be a value encrypted using SymmetricEncryption.encrypt'], user.errors[:encrypted_bank_account_number]
313
+ end
314
+
315
+ it 'passes encrypted data' do
316
+ user.encrypted_bank_account_number = SymmetricEncryption.encrypt('123')
317
+ assert user.valid?
318
+ end
319
+
320
+ it 'passes valid data' do
321
+ user.bank_account_number = '123'
322
+ assert user.valid?
323
+ end
324
+
325
+ it 'passes nil encrypted data' do
326
+ user.encrypted_bank_account_number = nil
327
+ assert user.valid?
328
+ end
329
+
330
+ it 'passes empty string encrypted data' do
331
+ user.encrypted_bank_account_number = ''
332
+ assert user.valid?
333
+ end
334
+
335
+ it 'passes nil data' do
336
+ user.bank_account_number = nil
337
+ assert user.valid?
338
+ end
339
+
340
+ it 'passes empty string data' do
341
+ user.bank_account_number = ''
342
+ assert user.valid?
300
343
  end
301
344
 
302
345
  it 'validate un-encrypted string data' do
303
- assert @user.valid?
304
- @user.text = '123'
305
- assert_equal false, @user.valid?
306
- assert_equal ['only allows letters'], @user.errors[:text]
307
- @user.text = nil
308
- assert_equal false, @user.valid?
309
- assert_equal ['only allows letters', "can't be blank"], @user.errors[:text]
310
- @user.text = ''
311
- assert_equal false, @user.valid?
312
- assert_equal ['only allows letters', "can't be blank"], @user.errors[:text]
346
+ assert user.valid?
347
+ user.text = '123'
348
+ assert_equal false, user.valid?
349
+ assert_equal ['only allows letters'], user.errors[:text]
350
+ user.text = nil
351
+ assert_equal false, user.valid?
352
+ assert_equal ['only allows letters', "can't be blank"], user.errors[:text]
353
+ user.text = ''
354
+ assert_equal false, user.valid?
355
+ assert_equal ['only allows letters', "can't be blank"], user.errors[:text]
313
356
  end
314
357
 
315
358
  it 'validate un-encrypted integer data with coercion' do
316
- assert @user.valid?
317
- @user.number = '123'
318
- assert @user.valid?
319
- assert_equal 123, @user.number
320
- assert @user.valid?
321
- @user.number = ''
322
- assert_equal false, @user.valid?
323
- assert_equal '', @user.number
324
- assert_equal ["can't be blank"], @user.errors[:number]
325
- @user.number = nil
326
- assert_nil @user.number
327
- assert_nil @user.encrypted_number
328
- assert_equal false, @user.valid?
329
- assert_equal ["can't be blank"], @user.errors[:number]
359
+ assert user.valid?
360
+ user.number = '123'
361
+ assert user.valid?
362
+ assert_equal 123, user.number
363
+ assert user.valid?
364
+ user.number = ''
365
+ assert_equal false, user.valid?
366
+ assert_equal '', user.number
367
+ assert_equal ["can't be blank"], user.errors[:number]
368
+ user.number = nil
369
+ assert_nil user.number
370
+ assert_nil user.encrypted_number
371
+ assert_equal false, user.valid?
372
+ assert_equal ["can't be blank"], user.errors[:number]
330
373
  end
331
374
  end
332
375
 
333
376
  describe 'with saved user' do
334
377
  before do
335
- @user.save!
378
+ user.save!
336
379
  end
337
380
 
338
381
  after do
339
- @user.destroy if @user
382
+ user&.destroy
340
383
  end
341
384
 
342
385
  it 'return correct data type before save' do
343
386
  u = User.new(integer_value: '5')
344
387
  assert_equal 5, u.integer_value
345
- assert u.integer_value.kind_of?(Integer)
388
+ assert u.integer_value.is_a?(Integer)
346
389
  end
347
390
 
348
391
  it 'handle gsub! for non-encrypted_field' do
349
- @user.name.gsub!('a', 'v')
350
- new_name = @name.gsub('a', 'v')
351
- assert_equal new_name, @user.name
352
- @user.reload
353
- assert_equal new_name, @user.name
392
+ user.name.tr!('a', 'v')
393
+ new_name = person_name.tr('a', 'v')
394
+ assert_equal new_name, user.name
395
+ user.reload
396
+ assert_equal new_name, user.name
354
397
  end
355
398
 
356
- it "prevent gsub! on non-encrypted value of encrypted_field" do
399
+ it 'prevent gsub! on non-encrypted value of encrypted_field' do
357
400
  # can't modify frozen String
358
401
  assert_raises RuntimeError do
359
- @user.bank_account_number.gsub!('5', '4')
402
+ user.bank_account_number.tr!('5', '4')
360
403
  end
361
404
  end
362
405
 
363
406
  describe '#reload' do
364
407
  it 'reverts changes' do
365
408
  new_bank_account_number = '444444444'
366
- @user.bank_account_number = new_bank_account_number
367
- assert_equal new_bank_account_number, @user.bank_account_number
409
+ user.bank_account_number = new_bank_account_number
410
+ assert_equal new_bank_account_number, user.bank_account_number
368
411
 
369
412
  # Reload User model from the database
370
- @user.reload
371
- assert_equal @bank_account_number_encrypted, @user.encrypted_bank_account_number
372
- assert_equal @bank_account_number, @user.bank_account_number
413
+ user.reload
414
+ assert_equal bank_account_number_encrypted, user.encrypted_bank_account_number
415
+ assert_equal bank_account_number, user.bank_account_number
373
416
  end
374
417
 
375
418
  it 'reverts changes to encrypted field' do
376
419
  new_bank_account_number = '111111111'
377
420
  new_encrypted_bank_account_number = SymmetricEncryption.encrypt(new_bank_account_number)
378
- @user.encrypted_bank_account_number = new_encrypted_bank_account_number
379
- assert_equal new_encrypted_bank_account_number, @user.encrypted_bank_account_number
380
- assert_equal new_bank_account_number, @user.bank_account_number
421
+ user.encrypted_bank_account_number = new_encrypted_bank_account_number
422
+ assert_equal new_encrypted_bank_account_number, user.encrypted_bank_account_number
423
+ assert_equal new_bank_account_number, user.bank_account_number
381
424
 
382
425
  # Reload User model from the database
383
- @user.reload
384
- assert_equal @bank_account_number_encrypted, @user.encrypted_bank_account_number
385
- assert_equal @bank_account_number, @user.bank_account_number
426
+ user.reload
427
+ assert_equal bank_account_number_encrypted, user.encrypted_bank_account_number
428
+ assert_equal bank_account_number, user.bank_account_number
386
429
  end
387
430
  end
388
431
 
389
432
  describe 'data types' do
390
433
  before do
391
- @user_clone = User.find(@user.id)
434
+ @user_clone = User.find(user.id)
392
435
  end
393
436
 
394
437
  [
395
- #@formatter:off
438
+ # @formatter:off
396
439
  {attribute: :integer_value, klass: Integer, value: INTEGER_VALUE, new_value: 98},
397
440
  {attribute: :float_value, klass: Float, value: FLOAT_VALUE, new_value: 45.4321},
398
- {attribute: :decimal_value, klass: BigDecimal, value: DECIMAL_VALUE, new_value: BigDecimal.new('99.95'), coercible: '22.51'},
441
+ {attribute: :decimal_value, klass: BigDecimal, value: DECIMAL_VALUE, new_value: BigDecimal('99.95'), coercible: '22.51'},
399
442
  {attribute: :datetime_value, klass: DateTime, value: DATETIME_VALUE, new_value: DateTime.new(1998, 10, 21, 8, 33, 28, '+5'), coercible: DATETIME_VALUE.to_time},
400
- {attribute: :time_value, klass: Time, value: TIME_VALUE, new_value: Time.new(2000, 01, 01, 22, 30, 00, "-04:00")},
401
- {attribute: :date_value, klass: Date, value: DATE_VALUE, new_value: Date.new(2027, 04, 02), coercible: DATE_VALUE.to_time},
443
+ {attribute: :time_value, klass: Time, value: TIME_VALUE, new_value: Time.new(2000, 1, 1, 22, 30, 0, '-04:00')},
444
+ {attribute: :date_value, klass: Date, value: DATE_VALUE, new_value: Date.new(2027, 4, 2), coercible: DATE_VALUE.to_time},
402
445
  {attribute: :true_value, klass: TrueClass, value: true, new_value: false},
403
446
  {attribute: :false_value, klass: FalseClass, value: false, new_value: true},
404
447
  {attribute: :string_value, klass: String, value: STRING_VALUE, new_value: 'Hello World'},
405
448
  {attribute: :long_string_value, klass: String, value: LONG_STRING_VALUE, new_value: 'A Really long Hello World'},
406
449
  {attribute: :binary_string_value, klass: String, value: BINARY_STRING_VALUE, new_value: "A new Non-UTF8 Binary \x92 string".force_encoding('BINARY')},
407
- #@formatter:on
450
+ # @formatter:on
408
451
  ].each do |value_test|
409
452
  describe "#{value_test[:klass]} values" do
410
453
  before do
@@ -420,39 +463,39 @@ class ActiveRecordTest < Minitest::Test
420
463
  # Need to dup since minitest attempts to modify the decrypted value which is frozen
421
464
  val = val.dup if val.duplicable?
422
465
  assert_equal @value, val, @user_clone.attributes.ai
423
- assert @user.send(@attribute).kind_of?(@klass)
466
+ assert user.send(@attribute).is_a?(@klass)
424
467
  end
425
468
 
426
469
  it 'coerce data type before save' do
427
470
  u = User.new(@attribute => @value)
428
471
  assert_equal @value, u.send(@attribute)
429
- assert u.send(@attribute).kind_of?(@klass), "Value supposed to be coerced into #{@klass}, but is #{u.send(@attribute).class.name}"
472
+ assert u.send(@attribute).is_a?(@klass), "Value supposed to be coerced into #{@klass}, but is #{u.send(@attribute).class.name}"
430
473
  end
431
474
 
432
475
  it 'permit replacing value with nil' do
433
476
  @user_clone.send("#{@attribute}=".to_sym, nil)
434
477
  @user_clone.save!
435
478
 
436
- @user.reload
437
- assert_nil @user.send(@attribute)
438
- assert_nil @user.send("encrypted_#{@attribute}".to_sym)
479
+ user.reload
480
+ assert_nil user.send(@attribute)
481
+ assert_nil user.send("encrypted_#{@attribute}".to_sym)
439
482
  end
440
483
 
441
484
  it 'permit replacing value with an empty string' do
442
485
  @user_clone.send("#{@attribute}=".to_sym, '')
443
486
  @user_clone.save!
444
487
 
445
- @user.reload
446
- assert_equal '', @user.send(@attribute)
447
- assert_equal '', @user.send("encrypted_#{@attribute}".to_sym)
488
+ user.reload
489
+ assert_equal '', user.send(@attribute)
490
+ assert_equal '', user.send("encrypted_#{@attribute}".to_sym)
448
491
  end
449
492
 
450
493
  it 'permit replacing value' do
451
494
  @user_clone.send("#{@attribute}=".to_sym, @new_value)
452
495
  @user_clone.save!
453
496
 
454
- @user.reload
455
- val = @user.send(@attribute)
497
+ user.reload
498
+ val = user.send(@attribute)
456
499
  # Need to dup since minitest attempts to modify the decrypted value which is frozen
457
500
  val = val.dup if val.duplicable?
458
501
  assert_equal @new_value, val
@@ -461,89 +504,84 @@ class ActiveRecordTest < Minitest::Test
461
504
  end
462
505
 
463
506
  describe 'JSON Serialization' do
464
- before do
465
- # JSON Does not support symbols, so they will come back as strings
466
- # Convert symbols to string in the test
467
- @h.keys.each do |k|
468
- @h[k.to_s] = @h[k]
469
- @h.delete(k)
470
- end
507
+ let :hash_data do
508
+ {'a' => 'A', 'b' => 'B'}
471
509
  end
472
510
 
473
511
  it 'return correct data type' do
474
- assert_equal @h, @user_clone.data_json
475
- assert @user.clone.data_json.kind_of?(Hash)
512
+ assert_equal hash_data, @user_clone.data_json
513
+ assert user.clone.data_json.is_a?(Hash)
476
514
  end
477
515
 
478
516
  it 'not coerce data type (leaves as hash) before save' do
479
- u = User.new(data_json: @h)
480
- assert_equal @h, u.data_json
481
- assert u.data_json.kind_of?(Hash)
517
+ u = User.new(data_json: hash_data)
518
+ assert_equal hash_data, u.data_json
519
+ assert u.data_json.is_a?(Hash)
482
520
  end
483
521
 
484
522
  it 'permit replacing value with nil' do
485
523
  @user_clone.data_json = nil
486
524
  @user_clone.save!
487
525
 
488
- @user.reload
489
- assert_nil @user.data_json
490
- assert_nil @user.encrypted_data_json
526
+ user.reload
527
+ assert_nil user.data_json
528
+ assert_nil user.encrypted_data_json
491
529
  end
492
530
 
493
531
  it 'permit replacing value' do
494
- new_value = @h.clone
532
+ new_value = hash_data.clone
495
533
  new_value['c'] = 'C'
496
534
  @user_clone.data_json = new_value
497
535
  @user_clone.save!
498
536
 
499
- @user.reload
500
- assert_equal new_value, @user.data_json
537
+ user.reload
538
+ assert_equal new_value, user.data_json
501
539
  end
502
540
  end
503
541
 
504
542
  describe 'YAML Serialization' do
505
543
  it 'return correct data type' do
506
- assert_equal @h, @user_clone.data_yaml
507
- assert @user.clone.data_yaml.kind_of?(Hash)
544
+ assert_equal hash_data, @user_clone.data_yaml
545
+ assert user.clone.data_yaml.is_a?(Hash)
508
546
  end
509
547
 
510
548
  it 'not coerce data type (leaves as hash) before save' do
511
- u = User.new(data_yaml: @h)
512
- assert_equal @h, u.data_yaml
513
- assert u.data_yaml.kind_of?(Hash)
549
+ u = User.new(data_yaml: hash_data)
550
+ assert_equal hash_data, u.data_yaml
551
+ assert u.data_yaml.is_a?(Hash)
514
552
  end
515
553
 
516
554
  it 'permit replacing value with nil' do
517
555
  @user_clone.data_yaml = nil
518
556
  @user_clone.save!
519
557
 
520
- @user.reload
521
- assert_nil @user.data_yaml
522
- assert_nil @user.encrypted_data_yaml
558
+ user.reload
559
+ assert_nil user.data_yaml
560
+ assert_nil user.encrypted_data_yaml
523
561
  end
524
562
 
525
563
  it 'permit replacing value' do
526
- new_value = @h.clone
564
+ new_value = hash_data.clone
527
565
  new_value[:c] = 'C'
528
566
  @user_clone.data_yaml = new_value
529
567
  @user_clone.save!
530
568
 
531
- @user.reload
532
- assert_equal new_value, @user.data_yaml
569
+ user.reload
570
+ assert_equal new_value, user.data_yaml
533
571
  end
534
572
  end
535
573
  end
536
574
 
537
575
  describe 'changed?' do
538
576
  it 'return false if it was not changed' do
539
- assert_equal false, @user.encrypted_bank_account_number_changed?
540
- assert_equal false, @user.bank_account_number_changed?
577
+ assert_equal false, user.encrypted_bank_account_number_changed?
578
+ assert_equal false, user.bank_account_number_changed?
541
579
  end
542
580
 
543
581
  it 'return true if it was changed' do
544
- @user.bank_account_number = '15424623'
545
- assert @user.encrypted_bank_account_number_changed?
546
- assert @user.bank_account_number_changed?
582
+ user.bank_account_number = '15424623'
583
+ assert user.encrypted_bank_account_number_changed?
584
+ assert user.bank_account_number_changed?
547
585
  end
548
586
  end
549
587
  end
@@ -553,7 +591,7 @@ class ActiveRecordTest < Minitest::Test
553
591
  UniqueUser.destroy_all
554
592
  @email = 'whatever@not-unique.com'
555
593
  @username = 'gibby007'
556
- @user = UniqueUser.create!(email: @email)
594
+ user = UniqueUser.create!(email: @email)
557
595
  @email_user = UniqueUser.create!(username: @username)
558
596
  end
559
597
 
@@ -563,6 +601,5 @@ class ActiveRecordTest < Minitest::Test
563
601
  assert_equal 'has already been taken', duplicate.errors.messages[:encrypted_email].first
564
602
  end
565
603
  end
566
-
567
604
  end
568
605
  end