attr_encrypted 3.0.0 → 3.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: 7818979e143dc8810acdc45dfe6ae67273be455d
4
- data.tar.gz: 734c97e4b7d4109b40f4f6bdf7c34aace6e3be3b
3
+ metadata.gz: f602391484e3437daae62ddb60596f0b4cbc83e0
4
+ data.tar.gz: 5e407d7e299a43380057a2f0fe816da3a6ad1fca
5
5
  SHA512:
6
- metadata.gz: 6d8458d63ccd20fbeb9ae4d79689e0a90d3007bd0a212c428c9b95b44d20f39c5e038215bac1e5c7af1138f2517faf7a96973167b213be289a6b5fc7c1b75918
7
- data.tar.gz: 57201322d4c3dcbf30bf5c74f931b47bf6478626e925620497fc842d87c393aeb507d277c92f524ff233d515acafad1d367ecb3427250ace7d125a9e3ecb1ab8
6
+ metadata.gz: 77b697d9e450d6baae65fb3ed339824b8bf730898296f172c2ae6b4e0bd7368add0da29c76596b9bbf71d298fccd038195f7ffb7d153ffaeaf2aabc7bfc60f9f
7
+ data.tar.gz: 211f1c52e7f0505d55eef59f06bb139f47fb1ae0158b39a643b5c7c5251865f13b871ab7b3194d44cd2fc6a128e86a5c6b9c8669bab6d2870a7914ed5dacb6c3
checksums.yaml.gz.sig CHANGED
Binary file
data/.travis.yml CHANGED
@@ -4,8 +4,10 @@ cache: bundler
4
4
  rvm:
5
5
  - 2.0
6
6
  - 2.1
7
- - 2.2
7
+ - 2.2.2
8
8
  - 2.3.0
9
+ - 2.4.0
10
+ - 2.5.0
9
11
  - rbx
10
12
  env:
11
13
  - ACTIVERECORD=3.0.0
@@ -14,8 +16,42 @@ env:
14
16
  - ACTIVERECORD=4.0.0
15
17
  - ACTIVERECORD=4.1.0
16
18
  - ACTIVERECORD=4.2.0
19
+ - ACTIVERECORD=5.0.0
20
+ - ACTIVERECORD=5.1.1
17
21
  matrix:
18
22
  exclude:
23
+ - rvm: 2.0
24
+ env: ACTIVERECORD=5.0.0
25
+ - rvm: 2.0
26
+ env: ACTIVERECORD=5.1.1
27
+ - rvm: 2.1
28
+ env: ACTIVERECORD=5.0.0
29
+ - rvm: 2.1
30
+ env: ACTIVERECORD=5.1.1
31
+ - rvm: 2.4.0
32
+ env: ACTIVERECORD=3.0.0
33
+ - rvm: 2.4.0
34
+ env: ACTIVERECORD=3.1.0
35
+ - rvm: 2.4.0
36
+ env: ACTIVERECORD=3.2.0
37
+ - rvm: 2.4.0
38
+ env: ACTIVERECORD=4.0.0
39
+ - rvm: 2.4.0
40
+ env: ACTIVERECORD=4.1.0
41
+ - rvm: 2.5.0
42
+ env: ACTIVERECORD=3.0.0
43
+ - rvm: 2.5.0
44
+ env: ACTIVERECORD=3.1.0
45
+ - rvm: 2.5.0
46
+ env: ACTIVERECORD=3.2.0
47
+ - rvm: 2.5.0
48
+ env: ACTIVERECORD=4.0.0
49
+ - rvm: 2.5.0
50
+ env: ACTIVERECORD=4.1.0
51
+ - rvm: rbx
52
+ env: ACTIVERECORD=5.0.0
53
+ - rvm: rbx
54
+ env: ACTIVERECORD=5.1.1
19
55
  allow_failures:
20
56
  - rvm: rbx
21
57
  fast_finish: true
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # attr_encrypted #
2
2
 
3
+ ## 3.1.0 ##
4
+ * Added: Abitilty to encrypt empty values. (@tamird)
5
+ * Added: MIT license
6
+ * Added: MRI 2.5.x support (@saghaulor)
7
+ * Fixed: No long generate IV and salt if value is empty, unless :allow_empty_value options is passed. (@saghaulor)
8
+ * Fixed: Only generate IV and salt when :if and :unless options evaluate such that encryption should be performed. (@saghaulor)
9
+ * Fixed: Private methods are correctly evaluated as options. (@saghaulor)
10
+ * Fixed: Mark virtual attributes for Rails 5.x compatibility (@grosser)
11
+ * Fixed: Only check empty on strings, allows for encrypting non-string type objects
12
+ * Fixed: Fixed how accessors for db columns are defined in the ActiveRecord adapter, preventing premature definition. (@nagachika)
13
+
14
+ ## 3.0.3 ##
15
+ * Fixed: attr_was would decrypt the attribute upon every call. This is inefficient and introduces problems when the options change between decrypting an old value and encrypting a new value; for example, when rotating the encryption key. As such, the new approach caches the decrypted value of the old encrypted value such that the old options are no longer needed. (@johnny-lai) (@saghaulor)
16
+
17
+ ## 3.0.2 ##
18
+ * Changed: Removed alias_method_chain for compatibility with Rails v5.x (@grosser)
19
+ * Changed: Updated Travis build matrix to include Rails 5. (@saghaulor) (@connorshea)
20
+ * Changed: Removed `.silence_stream` from tests as it has been removed from Rails 5. (@sblackstone)
21
+
22
+ ## 3.0.1 ##
23
+ * Fixed: attr_was method no longer calls undefined methods. (@saghaulor)
24
+
3
25
  ## 3.0.0 ##
4
26
  * Changed: Updated gemspec to use Encryptor v3.0.0. (@saghaulor)
5
27
  * Changed: Updated README with instructions related to moving from v2.0.0 to v3.0.0. (@saghaulor)
data/README.md CHANGED
@@ -72,7 +72,7 @@ The `attr_encrypted` class method is also aliased as `attr_encryptor` to conform
72
72
 
73
73
  ### attr_encrypted with database persistence
74
74
 
75
- By default, `attr_encrypted` uses the `:per_attribute_iv` encryption mode. This mode requires a column to store your cipher text and a column to store your IV.
75
+ By default, `attr_encrypted` uses the `:per_attribute_iv` encryption mode. This mode requires a column to store your cipher text and a column to store your IV (initialization vector).
76
76
 
77
77
  Create or modify the table that your model uses to add a column with the `encrypted_` prefix (which can be modified, see below), e.g. `encrypted_ssn` via a migration like the following:
78
78
 
@@ -145,6 +145,7 @@ The following are the default options used by `attr_encrypted`:
145
145
  decrypt_method: 'decrypt',
146
146
  mode: :per_attribute_iv,
147
147
  algorithm: 'aes-256-gcm',
148
+ allow_empty_value: false
148
149
  ```
149
150
 
150
151
  All of the aforementioned options are explained in depth below.
@@ -195,7 +196,7 @@ If you don't like the `encrypted_#{attribute}` naming convention then you can sp
195
196
  end
196
197
  ```
197
198
 
198
- This would generate the following attributes: `secret_email_crypted`, `secret_credit_card_crypted`, and `secret_ssn_crypted`.
199
+ This would generate the following attribute: `secret_email_crypted`.
199
200
 
200
201
 
201
202
  ### The `:key` option
@@ -296,7 +297,7 @@ You're probably going to be storing your encrypted attributes somehow (e.g. file
296
297
  end
297
298
  ```
298
299
 
299
- The default encoding is `m` (base64). You can change this by setting `encode: 'some encoding'`. See [`Arrary#pack`](http://ruby-doc.org/core-2.3.0/Array.html#method-i-pack) for more encoding options.
300
+ The default encoding is `m` (base64). You can change this by setting `encode: 'some encoding'`. See [`Array#pack`](http://ruby-doc.org/core-2.3.0/Array.html#method-i-pack) for more encoding options.
300
301
 
301
302
 
302
303
  ### The `:marshal`, `:dump_method`, and `:load_method` options
@@ -311,6 +312,16 @@ You may want to encrypt objects other than strings (e.g. hashes, arrays, etc). I
311
312
 
312
313
  You may also optionally specify `:marshaler`, `:dump_method`, and `:load_method` if you want to use something other than the default `Marshal` object.
313
314
 
315
+ ### The `:allow_empty_value` option
316
+
317
+ You may want to encrypt empty strings or nil so as to not reveal which records are populated and which records are not.
318
+
319
+ ```ruby
320
+ class User
321
+ attr_encrypted :credentials, key: 'some secret key', marshal: true, allow_empty_value: true
322
+ end
323
+ ```
324
+
314
325
 
315
326
  ## ORMs
316
327
 
@@ -400,10 +411,10 @@ It is recommended that you implement a strategy to insure that you do not mix th
400
411
 
401
412
  ```ruby
402
413
  class User
403
- attr_encrypted :ssn, key: :encryption_key, v2_gcm_iv: :is_decrypting?(:ssn)
414
+ attr_encrypted :ssn, key: :encryption_key, v2_gcm_iv: is_decrypting?(:ssn)
404
415
 
405
416
  def is_decrypting?(attribute)
406
- encrypted_atributes[attribute][operation] == :decrypting
417
+ encrypted_attributes[attribute][:operation] == :decrypting
407
418
  end
408
419
  end
409
420
 
data/Rakefile CHANGED
@@ -6,6 +6,7 @@ desc 'Test the attr_encrypted gem.'
6
6
  Rake::TestTask.new(:test) do |t|
7
7
  t.libs << 'lib'
8
8
  t.pattern = 'test/**/*_test.rb'
9
+ t.warning = false
9
10
  t.verbose = true
10
11
  end
11
12
 
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.authors = ['Sean Huber', 'S. Brent Faulkner', 'William Monk', 'Stephen Aghaulor']
18
18
  s.email = ['seah@shuber.io', 'sbfaulkner@gmail.com', 'billy.monk@gmail.com', 'saghaulor@gmail.com']
19
19
  s.homepage = 'http://github.com/attr-encrypted/attr_encrypted'
20
+ s.license = 'MIT'
20
21
 
21
22
  s.has_rdoc = false
22
23
  s.rdoc_options = ['--line-numbers', '--inline-source', '--main', 'README.rdoc']
@@ -41,6 +42,10 @@ Gem::Specification.new do |s|
41
42
  s.add_development_dependency('rake')
42
43
  s.add_development_dependency('minitest')
43
44
  s.add_development_dependency('sequel')
45
+ if RUBY_VERSION < '2.1.0'
46
+ s.add_development_dependency('nokogiri', '< 1.7.0')
47
+ s.add_development_dependency('public_suffix', '< 3.0.0')
48
+ end
44
49
  if defined?(RUBY_ENGINE) && RUBY_ENGINE.to_sym == :jruby
45
50
  s.add_development_dependency('activerecord-jdbcsqlite3-adapter')
46
51
  s.add_development_dependency('jdbc-sqlite3', '< 3.8.7') # 3.8.7 is nice and broke
@@ -50,7 +55,7 @@ Gem::Specification.new do |s|
50
55
  s.add_development_dependency('dm-sqlite-adapter')
51
56
  s.add_development_dependency('simplecov')
52
57
  s.add_development_dependency('simplecov-rcov')
53
- s.add_development_dependency("codeclimate-test-reporter")
58
+ s.add_development_dependency("codeclimate-test-reporter", '<= 0.6.0')
54
59
 
55
60
  s.cert_chain = ['certs/saghaulor.pem']
56
61
  s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
data/certs/saghaulor.pem CHANGED
@@ -1,21 +1,21 @@
1
1
  -----BEGIN CERTIFICATE-----
2
2
  MIIDdDCCAlygAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMRIwEAYDVQQDDAlzYWdo
3
3
  YXVsb3IxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
4
- bTAeFw0xNjAxMTEyMjQyMDFaFw0xNzAxMTAyMjQyMDFaMEAxEjAQBgNVBAMMCXNh
4
+ bTAeFw0xODAyMTIwMzMzMThaFw0xOTAyMTIwMzMzMThaMEAxEjAQBgNVBAMMCXNh
5
5
  Z2hhdWxvcjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYD
6
- Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx0xdQYk2GwCpQ1n/
7
- n2mPVYHLYqU5TAn/82t5kbqBUWjbcj8tHAi41tJ19+fT/hH0dog8JHvho1zmOr71
8
- ZIqreJQo60TqP6oE9a5HncUpjqbRp7tOmHo9E+mOW1yT4NiXqFf1YINExQKy2XND
9
- WPQ+T50ZNUsGMfHFWB4NAymejRWXlOEY3bvKW0UHFeNmouP5he51TjoP8uCc9536
10
- 4AIWVP/zzzjwrFtC7av7nRw4Y+gX2bQjrkK2k2JS0ejiGzKBIEMJejcI2B+t79zT
11
- kUQq9SFwp2BrKSIy+4kh4CiF20RT/Hfc1MbvTxSIl/bbIxCYEOhmtHExHi0CoCWs
12
- YCGCXQIDAQABo3kwdzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU
13
- SCpVzSBvYbO6B3oT3n3RCZmurG8wHgYDVR0RBBcwFYETc2FnaGF1bG9yQGdtYWls
6
+ Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvOLqbSmj5txfw39a
7
+ Ki0g3BJWGrfGBiSRq9aThUGzoiaqyDo/m1WMQdgPioZG+P923okChEWFjhSymBQU
8
+ eMdys6JRPm5ortp5sh9gesOWoozqb8R55d8rr1V7pY533cCut53Kb1wiitjkfXjR
9
+ efT2HPh6nV6rYjGMJek/URaCNzsZo7HCkRsKdezP+BKr4V4wOka69tfJX5pcvFvR
10
+ iiqfaiP4RK12hYdsFnSVKiKP7SAFTFiYcohbL8TUW6ezQQqJCK0M6fu74EWVCnBS
11
+ gFVjj931BuD8qhuxMiB6uC6FKxemB5TRGBLzn7RcrOMAo2inMAopjkGeQJUAyVCm
12
+ J5US3wIDAQABo3kwdzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU
13
+ hJEuSZgvuuIhIsxQ/0pRQTBVzokwHgYDVR0RBBcwFYETc2FnaGF1bG9yQGdtYWls
14
14
  LmNvbTAeBgNVHRIEFzAVgRNzYWdoYXVsb3JAZ21haWwuY29tMA0GCSqGSIb3DQEB
15
- BQUAA4IBAQAeiGdC3e0WiZpm0cF/b7JC6hJYXC9Yv9VsRAWD9ROsLjFKwOhmonnc
16
- +l/QrmoTjMakYXBCai/Ca3L+k5eRrKilgyITILsmmFxK8sqPJXUw2Jmwk/dAky6x
17
- hHKVZAofT1OrOOPJ2USoZyhR/VI8epLaD5wUmkVDNqtZWviW+dtRa55aPYjRw5Pj
18
- wuj9nybhZr+BbEbmZE//2nbfkM4hCuMtxxxilPrJ22aYNmeWU0wsPpDyhPYxOUgU
19
- ZjeLmnSDiwL6doiP5IiwALH/dcHU67ck3NGf6XyqNwQrrmtPY0mv1WVVL4Uh+vYE
20
- kHoFzE2no0BfBg78Re8fY69P5yES5ncC
15
+ BQUAA4IBAQCsBS2cxqTmV4nXJEH/QbdgjVDAZbK6xf2gpM3vCRlYsy7Wz6GEoOpD
16
+ bzRkjxZwGNbhXShMUZwm6zahYQ/L1/HFztLoMBMkm8EIfPxH0PDrP4aWl0oyWxmU
17
+ OLm0/t9icSWRPPJ1tLJvuAaDdVpY5dEHd6VdnNJGQC5vHKRInt1kEyqEttIJ/xmJ
18
+ leSEFyMeoFsR+C/WPG9WSC+xN0eXqakCu6YUJoQzCn/7znv8WxpHEbeZjNIHq0qb
19
+ nbqZ/ZW1bwzj1T/NIbnMr37wqV29XwkI4+LbewMkb6/bDPYl0qZpAkCxKtGYCCJp
20
+ l6KPs9K/72yH00dxuAhiTXikTkcLXeQJ
21
21
  -----END CERTIFICATE-----
@@ -0,0 +1 @@
1
+ 845fc3cb09a19c3ac76192aba443788f92c880744617bca99b16fd31ce843e07
@@ -0,0 +1 @@
1
+ 81a065442258cc3702aab62c7b2307a48ed3e0deb803600d11a7480cce0db7c43fd9929acd2755081042f8989236553fd694b6cb62776bbfc53f9165a22cbca1
@@ -0,0 +1 @@
1
+ 33140af4b223177db7a19efb2fa38472a299a745b29ca1c5ba9d3fa947390b77
@@ -0,0 +1 @@
1
+ 0c467cab98b9b2eb331f9818323a90ae01392d6cb03cf1f32faccc954d0fc54be65f0fc7bf751b0fce57925eef1c9e2af90181bc40d81ad93e21d15a001c53c6
@@ -0,0 +1 @@
1
+ c1256b459336d4a2012a0d0c70ce5cd3dac46acb5e78da6f77f6f104cb1e8b7b
@@ -0,0 +1 @@
1
+ dca0c8a729974c0e26fde4cd4216c7d0f66d9eca9f6cf0ccca64999f5180a00bf7c05b630c1d420ec1673141a2923946e8bd28b12e711faf64a4cd42c7a3ac9e
@@ -0,0 +1 @@
1
+ 6d84c64852c4bbc0926b92fe7a93295671a9e69cb2939b96fb1e4b5e8a5b33b6
@@ -0,0 +1 @@
1
+ 0f960e8a2f63c747c273241f7395dcceb0dd8a6f79349bee453db741fc7ea5ceb4342d7d5908e540e3b5acea2216ff38bef8c743e6e7c8559bacb4a731ab27c4
@@ -6,19 +6,20 @@ if defined?(ActiveRecord::Base)
6
6
  base.class_eval do
7
7
 
8
8
  # https://github.com/attr-encrypted/attr_encrypted/issues/68
9
- def reload_with_attr_encrypted(*args, &block)
9
+ alias_method :reload_without_attr_encrypted, :reload
10
+ def reload(*args, &block)
10
11
  result = reload_without_attr_encrypted(*args, &block)
11
12
  self.class.encrypted_attributes.keys.each do |attribute_name|
12
13
  instance_variable_set("@#{attribute_name}", nil)
13
14
  end
14
15
  result
15
16
  end
16
- alias_method_chain :reload, :attr_encrypted
17
17
 
18
18
  attr_encrypted_options[:encode] = true
19
19
 
20
20
  class << self
21
- alias_method_chain :method_missing, :attr_encrypted
21
+ alias_method :method_missing_without_attr_encrypted, :method_missing
22
+ alias_method :method_missing, :method_missing_with_attr_encrypted
22
23
  end
23
24
 
24
25
  def perform_attribute_assignment(method, new_attributes, *args)
@@ -30,16 +31,16 @@ if defined?(ActiveRecord::Base)
30
31
  private :perform_attribute_assignment
31
32
 
32
33
  if ::ActiveRecord::VERSION::STRING > "3.1"
33
- def assign_attributes_with_attr_encrypted(*args)
34
+ alias_method :assign_attributes_without_attr_encrypted, :assign_attributes
35
+ def assign_attributes(*args)
34
36
  perform_attribute_assignment :assign_attributes_without_attr_encrypted, *args
35
37
  end
36
- alias_method_chain :assign_attributes, :attr_encrypted
37
38
  end
38
39
 
39
- def attributes_with_attr_encrypted=(*args)
40
+ alias_method :attributes_without_attr_encrypted=, :attributes=
41
+ def attributes=(*args)
40
42
  perform_attribute_assignment :attributes_without_attr_encrypted=, *args
41
43
  end
42
- alias_method_chain :attributes=, :attr_encrypted
43
44
  end
44
45
  end
45
46
 
@@ -50,22 +51,35 @@ if defined?(ActiveRecord::Base)
50
51
  super
51
52
  options = attrs.extract_options!
52
53
  attr = attrs.pop
54
+ attribute attr if ::ActiveRecord::VERSION::STRING >= "5.1.0"
53
55
  options.merge! encrypted_attributes[attr]
54
56
 
55
- define_method("#{attr}_changed?") do
56
- if send("#{options[:attribute]}_changed?")
57
- send(attr) != send("#{attr}_was")
57
+ define_method("#{attr}_was") do
58
+ attribute_was(attr)
59
+ end
60
+
61
+ if ::ActiveRecord::VERSION::STRING >= "4.1"
62
+ define_method("#{attr}_changed?") do |options = {}|
63
+ attribute_changed?(attr, options)
64
+ end
65
+ else
66
+ define_method("#{attr}_changed?") do
67
+ attribute_changed?(attr)
58
68
  end
59
69
  end
60
70
 
61
- define_method("#{attr}_was") do
62
- iv_and_salt = { iv: send("#{options[:attribute]}_iv_was"), salt: send("#{options[:attribute]}_salt_was"), operation: :decrypting }
63
- encrypted_attributes[attr].merge!(iv_and_salt)
64
- evaluated_options = evaluated_attr_encrypted_options_for(attr)
65
- [:iv, :salt, :operation].each { |key| encrypted_attributes[attr].delete(key) }
66
- self.class.decrypt(attr, send("#{options[:attribute]}_was"), evaluated_options)
71
+ define_method("#{attr}_change") do
72
+ attribute_change(attr)
67
73
  end
68
74
 
75
+ define_method("#{attr}_with_dirtiness=") do |value|
76
+ attribute_will_change!(attr) if value != __send__(attr)
77
+ __send__("#{attr}_without_dirtiness=", value)
78
+ end
79
+
80
+ alias_method "#{attr}_without_dirtiness=", "#{attr}="
81
+ alias_method "#{attr}=", "#{attr}_with_dirtiness="
82
+
69
83
  alias_method "#{attr}_before_type_cast", attr
70
84
  end
71
85
 
@@ -74,16 +88,17 @@ if defined?(ActiveRecord::Base)
74
88
  # methods returned to let ActiveRecord define the accessor methods
75
89
  # for the db columns
76
90
 
77
- # Use with_connection so the connection doesn't stay pinned to the thread.
78
- connected = ::ActiveRecord::Base.connection_pool.with_connection(&:active?) rescue false
79
-
80
- if connected && table_exists?
91
+ if connected? && table_exists?
81
92
  columns_hash.keys.inject(super) {|instance_methods, column_name| instance_methods.concat [column_name.to_sym, :"#{column_name}="]}
82
93
  else
83
94
  super
84
95
  end
85
96
  end
86
97
 
98
+ def attribute_instance_methods_as_symbols_available?
99
+ connected? && table_exists?
100
+ end
101
+
87
102
  # Allows you to use dynamic methods like <tt>find_by_email</tt> or <tt>scoped_by_email</tt> for
88
103
  # encrypted attributes
89
104
  #
@@ -2,7 +2,7 @@ module AttrEncrypted
2
2
  # Contains information about this gem's version
3
3
  module Version
4
4
  MAJOR = 3
5
- MINOR = 0
5
+ MINOR = 1
6
6
  PATCH = 0
7
7
 
8
8
  # Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>