attr_encrypted 1.3.3 → 1.3.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|