attr_encrypted 1.3.3 → 1.3.4
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.
- data/README.rdoc +43 -1
- data/Rakefile +1 -0
- data/lib/attr_encrypted.rb +10 -2
- data/lib/attr_encrypted/adapters/active_record.rb +32 -14
- data/lib/attr_encrypted/version.rb +1 -1
- data/test/active_record_test.rb +66 -17
- data/test/attr_encrypted_test.rb +19 -19
- data/test/compatibility_test.rb +1 -1
- data/test/data_mapper_test.rb +5 -5
- data/test/legacy_active_record_test.rb +5 -5
- data/test/legacy_attr_encrypted_test.rb +15 -15
- data/test/legacy_compatibility_test.rb +1 -1
- data/test/legacy_data_mapper_test.rb +5 -5
- data/test/legacy_sequel_test.rb +5 -5
- data/test/sequel_test.rb +5 -5
- data/test/test_helper.rb +5 -1
- metadata +27 -3
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= attr_encrypted {<img src="https://travis-ci.org/attr-encrypted/attr_encrypted.png" />}[https://travis-ci.org/attr-encrypted/attr_encrypted]
|
1
|
+
= attr_encrypted {<img src="https://travis-ci.org/attr-encrypted/attr_encrypted.png" />}[https://travis-ci.org/attr-encrypted/attr_encrypted] {<img src="https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/gpa.svg" />}[https://codeclimate.com/github/attr-encrypted/attr_encrypted]{<img src="https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/gpa.svg" />}[https://codeclimate.com/github/attr-encrypted/attr_encrypted]
|
2
2
|
|
3
3
|
Generates attr_accessors that encrypt and decrypt attributes transparently
|
4
4
|
|
@@ -39,6 +39,48 @@ Encrypting attributes has never been easier:
|
|
39
39
|
|
40
40
|
The <tt>attr_encrypted</tt> method is also aliased as <tt>attr_encryptor</tt> to conform to Ruby's <tt>attr_</tt> naming conventions. I should have called this project <tt>attr_encryptor</tt> but it was too late when I realized it ='(.
|
41
41
|
|
42
|
+
=== Adding required columns via database migration
|
43
|
+
|
44
|
+
By default, <tt>attr_encrypted</tt> uses the <tt>:single_iv_and_salt</tt>
|
45
|
+
encryption mode for compatibility with previous versions of the gem. This mode
|
46
|
+
uses a single IV and salt for each encrypted column. Create or modify your model
|
47
|
+
to add a column with the <tt>encrypted_</tt> prefix (which can be modified, see
|
48
|
+
below), e.g. <tt>encrypted_ssn</tt> via a migration like the following:
|
49
|
+
|
50
|
+
create_table :users do |t|
|
51
|
+
t.string :name
|
52
|
+
t.string :encrypted_ssn
|
53
|
+
t.timestamps
|
54
|
+
end
|
55
|
+
|
56
|
+
For enhanced security, you can use the <tt>:per_attribute_iv_and_salt</tt> mode.
|
57
|
+
This requires additional <tt>_salt</tt> and <tt>_iv</tt> columns with the
|
58
|
+
<tt>encrypted_</tt> prefix as follows and generates a unique salt and IV per
|
59
|
+
attribute:
|
60
|
+
|
61
|
+
create_table :users do |t|
|
62
|
+
t.string :name
|
63
|
+
t.string :encrypted_ssn
|
64
|
+
t.string :encrypted_ssn_salt
|
65
|
+
t.string :encrypted_ssn_iv
|
66
|
+
t.string :domain
|
67
|
+
t.timestamps
|
68
|
+
end
|
69
|
+
|
70
|
+
This mode is enabled by specifying a value of <tt>:per_attribute_iv_and_salt</tt>
|
71
|
+
via the <tt>:mode</tt> option as follows:
|
72
|
+
|
73
|
+
class User
|
74
|
+
attr_accessor :name
|
75
|
+
attr_encrypted :ssn, :key => 'a secret key', :mode => :per_attribute_iv_and_salt
|
76
|
+
end
|
77
|
+
|
78
|
+
Note that there are alternatives to storing the IV and salt in separate columns:
|
79
|
+
for example, see here[https://github.com/attr-encrypted/attr_encrypted/issues/118#issuecomment-45806629].
|
80
|
+
Note that migration from the old encryption scheme to the new is nontrivial. One
|
81
|
+
approach is described here[http://jjasonclark.com/switching_from_attr_encrypted_to_attr_encryptor],
|
82
|
+
though these instructions describe the now-defunct <tt>attr_encryptor</tt> gem
|
83
|
+
whose functionality has been merged into this project.
|
42
84
|
|
43
85
|
=== Specifying the encrypted attribute name
|
44
86
|
|
data/Rakefile
CHANGED
data/lib/attr_encrypted.rb
CHANGED
@@ -127,7 +127,7 @@ module AttrEncrypted
|
|
127
127
|
iv_name = "#{encrypted_attribute_name}_iv".to_sym
|
128
128
|
salt_name = "#{encrypted_attribute_name}_salt".to_sym
|
129
129
|
|
130
|
-
instance_methods_as_symbols =
|
130
|
+
instance_methods_as_symbols = attribute_instance_methods_as_symbols
|
131
131
|
attr_reader encrypted_attribute_name unless instance_methods_as_symbols.include?(encrypted_attribute_name)
|
132
132
|
attr_writer encrypted_attribute_name unless instance_methods_as_symbols.include?(:"#{encrypted_attribute_name}=")
|
133
133
|
|
@@ -156,6 +156,7 @@ module AttrEncrypted
|
|
156
156
|
encrypted_attributes[attribute.to_sym] = options.merge(:attribute => encrypted_attribute_name)
|
157
157
|
end
|
158
158
|
end
|
159
|
+
|
159
160
|
alias_method :attr_encryptor, :attr_encrypted
|
160
161
|
|
161
162
|
# Default options to use with calls to <tt>attr_encrypted</tt>
|
@@ -302,7 +303,7 @@ module AttrEncrypted
|
|
302
303
|
|
303
304
|
# Returns attr_encrypted options evaluated in the current object's scope for the attribute specified
|
304
305
|
def evaluated_attr_encrypted_options_for(attribute)
|
305
|
-
if self.class.encrypted_attributes[attribute.to_sym][:mode] == :per_attribute_iv_and_salt
|
306
|
+
if evaluate_attr_encrypted_option(self.class.encrypted_attributes[attribute.to_sym][:mode]) == :per_attribute_iv_and_salt
|
306
307
|
load_iv_for_attribute(attribute, self.class.encrypted_attributes[attribute.to_sym][:algorithm])
|
307
308
|
load_salt_for_attribute(attribute)
|
308
309
|
end
|
@@ -344,6 +345,13 @@ module AttrEncrypted
|
|
344
345
|
self.class.encrypted_attributes[attribute.to_sym] = self.class.encrypted_attributes[attribute.to_sym].merge(:salt => salt)
|
345
346
|
end
|
346
347
|
end
|
348
|
+
|
349
|
+
protected
|
350
|
+
|
351
|
+
def attribute_instance_methods_as_symbols
|
352
|
+
instance_methods.collect { |method| method.to_sym }
|
353
|
+
end
|
354
|
+
|
347
355
|
end
|
348
356
|
|
349
357
|
Object.extend AttrEncrypted
|
@@ -4,6 +4,17 @@ if defined?(ActiveRecord::Base)
|
|
4
4
|
module ActiveRecord
|
5
5
|
def self.extended(base) # :nodoc:
|
6
6
|
base.class_eval do
|
7
|
+
|
8
|
+
# https://github.com/attr-encrypted/attr_encrypted/issues/68
|
9
|
+
def reload_with_attr_encrypted(*args, &block)
|
10
|
+
result = reload_without_attr_encrypted(*args, &block)
|
11
|
+
self.class.encrypted_attributes.keys.each do |attribute_name|
|
12
|
+
instance_variable_set("@#{attribute_name}", nil)
|
13
|
+
end
|
14
|
+
result
|
15
|
+
end
|
16
|
+
alias_method_chain :reload, :attr_encrypted
|
17
|
+
|
7
18
|
attr_encrypted_options[:encode] = true
|
8
19
|
class << self
|
9
20
|
alias_method :attr_encryptor, :attr_encrypted
|
@@ -13,10 +24,9 @@ if defined?(ActiveRecord::Base)
|
|
13
24
|
|
14
25
|
def perform_attribute_assignment(method, new_attributes, *args)
|
15
26
|
return if new_attributes.blank?
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
self.send method, attributes.slice(*encrypted_attributes), *args
|
27
|
+
|
28
|
+
send method, new_attributes.reject { |k, _| self.class.encrypted_attributes.key?(k.to_sym) }, *args
|
29
|
+
send method, new_attributes.reject { |k, _| !self.class.encrypted_attributes.key?(k.to_sym) }, *args
|
20
30
|
end
|
21
31
|
private :perform_attribute_assignment
|
22
32
|
|
@@ -25,27 +35,35 @@ if defined?(ActiveRecord::Base)
|
|
25
35
|
perform_attribute_assignment :assign_attributes_without_attr_encrypted, *args
|
26
36
|
end
|
27
37
|
alias_method_chain :assign_attributes, :attr_encrypted
|
28
|
-
else
|
29
|
-
def attributes_with_attr_encrypted=(*args)
|
30
|
-
perform_attribute_assignment :attributes_without_attr_encrypted=, *args
|
31
|
-
end
|
32
|
-
alias_method_chain :attributes=, :attr_encrypted
|
33
38
|
end
|
39
|
+
|
40
|
+
def attributes_with_attr_encrypted=(*args)
|
41
|
+
perform_attribute_assignment :attributes_without_attr_encrypted=, *args
|
42
|
+
end
|
43
|
+
alias_method_chain :attributes=, :attr_encrypted
|
34
44
|
end
|
35
45
|
end
|
36
46
|
|
37
47
|
protected
|
38
48
|
|
39
|
-
# Ensures the attribute methods for db fields have been defined before calling the original
|
40
49
|
# <tt>attr_encrypted</tt> method
|
41
50
|
def attr_encrypted(*attrs)
|
42
|
-
define_attribute_methods rescue nil
|
43
51
|
super
|
44
|
-
undefine_attribute_methods
|
45
52
|
attrs.reject { |attr| attr.is_a?(Hash) }.each { |attr| alias_method "#{attr}_before_type_cast", attr }
|
46
53
|
end
|
47
54
|
|
48
|
-
|
55
|
+
def attribute_instance_methods_as_symbols
|
56
|
+
# We add accessor methods of the db columns to the list of instance
|
57
|
+
# methods returned to let ActiveRecord define the accessor methods
|
58
|
+
# for the db columns
|
59
|
+
if table_exists?
|
60
|
+
columns_hash.keys.inject(super) {|instance_methods, column_name| instance_methods.concat [column_name.to_sym, :"#{column_name}="]}
|
61
|
+
else
|
62
|
+
super
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Allows you to use dynamic methods like <tt>find_by_email</tt> or <tt>scoped_by_email</tt> for
|
49
67
|
# encrypted attributes
|
50
68
|
#
|
51
69
|
# NOTE: This only works when the <tt>:key</tt> option is specified as a string (see the README)
|
@@ -80,4 +98,4 @@ if defined?(ActiveRecord::Base)
|
|
80
98
|
end
|
81
99
|
|
82
100
|
ActiveRecord::Base.extend AttrEncrypted::Adapters::ActiveRecord
|
83
|
-
end
|
101
|
+
end
|
data/test/active_record_test.rb
CHANGED
@@ -25,6 +25,9 @@ def create_tables
|
|
25
25
|
t.string :encrypted_password
|
26
26
|
t.boolean :is_admin
|
27
27
|
end
|
28
|
+
create_table :prime_ministers do |t|
|
29
|
+
t.string :encrypted_name
|
30
|
+
end
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
@@ -70,6 +73,11 @@ class PersonWithValidation < Person
|
|
70
73
|
validates_presence_of :email
|
71
74
|
end
|
72
75
|
|
76
|
+
class PersonWithProcMode < Person
|
77
|
+
attr_encrypted :email, :key => SECRET_KEY, :mode => Proc.new { :per_attribute_iv_and_salt }
|
78
|
+
attr_encrypted :credentials, :key => SECRET_KEY, :mode => Proc.new { :single_iv_and_salt }
|
79
|
+
end
|
80
|
+
|
73
81
|
class Account < ActiveRecord::Base
|
74
82
|
attr_accessor :key
|
75
83
|
attr_encrypted :password, :key => Proc.new {|account| account.key}
|
@@ -92,7 +100,11 @@ class PersonUsingAlias < ActiveRecord::Base
|
|
92
100
|
attr_encryptor :email, :key => 'a secret key'
|
93
101
|
end
|
94
102
|
|
95
|
-
class
|
103
|
+
class PrimeMinister < ActiveRecord::Base
|
104
|
+
attr_encrypted :name, :marshal => true, :key => 'SECRET_KEY'
|
105
|
+
end
|
106
|
+
|
107
|
+
class ActiveRecordTest < Minitest::Test
|
96
108
|
|
97
109
|
def setup
|
98
110
|
ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
|
@@ -102,15 +114,15 @@ class ActiveRecordTest < Test::Unit::TestCase
|
|
102
114
|
|
103
115
|
def test_should_encrypt_email
|
104
116
|
@person = Person.create :email => 'test@example.com'
|
105
|
-
|
106
|
-
|
117
|
+
refute_nil @person.encrypted_email
|
118
|
+
refute_equal @person.email, @person.encrypted_email
|
107
119
|
assert_equal @person.email, Person.find(:first).email
|
108
120
|
end
|
109
121
|
|
110
122
|
def test_should_marshal_and_encrypt_credentials
|
111
123
|
@person = Person.create
|
112
|
-
|
113
|
-
|
124
|
+
refute_nil @person.encrypted_credentials
|
125
|
+
refute_equal @person.credentials, @person.encrypted_credentials
|
114
126
|
assert_equal @person.credentials, Person.find(:first).credentials
|
115
127
|
end
|
116
128
|
|
@@ -127,7 +139,7 @@ class ActiveRecordTest < Test::Unit::TestCase
|
|
127
139
|
def test_should_encrypt_decrypt_with_iv
|
128
140
|
@person = Person.create :email => 'test@example.com'
|
129
141
|
@person2 = Person.find(@person.id)
|
130
|
-
|
142
|
+
refute_nil @person2.encrypted_email_iv
|
131
143
|
assert_equal 'test@example.com', @person2.email
|
132
144
|
end
|
133
145
|
|
@@ -142,6 +154,16 @@ class ActiveRecordTest < Test::Unit::TestCase
|
|
142
154
|
Account.create!(:password => "password" , :key => SECRET_KEY)
|
143
155
|
end
|
144
156
|
|
157
|
+
def test_should_set_attributes_regardless_of_arguments_order
|
158
|
+
Account.new.attributes = { :password => "password" , :key => SECRET_KEY }
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_should_preserve_hash_key_type
|
162
|
+
hash = { :foo => 'bar' }
|
163
|
+
account = Account.create!(:key => hash)
|
164
|
+
assert_equal account.key, hash
|
165
|
+
end
|
166
|
+
|
145
167
|
if ::ActiveRecord::VERSION::STRING > "4.0"
|
146
168
|
def test_should_assign_attributes
|
147
169
|
@user = UserWithProtectedAttribute.new :login => 'login', :is_admin => false
|
@@ -157,13 +179,13 @@ class ActiveRecordTest < Test::Unit::TestCase
|
|
157
179
|
|
158
180
|
def test_should_raise_exception_if_not_permitted
|
159
181
|
@user = UserWithProtectedAttribute.new :login => 'login', :is_admin => false
|
160
|
-
|
182
|
+
assert_raises ActiveModel::ForbiddenAttributesError do
|
161
183
|
@user.attributes = ActionController::Parameters.new(:login => 'modified', :is_admin => true)
|
162
184
|
end
|
163
185
|
end
|
164
186
|
|
165
187
|
def test_should_raise_exception_on_init_if_not_permitted
|
166
|
-
|
188
|
+
assert_raises ActiveModel::ForbiddenAttributesError do
|
167
189
|
@user = UserWithProtectedAttribute.new ActionController::Parameters.new(:login => 'modified', :is_admin => true)
|
168
190
|
end
|
169
191
|
end
|
@@ -196,6 +218,22 @@ class ActiveRecordTest < Test::Unit::TestCase
|
|
196
218
|
assert_nil(@person.attributes = nil)
|
197
219
|
end
|
198
220
|
|
221
|
+
def test_should_allow_proc_based_mode
|
222
|
+
@person = PersonWithProcMode.create :email => 'test@example.com', :credentials => 'password123'
|
223
|
+
|
224
|
+
# Email is :per_attribute_iv_and_salt
|
225
|
+
assert_equal @person.class.encrypted_attributes[:email][:mode].class, Proc
|
226
|
+
assert_equal @person.class.encrypted_attributes[:email][:mode].call, :per_attribute_iv_and_salt
|
227
|
+
refute_nil @person.encrypted_email_salt
|
228
|
+
refute_nil @person.encrypted_email_iv
|
229
|
+
|
230
|
+
# Credentials is :single_iv_and_salt
|
231
|
+
assert_equal @person.class.encrypted_attributes[:credentials][:mode].class, Proc
|
232
|
+
assert_equal @person.class.encrypted_attributes[:credentials][:mode].call, :single_iv_and_salt
|
233
|
+
assert_nil @person.encrypted_credentials_salt
|
234
|
+
assert_nil @person.encrypted_credentials_iv
|
235
|
+
end
|
236
|
+
|
199
237
|
if ::ActiveRecord::VERSION::STRING > "3.1"
|
200
238
|
def test_should_allow_assign_attributes_with_nil
|
201
239
|
@person = Person.new
|
@@ -203,15 +241,26 @@ class ActiveRecordTest < Test::Unit::TestCase
|
|
203
241
|
end
|
204
242
|
end
|
205
243
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
user.save
|
244
|
+
def test_that_alias_encrypts_column
|
245
|
+
user = PersonUsingAlias.new
|
246
|
+
user.email = 'test@example.com'
|
247
|
+
user.save
|
211
248
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
249
|
+
refute_nil user.encrypted_email
|
250
|
+
refute_equal user.email, user.encrypted_email
|
251
|
+
assert_equal user.email, PersonUsingAlias.find(:first).email
|
252
|
+
end
|
253
|
+
|
254
|
+
# See https://github.com/attr-encrypted/attr_encrypted/issues/68
|
255
|
+
def test_should_invalidate_virtual_attributes_on_reload
|
256
|
+
pm = PrimeMinister.new(:name => 'Winston Churchill')
|
257
|
+
pm.save!
|
258
|
+
assert_equal 'Winston Churchill', pm.name
|
259
|
+
pm.name = 'Neville Chamberlain'
|
260
|
+
assert_equal 'Neville Chamberlain', pm.name
|
261
|
+
|
262
|
+
result = pm.reload
|
263
|
+
assert_equal pm, result
|
264
|
+
assert_equal 'Winston Churchill', pm.name
|
216
265
|
end
|
217
266
|
end
|
data/test/attr_encrypted_test.rb
CHANGED
@@ -53,7 +53,7 @@ class SomeOtherClass
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
class AttrEncryptedTest < Test
|
56
|
+
class AttrEncryptedTest < Minitest::Test
|
57
57
|
|
58
58
|
def test_should_store_email_in_encrypted_attributes
|
59
59
|
assert User.encrypted_attributes.include?(:email)
|
@@ -68,7 +68,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def test_attr_encrypted_should_not_use_the_same_attribute_name_for_two_attributes_in_the_same_line
|
71
|
-
|
71
|
+
refute_equal User.encrypted_attributes[:email][:attribute], User.encrypted_attributes[:without_encoding][:attribute]
|
72
72
|
end
|
73
73
|
|
74
74
|
def test_attr_encrypted_should_return_false_for_salt
|
@@ -96,15 +96,15 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
96
96
|
end
|
97
97
|
|
98
98
|
def test_should_encrypt_email
|
99
|
-
|
100
|
-
|
99
|
+
refute_nil User.encrypt_email('test@example.com')
|
100
|
+
refute_equal 'test@example.com', User.encrypt_email('test@example.com')
|
101
101
|
end
|
102
102
|
|
103
103
|
def test_should_encrypt_email_when_modifying_the_attr_writer
|
104
104
|
@user = User.new
|
105
105
|
assert_nil @user.encrypted_email
|
106
106
|
@user.email = 'test@example.com'
|
107
|
-
|
107
|
+
refute_nil @user.encrypted_email
|
108
108
|
assert_equal User.encrypt_email('test@example.com'), @user.encrypted_email
|
109
109
|
end
|
110
110
|
|
@@ -118,7 +118,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
118
118
|
|
119
119
|
def test_should_decrypt_email
|
120
120
|
encrypted_email = User.encrypt_email('test@example.com')
|
121
|
-
|
121
|
+
refute_equal 'test@test.com', encrypted_email
|
122
122
|
assert_equal 'test@example.com', User.decrypt_email(encrypted_email)
|
123
123
|
end
|
124
124
|
|
@@ -152,7 +152,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
152
152
|
def test_should_encrypt_with_marshaling
|
153
153
|
@user = User.new
|
154
154
|
@user.with_marshaling = [1, 2, 3]
|
155
|
-
|
155
|
+
refute_nil @user.encrypted_with_marshaling
|
156
156
|
end
|
157
157
|
|
158
158
|
def test_should_use_custom_encryptor_and_crypt_method_names_and_arguments
|
@@ -163,7 +163,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
163
163
|
@user = User.new
|
164
164
|
assert_nil @user.ssn_encrypted
|
165
165
|
@user.ssn = 'testing'
|
166
|
-
|
166
|
+
refute_nil @user.ssn_encrypted
|
167
167
|
encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.ssn_encrypted_iv.unpack("m").first, :salt => @user.ssn_encrypted_salt )
|
168
168
|
assert_equal encrypted, @user.ssn_encrypted
|
169
169
|
end
|
@@ -172,7 +172,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
172
172
|
@user = User.new
|
173
173
|
assert_nil @user.crypted_password_test
|
174
174
|
@user.password = 'testing'
|
175
|
-
|
175
|
+
refute_nil @user.crypted_password_test
|
176
176
|
encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt)
|
177
177
|
assert_equal encrypted, @user.crypted_password_test
|
178
178
|
end
|
@@ -181,7 +181,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
181
181
|
@user = User.new
|
182
182
|
assert_nil @user.crypted_password_test
|
183
183
|
@user.password = 'testing'
|
184
|
-
|
184
|
+
refute_nil @user.crypted_password_test
|
185
185
|
encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt)
|
186
186
|
assert_equal encrypted, @user.crypted_password_test
|
187
187
|
end
|
@@ -224,7 +224,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
224
224
|
@user = User.new
|
225
225
|
assert_nil @user.encrypted_with_true_if
|
226
226
|
@user.with_true_if = 'testing'
|
227
|
-
|
227
|
+
refute_nil @user.encrypted_with_true_if
|
228
228
|
encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_true_if_iv.unpack("m").first, :salt => @user.encrypted_with_true_if_salt)
|
229
229
|
assert_equal encrypted, @user.encrypted_with_true_if
|
230
230
|
end
|
@@ -233,7 +233,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
233
233
|
@user = User.new
|
234
234
|
assert_nil @user.encrypted_with_false_if
|
235
235
|
@user.with_false_if = 'testing'
|
236
|
-
|
236
|
+
refute_nil @user.encrypted_with_false_if
|
237
237
|
assert_equal 'testing', @user.encrypted_with_false_if
|
238
238
|
end
|
239
239
|
|
@@ -241,7 +241,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
241
241
|
@user = User.new
|
242
242
|
assert_nil @user.encrypted_with_false_unless
|
243
243
|
@user.with_false_unless = 'testing'
|
244
|
-
|
244
|
+
refute_nil @user.encrypted_with_false_unless
|
245
245
|
encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_false_unless_iv.unpack("m").first, :salt => @user.encrypted_with_false_unless_salt)
|
246
246
|
assert_equal encrypted, @user.encrypted_with_false_unless
|
247
247
|
end
|
@@ -250,7 +250,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
250
250
|
@user = User.new
|
251
251
|
assert_nil @user.encrypted_with_true_unless
|
252
252
|
@user.with_true_unless = 'testing'
|
253
|
-
|
253
|
+
refute_nil @user.encrypted_with_true_unless
|
254
254
|
assert_equal 'testing', @user.encrypted_with_true_unless
|
255
255
|
end
|
256
256
|
|
@@ -263,7 +263,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
263
263
|
@user.with_if_changed = "encrypt_stuff"
|
264
264
|
@user.stubs(:instance_variable_get).returns(nil)
|
265
265
|
@user.stubs(:instance_variable_set).raises("BadStuff")
|
266
|
-
|
266
|
+
assert_raises RuntimeError do
|
267
267
|
@user.with_if_changed
|
268
268
|
end
|
269
269
|
|
@@ -293,7 +293,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
293
293
|
@user = User.new
|
294
294
|
@user.email = 'email@example.com'
|
295
295
|
@user.password = 'p455w0rd'
|
296
|
-
|
296
|
+
refute_equal @user.encrypted_email_iv, @user.crypted_password_test_iv
|
297
297
|
end
|
298
298
|
|
299
299
|
def test_should_vary_iv_per_instance
|
@@ -301,14 +301,14 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
301
301
|
@user1.email = 'email@example.com'
|
302
302
|
@user2 = User.new
|
303
303
|
@user2.email = 'email@example.com'
|
304
|
-
|
304
|
+
refute_equal @user1.encrypted_email_iv, @user2.encrypted_email_iv
|
305
305
|
end
|
306
306
|
|
307
307
|
def test_should_vary_salt_per_attribute
|
308
308
|
@user = User.new
|
309
309
|
@user.email = 'email@example.com'
|
310
310
|
@user.password = 'p455w0rd'
|
311
|
-
|
311
|
+
refute_equal @user.encrypted_email_salt, @user.crypted_password_test_salt
|
312
312
|
end
|
313
313
|
|
314
314
|
def test_should_vary_salt_per_instance
|
@@ -316,7 +316,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
|
|
316
316
|
@user1.email = 'email@example.com'
|
317
317
|
@user2 = User.new
|
318
318
|
@user2.email = 'email@example.com'
|
319
|
-
|
319
|
+
refute_equal @user1.encrypted_email_salt, @user2.encrypted_email_salt
|
320
320
|
end
|
321
321
|
|
322
322
|
def test_should_decrypt_second_record
|
data/test/compatibility_test.rb
CHANGED
@@ -5,7 +5,7 @@ require File.expand_path('../test_helper', __FILE__)
|
|
5
5
|
# migrating to new versions of this gem. This ensures that future versions of
|
6
6
|
# this gem will retain backwards compatibility with data generated by earlier
|
7
7
|
# versions.
|
8
|
-
class CompatibilityTest < Test
|
8
|
+
class CompatibilityTest < Minitest::Test
|
9
9
|
class NonmarshallingPet < ActiveRecord::Base
|
10
10
|
PET_NICKNAME_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-nickname-salt')
|
11
11
|
PET_NICKNAME_KEY = 'my-really-really-secret-pet-nickname-key'
|
data/test/data_mapper_test.rb
CHANGED
@@ -27,7 +27,7 @@ end
|
|
27
27
|
|
28
28
|
DataMapper.auto_migrate!
|
29
29
|
|
30
|
-
class DataMapperTest < Test
|
30
|
+
class DataMapperTest < Minitest::Test
|
31
31
|
|
32
32
|
def setup
|
33
33
|
Client.all.each(&:destroy)
|
@@ -36,16 +36,16 @@ class DataMapperTest < Test::Unit::TestCase
|
|
36
36
|
def test_should_encrypt_email
|
37
37
|
@client = Client.new :email => 'test@example.com'
|
38
38
|
assert @client.save
|
39
|
-
|
40
|
-
|
39
|
+
refute_nil @client.encrypted_email
|
40
|
+
refute_equal @client.email, @client.encrypted_email
|
41
41
|
assert_equal @client.email, Client.first.email
|
42
42
|
end
|
43
43
|
|
44
44
|
def test_should_marshal_and_encrypt_credentials
|
45
45
|
@client = Client.new
|
46
46
|
assert @client.save
|
47
|
-
|
48
|
-
|
47
|
+
refute_nil @client.encrypted_credentials
|
48
|
+
refute_equal @client.credentials, @client.encrypted_credentials
|
49
49
|
assert_equal @client.credentials, Client.first.credentials
|
50
50
|
assert Client.first.credentials.is_a?(Hash)
|
51
51
|
end
|
@@ -45,7 +45,7 @@ class LegacyPersonWithValidation < LegacyPerson
|
|
45
45
|
validates_uniqueness_of :encrypted_email
|
46
46
|
end
|
47
47
|
|
48
|
-
class LegacyActiveRecordTest < Test
|
48
|
+
class LegacyActiveRecordTest < Minitest::Test
|
49
49
|
|
50
50
|
def setup
|
51
51
|
ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
|
@@ -61,15 +61,15 @@ class LegacyActiveRecordTest < Test::Unit::TestCase
|
|
61
61
|
|
62
62
|
def test_should_encrypt_email
|
63
63
|
@person = LegacyPerson.create :email => 'test@example.com'
|
64
|
-
|
65
|
-
|
64
|
+
refute_nil @person.encrypted_email
|
65
|
+
refute_equal @person.email, @person.encrypted_email
|
66
66
|
assert_equal @person.email, LegacyPerson.find(:first).email
|
67
67
|
end
|
68
68
|
|
69
69
|
def test_should_marshal_and_encrypt_credentials
|
70
70
|
@person = LegacyPerson.create
|
71
|
-
|
72
|
-
|
71
|
+
refute_nil @person.encrypted_credentials
|
72
|
+
refute_equal @person.credentials, @person.encrypted_credentials
|
73
73
|
assert_equal @person.credentials, LegacyPerson.find(:first).credentials
|
74
74
|
end
|
75
75
|
|
@@ -48,7 +48,7 @@ class LegacySomeOtherClass
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
class LegacyAttrEncryptedTest < Test
|
51
|
+
class LegacyAttrEncryptedTest < Minitest::Test
|
52
52
|
|
53
53
|
def test_should_store_email_in_encrypted_attributes
|
54
54
|
assert LegacyUser.encrypted_attributes.include?(:email)
|
@@ -63,7 +63,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def test_attr_encrypted_should_not_use_the_same_attribute_name_for_two_attributes_in_the_same_line
|
66
|
-
|
66
|
+
refute_equal LegacyUser.encrypted_attributes[:email][:attribute], LegacyUser.encrypted_attributes[:without_encoding][:attribute]
|
67
67
|
end
|
68
68
|
|
69
69
|
def test_attr_encrypted_should_return_false_for_salt
|
@@ -91,15 +91,15 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def test_should_encrypt_email
|
94
|
-
|
95
|
-
|
94
|
+
refute_nil LegacyUser.encrypt_email('test@example.com')
|
95
|
+
refute_equal 'test@example.com', LegacyUser.encrypt_email('test@example.com')
|
96
96
|
end
|
97
97
|
|
98
98
|
def test_should_encrypt_email_when_modifying_the_attr_writer
|
99
99
|
@user = LegacyUser.new
|
100
100
|
assert_nil @user.encrypted_email
|
101
101
|
@user.email = 'test@example.com'
|
102
|
-
|
102
|
+
refute_nil @user.encrypted_email
|
103
103
|
assert_equal LegacyUser.encrypt_email('test@example.com'), @user.encrypted_email
|
104
104
|
end
|
105
105
|
|
@@ -113,7 +113,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
113
113
|
|
114
114
|
def test_should_decrypt_email
|
115
115
|
encrypted_email = LegacyUser.encrypt_email('test@example.com')
|
116
|
-
|
116
|
+
refute_equal 'test@test.com', encrypted_email
|
117
117
|
assert_equal 'test@example.com', LegacyUser.decrypt_email(encrypted_email)
|
118
118
|
end
|
119
119
|
|
@@ -153,7 +153,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
153
153
|
def test_should_encrypt_with_marshaling
|
154
154
|
@user = LegacyUser.new
|
155
155
|
@user.with_marshaling = [1, 2, 3]
|
156
|
-
|
156
|
+
refute_nil @user.encrypted_with_marshaling
|
157
157
|
assert_equal LegacyUser.encrypt_with_marshaling([1, 2, 3]), @user.encrypted_with_marshaling
|
158
158
|
end
|
159
159
|
|
@@ -173,7 +173,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
173
173
|
@user = LegacyUser.new
|
174
174
|
assert_nil @user.ssn_encrypted
|
175
175
|
@user.ssn = 'testing'
|
176
|
-
|
176
|
+
refute_nil @user.ssn_encrypted
|
177
177
|
assert_equal Encryptor.encrypt(:value => 'testing', :key => @user.salt), @user.ssn_encrypted
|
178
178
|
end
|
179
179
|
|
@@ -181,7 +181,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
181
181
|
@user = LegacyUser.new
|
182
182
|
assert_nil @user.crypted_password_test
|
183
183
|
@user.password = 'testing'
|
184
|
-
|
184
|
+
refute_nil @user.crypted_password_test
|
185
185
|
assert_equal Encryptor.encrypt(:value => 'testing', :key => 'LegacyUser'), @user.crypted_password_test
|
186
186
|
end
|
187
187
|
|
@@ -189,7 +189,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
189
189
|
@user = LegacyUser.new
|
190
190
|
assert_nil @user.crypted_password_test
|
191
191
|
@user.password = 'testing'
|
192
|
-
|
192
|
+
refute_nil @user.crypted_password_test
|
193
193
|
assert_equal Encryptor.encrypt(:value => 'testing', :key => 'LegacyUser'), @user.crypted_password_test
|
194
194
|
end
|
195
195
|
|
@@ -231,7 +231,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
231
231
|
@user = LegacyUser.new
|
232
232
|
assert_nil @user.encrypted_with_true_if
|
233
233
|
@user.with_true_if = 'testing'
|
234
|
-
|
234
|
+
refute_nil @user.encrypted_with_true_if
|
235
235
|
assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key'), @user.encrypted_with_true_if
|
236
236
|
end
|
237
237
|
|
@@ -239,7 +239,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
239
239
|
@user = LegacyUser.new
|
240
240
|
assert_nil @user.encrypted_with_false_if
|
241
241
|
@user.with_false_if = 'testing'
|
242
|
-
|
242
|
+
refute_nil @user.encrypted_with_false_if
|
243
243
|
assert_equal 'testing', @user.encrypted_with_false_if
|
244
244
|
end
|
245
245
|
|
@@ -247,7 +247,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
247
247
|
@user = LegacyUser.new
|
248
248
|
assert_nil @user.encrypted_with_false_unless
|
249
249
|
@user.with_false_unless = 'testing'
|
250
|
-
|
250
|
+
refute_nil @user.encrypted_with_false_unless
|
251
251
|
assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key'), @user.encrypted_with_false_unless
|
252
252
|
end
|
253
253
|
|
@@ -255,7 +255,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
255
255
|
@user = LegacyUser.new
|
256
256
|
assert_nil @user.encrypted_with_true_unless
|
257
257
|
@user.with_true_unless = 'testing'
|
258
|
-
|
258
|
+
refute_nil @user.encrypted_with_true_unless
|
259
259
|
assert_equal 'testing', @user.encrypted_with_true_unless
|
260
260
|
end
|
261
261
|
|
@@ -268,7 +268,7 @@ class LegacyAttrEncryptedTest < Test::Unit::TestCase
|
|
268
268
|
@user.with_if_changed = "encrypt_stuff"
|
269
269
|
@user.stubs(:instance_variable_get).returns(nil)
|
270
270
|
@user.stubs(:instance_variable_set).raises("BadStuff")
|
271
|
-
|
271
|
+
assert_raises RuntimeError do
|
272
272
|
@user.with_if_changed
|
273
273
|
end
|
274
274
|
|
@@ -5,7 +5,7 @@ require File.expand_path('../test_helper', __FILE__)
|
|
5
5
|
# migrating to new versions of this gem. This ensures that future versions of
|
6
6
|
# this gem will retain backwards compatibility with data generated by earlier
|
7
7
|
# versions.
|
8
|
-
class LegacyCompatibilityTest < Test
|
8
|
+
class LegacyCompatibilityTest < Minitest::Test
|
9
9
|
class LegacyNonmarshallingPet < ActiveRecord::Base
|
10
10
|
PET_NICKNAME_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-nickname-salt')
|
11
11
|
PET_NICKNAME_KEY = 'my-really-really-secret-pet-nickname-key'
|
@@ -22,7 +22,7 @@ end
|
|
22
22
|
|
23
23
|
DataMapper.auto_migrate!
|
24
24
|
|
25
|
-
class LegacyDataMapperTest < Test
|
25
|
+
class LegacyDataMapperTest < Minitest::Test
|
26
26
|
|
27
27
|
def setup
|
28
28
|
LegacyClient.all.each(&:destroy)
|
@@ -31,16 +31,16 @@ class LegacyDataMapperTest < Test::Unit::TestCase
|
|
31
31
|
def test_should_encrypt_email
|
32
32
|
@client = LegacyClient.new :email => 'test@example.com'
|
33
33
|
assert @client.save
|
34
|
-
|
35
|
-
|
34
|
+
refute_nil @client.encrypted_email
|
35
|
+
refute_equal @client.email, @client.encrypted_email
|
36
36
|
assert_equal @client.email, LegacyClient.first.email
|
37
37
|
end
|
38
38
|
|
39
39
|
def test_should_marshal_and_encrypt_credentials
|
40
40
|
@client = LegacyClient.new
|
41
41
|
assert @client.save
|
42
|
-
|
43
|
-
|
42
|
+
refute_nil @client.encrypted_credentials
|
43
|
+
refute_equal @client.credentials, @client.encrypted_credentials
|
44
44
|
assert_equal @client.credentials, LegacyClient.first.credentials
|
45
45
|
assert LegacyClient.first.credentials.is_a?(Hash)
|
46
46
|
end
|
data/test/legacy_sequel_test.rb
CHANGED
@@ -18,7 +18,7 @@ class LegacyHuman < Sequel::Model(:legacy_humans)
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
class LegacySequelTest < Test
|
21
|
+
class LegacySequelTest < Minitest::Test
|
22
22
|
|
23
23
|
def setup
|
24
24
|
LegacyHuman.all.each(&:destroy)
|
@@ -27,16 +27,16 @@ class LegacySequelTest < Test::Unit::TestCase
|
|
27
27
|
def test_should_encrypt_email
|
28
28
|
@human = LegacyHuman.new :email => 'test@example.com'
|
29
29
|
assert @human.save
|
30
|
-
|
31
|
-
|
30
|
+
refute_nil @human.encrypted_email
|
31
|
+
refute_equal @human.email, @human.encrypted_email
|
32
32
|
assert_equal @human.email, LegacyHuman.first.email
|
33
33
|
end
|
34
34
|
|
35
35
|
def test_should_marshal_and_encrypt_credentials
|
36
36
|
@human = LegacyHuman.new
|
37
37
|
assert @human.save
|
38
|
-
|
39
|
-
|
38
|
+
refute_nil @human.encrypted_credentials
|
39
|
+
refute_equal @human.credentials, @human.encrypted_credentials
|
40
40
|
assert_equal @human.credentials, LegacyHuman.first.credentials
|
41
41
|
assert LegacyHuman.first.credentials.is_a?(Hash)
|
42
42
|
end
|
data/test/sequel_test.rb
CHANGED
@@ -22,7 +22,7 @@ class Human < Sequel::Model(:humans)
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
class SequelTest < Test
|
25
|
+
class SequelTest < Minitest::Test
|
26
26
|
|
27
27
|
def setup
|
28
28
|
Human.all.each(&:destroy)
|
@@ -31,8 +31,8 @@ class SequelTest < Test::Unit::TestCase
|
|
31
31
|
def test_should_encrypt_email
|
32
32
|
@human = Human.new :email => 'test@example.com'
|
33
33
|
assert @human.save
|
34
|
-
|
35
|
-
|
34
|
+
refute_nil @human.encrypted_email
|
35
|
+
refute_equal @human.email, @human.encrypted_email
|
36
36
|
assert_equal @human.email, Human.first.email
|
37
37
|
end
|
38
38
|
|
@@ -40,8 +40,8 @@ class SequelTest < Test::Unit::TestCase
|
|
40
40
|
|
41
41
|
@human = Human.new :credentials => { :username => 'example', :password => 'test' }
|
42
42
|
assert @human.save
|
43
|
-
|
44
|
-
|
43
|
+
refute_nil @human.encrypted_credentials
|
44
|
+
refute_equal @human.credentials, @human.encrypted_credentials
|
45
45
|
assert_equal @human.credentials, Human.first.credentials
|
46
46
|
assert Human.first.credentials.is_a?(Hash)
|
47
47
|
end
|
data/test/test_helper.rb
CHANGED
@@ -12,7 +12,11 @@ if RUBY_VERSION >= '1.9.3'
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
require '
|
15
|
+
require 'minitest'
|
16
|
+
require "codeclimate-test-reporter"
|
17
|
+
CodeClimate::TestReporter.start
|
18
|
+
|
19
|
+
require 'minitest/autorun'
|
16
20
|
require 'digest/sha2'
|
17
21
|
require 'rubygems'
|
18
22
|
gem 'activerecord', ENV['ACTIVE_RECORD_VERSION'] if ENV['ACTIVE_RECORD_VERSION']
|
metadata
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attr_encrypted
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Sean Huber
|
9
9
|
- S. Brent Faulkner
|
10
10
|
- William Monk
|
11
|
+
- Stephen Aghaulor
|
11
12
|
autorequire:
|
12
13
|
bindir: bin
|
13
14
|
cert_chain: []
|
14
|
-
date:
|
15
|
+
date: 2015-05-11 00:00:00.000000000 Z
|
15
16
|
dependencies:
|
16
17
|
- !ruby/object:Gem::Dependency
|
17
18
|
name: encryptor
|
@@ -45,6 +46,22 @@ dependencies:
|
|
45
46
|
- - ! '>='
|
46
47
|
- !ruby/object:Gem::Version
|
47
48
|
version: 2.0.0
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: minitest
|
51
|
+
requirement: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
48
65
|
- !ruby/object:Gem::Dependency
|
49
66
|
name: datamapper
|
50
67
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,6 +195,7 @@ email:
|
|
178
195
|
- shuber@huberry.com
|
179
196
|
- sbfaulkner@gmail.com
|
180
197
|
- billy.monk@gmail.com
|
198
|
+
- saghaulor@gmail.com
|
181
199
|
executables: []
|
182
200
|
extensions: []
|
183
201
|
extra_rdoc_files: []
|
@@ -218,15 +236,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
218
236
|
- - ! '>='
|
219
237
|
- !ruby/object:Gem::Version
|
220
238
|
version: '0'
|
239
|
+
segments:
|
240
|
+
- 0
|
241
|
+
hash: -1997953751590493696
|
221
242
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
222
243
|
none: false
|
223
244
|
requirements:
|
224
245
|
- - ! '>='
|
225
246
|
- !ruby/object:Gem::Version
|
226
247
|
version: '0'
|
248
|
+
segments:
|
249
|
+
- 0
|
250
|
+
hash: -1997953751590493696
|
227
251
|
requirements: []
|
228
252
|
rubyforge_project:
|
229
|
-
rubygems_version: 1.8.23
|
253
|
+
rubygems_version: 1.8.23.2
|
230
254
|
signing_key:
|
231
255
|
specification_version: 3
|
232
256
|
summary: Encrypt and decrypt attributes
|