attr_encrypted 1.1.2 → 1.2.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.
@@ -2,13 +2,15 @@ if defined?(ActiveRecord)
2
2
  module AttrEncrypted
3
3
  module Adapters
4
4
  module ActiveRecord
5
- def self.extended(base)
6
- base.attr_encrypted_options[:encode] = true
7
- base.eigenclass_eval { alias_method_chain :method_missing, :attr_encrypted }
5
+ def self.extended(base) # :nodoc:
6
+ base.class_eval do
7
+ attr_encrypted_options[:encode] = true
8
+ class << self; alias_method_chain :method_missing, :attr_encrypted; end
9
+ end
8
10
  end
9
-
11
+
10
12
  protected
11
-
13
+
12
14
  # Ensures the attribute methods for db fields have been defined before calling the original
13
15
  # <tt>attr_encrypted</tt> method
14
16
  def attr_encrypted(*attrs)
@@ -16,7 +18,7 @@ if defined?(ActiveRecord)
16
18
  super
17
19
  attrs.reject { |attr| attr.is_a?(Hash) }.each { |attr| alias_method "#{attr}_before_type_cast", attr }
18
20
  end
19
-
21
+
20
22
  # Allows you to use dynamic methods like <tt>find_by_email</tt> or <tt>scoped_by_email</tt> for
21
23
  # encrypted attributes
22
24
  #
@@ -40,7 +42,7 @@ if defined?(ActiveRecord)
40
42
  attribute_names.each_with_index do |attribute, index|
41
43
  if attr_encrypted?(attribute)
42
44
  args[index] = send("encrypt_#{attribute}", args[index])
43
- attribute_names[index] = encrypted_attributes[attribute]
45
+ attribute_names[index] = encrypted_attributes[attribute.to_sym][:attribute]
44
46
  end
45
47
  end
46
48
  method = "#{match.captures[0]}_#{match.captures[1]}_#{attribute_names.join('_and_')}".to_sym
@@ -50,6 +52,6 @@ if defined?(ActiveRecord)
50
52
  end
51
53
  end
52
54
  end
53
-
55
+
54
56
  ActiveRecord::Base.extend AttrEncrypted::Adapters::ActiveRecord
55
57
  end
@@ -2,13 +2,13 @@ if defined?(DataMapper)
2
2
  module AttrEncrypted
3
3
  module Adapters
4
4
  module DataMapper
5
- def self.extended(base)
6
- base.eigenclass_eval do
5
+ def self.extended(base) # :nodoc:
6
+ class << base
7
7
  alias_method :included_without_attr_encrypted, :included
8
8
  alias_method :included, :included_with_attr_encrypted
9
9
  end
10
10
  end
11
-
11
+
12
12
  def included_with_attr_encrypted(base)
13
13
  included_without_attr_encrypted(base)
14
14
  base.attr_encrypted_options[:encode] = true
@@ -16,6 +16,6 @@ if defined?(DataMapper)
16
16
  end
17
17
  end
18
18
  end
19
-
19
+
20
20
  DataMapper::Resource.extend AttrEncrypted::Adapters::DataMapper
21
21
  end
@@ -2,12 +2,12 @@ if defined?(Sequel)
2
2
  module AttrEncrypted
3
3
  module Adapters
4
4
  module Sequel
5
- def self.extended(base)
5
+ def self.extended(base) # :nodoc:
6
6
  base.attr_encrypted_options[:encode] = true
7
7
  end
8
8
  end
9
9
  end
10
10
  end
11
-
11
+
12
12
  Sequel::Model.extend AttrEncrypted::Adapters::Sequel
13
13
  end
@@ -0,0 +1,17 @@
1
+ module AttrEncrypted
2
+ # Contains information about this gem's version
3
+ module Version
4
+ MAJOR = 1
5
+ MINOR = 2
6
+ PATCH = 0
7
+
8
+ # Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>
9
+ #
10
+ # Example
11
+ #
12
+ # Version.string # '1.0.2'
13
+ def self.string
14
+ [MAJOR, MINOR, PATCH].join('.')
15
+ end
16
+ end
17
+ end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require File.expand_path('../test_helper', __FILE__)
2
2
 
3
3
  ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
4
4
 
@@ -18,15 +18,25 @@ end
18
18
  # The table needs to exist before defining the class
19
19
  create_people_table
20
20
 
21
+ ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError)
22
+
21
23
  class Person < ActiveRecord::Base
22
24
  attr_encrypted :email, :key => 'a secret key'
23
25
  attr_encrypted :credentials, :key => Proc.new { |user| Encryptor.encrypt(:value => user.salt, :key => 'some private key') }, :marshal => true
24
-
25
- def after_initialize
26
- self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(5)).to_s)
27
- self.credentials ||= { :username => 'example', :password => 'test' }
28
- rescue ActiveRecord::MissingAttributeError
29
- end
26
+
27
+ ActiveSupport::Deprecation.silenced = true
28
+ def after_initialize; end
29
+ ActiveSupport::Deprecation.silenced = false
30
+
31
+ after_initialize :initialize_salt_and_credentials
32
+
33
+ protected
34
+
35
+ def initialize_salt_and_credentials
36
+ self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(5)).to_s)
37
+ self.credentials ||= { :username => 'example', :password => 'test' }
38
+ rescue ActiveRecord::MissingAttributeError
39
+ end
30
40
  end
31
41
 
32
42
  class PersonWithValidation < Person
@@ -35,64 +45,64 @@ class PersonWithValidation < Person
35
45
  end
36
46
 
37
47
  class ActiveRecordTest < Test::Unit::TestCase
38
-
48
+
39
49
  def setup
40
50
  ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
41
51
  create_people_table
42
52
  end
43
-
53
+
44
54
  def test_should_encrypt_email
45
55
  @person = Person.create :email => 'test@example.com'
46
56
  assert_not_nil @person.encrypted_email
47
57
  assert_not_equal @person.email, @person.encrypted_email
48
58
  assert_equal @person.email, Person.find(:first).email
49
59
  end
50
-
60
+
51
61
  def test_should_marshal_and_encrypt_credentials
52
62
  @person = Person.create
53
63
  assert_not_nil @person.encrypted_credentials
54
64
  assert_not_equal @person.credentials, @person.encrypted_credentials
55
65
  assert_equal @person.credentials, Person.find(:first).credentials
56
66
  end
57
-
67
+
58
68
  def test_should_find_by_email
59
69
  @person = Person.create(:email => 'test@example.com')
60
70
  assert_equal @person, Person.find_by_email('test@example.com')
61
71
  end
62
-
72
+
63
73
  def test_should_find_by_email_and_password
64
74
  Person.create(:email => 'test@example.com', :password => 'invalid')
65
75
  @person = Person.create(:email => 'test@example.com', :password => 'test')
66
76
  assert_equal @person, Person.find_by_email_and_password('test@example.com', 'test')
67
77
  end
68
-
78
+
69
79
  def test_should_scope_by_email
70
80
  @person = Person.create(:email => 'test@example.com')
71
81
  assert_equal @person, Person.scoped_by_email('test@example.com').find(:first) rescue NoMethodError
72
82
  end
73
-
83
+
74
84
  def test_should_scope_by_email_and_password
75
85
  Person.create(:email => 'test@example.com', :password => 'invalid')
76
86
  @person = Person.create(:email => 'test@example.com', :password => 'test')
77
87
  assert_equal @person, Person.scoped_by_email_and_password('test@example.com', 'test').find(:first) rescue NoMethodError
78
88
  end
79
-
89
+
80
90
  def test_should_encode_by_default
81
91
  assert Person.attr_encrypted_options[:encode]
82
92
  end
83
-
93
+
84
94
  def test_should_validate_presence_of_email
85
95
  @person = PersonWithValidation.new
86
96
  assert !@person.valid?
87
- assert @person.errors.on(:email)
97
+ assert !@person.errors[:email].empty? || @person.errors.on(:email)
88
98
  end
89
-
99
+
90
100
  def test_should_validate_uniqueness_of_email
91
101
  @person = PersonWithValidation.new :email => 'test@example.com'
92
102
  assert @person.save
93
103
  @person2 = PersonWithValidation.new :email => @person.email
94
104
  assert !@person2.valid?
95
- assert @person2.errors.on(:encrypted_email)
105
+ assert !@person2.errors[:encrypted_email].empty? || @person2.errors.on(:encrypted_email)
96
106
  end
97
-
107
+
98
108
  end
@@ -1,11 +1,10 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
- require 'mocha'
1
+ require File.expand_path('../test_helper', __FILE__)
3
2
 
4
3
  class SillyEncryptor
5
4
  def self.silly_encrypt(options)
6
5
  (options[:value] + options[:some_arg]).reverse
7
6
  end
8
-
7
+
9
8
  def self.silly_decrypt(options)
10
9
  options[:value].reverse.gsub(/#{options[:some_arg]}$/, '')
11
10
  end
@@ -13,7 +12,7 @@ end
13
12
 
14
13
  class User
15
14
  self.attr_encrypted_options[:key] = Proc.new { |user| user.class.to_s } # default key
16
-
15
+
17
16
  attr_encrypted :email, :without_encoding, :key => 'secret key'
18
17
  attr_encrypted :password, :prefix => 'crypted_', :suffix => '_test'
19
18
  attr_encrypted :ssn, :key => :salt, :attribute => 'ssn_encrypted'
@@ -26,12 +25,12 @@ class User
26
25
  attr_encrypted :with_true_unless, :key => 'secret key', :unless => true
27
26
  attr_encrypted :with_false_unless, :key => 'secret key', :unless => false
28
27
  attr_encrypted :with_if_changed, :key => 'secret key', :if => :should_encrypt
29
-
28
+
30
29
  attr_encryptor :aliased, :key => 'secret_key'
31
-
30
+
32
31
  attr_accessor :salt
33
32
  attr_accessor :should_encrypt
34
-
33
+
35
34
  def initialize
36
35
  self.salt = Time.now.to_i.to_s
37
36
  self.should_encrypt = true
@@ -49,48 +48,48 @@ class SomeOtherClass
49
48
  end
50
49
 
51
50
  class AttrEncryptedTest < Test::Unit::TestCase
52
-
51
+
53
52
  def test_should_store_email_in_encrypted_attributes
54
- assert User.encrypted_attributes.include?('email')
53
+ assert User.encrypted_attributes.include?(:email)
55
54
  end
56
-
55
+
57
56
  def test_should_not_store_salt_in_encrypted_attributes
58
- assert !User.encrypted_attributes.include?('salt')
57
+ assert !User.encrypted_attributes.include?(:salt)
59
58
  end
60
-
59
+
61
60
  def test_attr_encrypted_should_return_true_for_email
62
61
  assert User.attr_encrypted?('email')
63
62
  end
64
-
63
+
65
64
  def test_attr_encrypted_should_return_false_for_salt
66
65
  assert !User.attr_encrypted?('salt')
67
66
  end
68
-
67
+
69
68
  def test_should_generate_an_encrypted_attribute
70
69
  assert User.new.respond_to?(:encrypted_email)
71
70
  end
72
-
71
+
73
72
  def test_should_generate_an_encrypted_attribute_with_a_prefix_and_suffix
74
73
  assert User.new.respond_to?(:crypted_password_test)
75
74
  end
76
-
75
+
77
76
  def test_should_generate_an_encrypted_attribute_with_the_attribute_option
78
77
  assert User.new.respond_to?(:ssn_encrypted)
79
78
  end
80
-
79
+
81
80
  def test_should_not_encrypt_nil_value
82
81
  assert_nil User.encrypt_email(nil)
83
82
  end
84
-
83
+
85
84
  def test_should_not_encrypt_empty_string
86
85
  assert_equal '', User.encrypt_email('')
87
86
  end
88
-
87
+
89
88
  def test_should_encrypt_email
90
89
  assert_not_nil User.encrypt_email('test@example.com')
91
90
  assert_not_equal 'test@example.com', User.encrypt_email('test@example.com')
92
91
  end
93
-
92
+
94
93
  def test_should_encrypt_email_when_modifying_the_attr_writer
95
94
  @user = User.new
96
95
  assert_nil @user.encrypted_email
@@ -98,55 +97,55 @@ class AttrEncryptedTest < Test::Unit::TestCase
98
97
  assert_not_nil @user.encrypted_email
99
98
  assert_equal User.encrypt_email('test@example.com'), @user.encrypted_email
100
99
  end
101
-
100
+
102
101
  def test_should_not_decrypt_nil_value
103
102
  assert_nil User.decrypt_email(nil)
104
103
  end
105
-
104
+
106
105
  def test_should_not_decrypt_empty_string
107
106
  assert_equal '', User.decrypt_email('')
108
107
  end
109
-
108
+
110
109
  def test_should_decrypt_email
111
110
  encrypted_email = User.encrypt_email('test@example.com')
112
111
  assert_not_equal 'test@test.com', encrypted_email
113
112
  assert_equal 'test@example.com', User.decrypt_email(encrypted_email)
114
113
  end
115
-
114
+
116
115
  def test_should_decrypt_email_when_reading
117
116
  @user = User.new
118
117
  assert_nil @user.email
119
118
  @user.encrypted_email = User.encrypt_email('test@example.com')
120
119
  assert_equal 'test@example.com', @user.email
121
120
  end
122
-
121
+
123
122
  def test_should_encrypt_with_encoding
124
- assert_equal User.encrypt_with_encoding('test'), [User.encrypt_without_encoding('test')].pack('m*')
123
+ assert_equal User.encrypt_with_encoding('test'), [User.encrypt_without_encoding('test')].pack('m')
125
124
  end
126
-
125
+
127
126
  def test_should_decrypt_with_encoding
128
127
  encrypted = User.encrypt_with_encoding('test')
129
128
  assert_equal 'test', User.decrypt_with_encoding(encrypted)
130
- assert_equal User.decrypt_with_encoding(encrypted), User.decrypt_without_encoding(encrypted.unpack('m*').to_s)
129
+ assert_equal User.decrypt_with_encoding(encrypted), User.decrypt_without_encoding(encrypted.unpack('m').first)
131
130
  end
132
-
131
+
133
132
  def test_should_encrypt_with_custom_encoding
134
133
  assert_equal User.encrypt_with_encoding('test'), [User.encrypt_without_encoding('test')].pack('m')
135
134
  end
136
-
135
+
137
136
  def test_should_decrypt_with_custom_encoding
138
137
  encrypted = User.encrypt_with_encoding('test')
139
138
  assert_equal 'test', User.decrypt_with_encoding(encrypted)
140
- assert_equal User.decrypt_with_encoding(encrypted), User.decrypt_without_encoding(encrypted.unpack('m').to_s)
139
+ assert_equal User.decrypt_with_encoding(encrypted), User.decrypt_without_encoding(encrypted.unpack('m').first)
141
140
  end
142
-
141
+
143
142
  def test_should_encrypt_with_marshaling
144
143
  @user = User.new
145
144
  @user.with_marshaling = [1, 2, 3]
146
145
  assert_not_nil @user.encrypted_with_marshaling
147
146
  assert_equal User.encrypt_with_marshaling([1, 2, 3]), @user.encrypted_with_marshaling
148
147
  end
149
-
148
+
150
149
  def test_should_decrypt_with_marshaling
151
150
  encrypted = User.encrypt_with_marshaling([1, 2, 3])
152
151
  @user = User.new
@@ -154,11 +153,11 @@ class AttrEncryptedTest < Test::Unit::TestCase
154
153
  @user.encrypted_with_marshaling = encrypted
155
154
  assert_equal [1, 2, 3], @user.with_marshaling
156
155
  end
157
-
156
+
158
157
  def test_should_use_custom_encryptor_and_crypt_method_names_and_arguments
159
158
  assert_equal SillyEncryptor.silly_encrypt(:value => 'testing', :some_arg => 'test'), User.encrypt_credit_card('testing')
160
159
  end
161
-
160
+
162
161
  def test_should_evaluate_a_key_passed_as_a_symbol
163
162
  @user = User.new
164
163
  assert_nil @user.ssn_encrypted
@@ -166,7 +165,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
166
165
  assert_not_nil @user.ssn_encrypted
167
166
  assert_equal Encryptor.encrypt(:value => 'testing', :key => @user.salt), @user.ssn_encrypted
168
167
  end
169
-
168
+
170
169
  def test_should_evaluate_a_key_passed_as_a_proc
171
170
  @user = User.new
172
171
  assert_nil @user.crypted_password_test
@@ -174,7 +173,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
174
173
  assert_not_nil @user.crypted_password_test
175
174
  assert_equal Encryptor.encrypt(:value => 'testing', :key => 'User'), @user.crypted_password_test
176
175
  end
177
-
176
+
178
177
  def test_should_use_options_found_in_the_attr_encrypted_options_attribute
179
178
  @user = User.new
180
179
  assert_nil @user.crypted_password_test
@@ -182,41 +181,41 @@ class AttrEncryptedTest < Test::Unit::TestCase
182
181
  assert_not_nil @user.crypted_password_test
183
182
  assert_equal Encryptor.encrypt(:value => 'testing', :key => 'User'), @user.crypted_password_test
184
183
  end
185
-
184
+
186
185
  def test_should_inherit_encrypted_attributes
187
- assert_equal User.encrypted_attributes.merge('testing' => 'encrypted_testing'), Admin.encrypted_attributes
186
+ assert_equal [User.encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, Admin.encrypted_attributes.keys.collect { |key| key.to_s }.sort
188
187
  end
189
-
188
+
190
189
  def test_should_inherit_attr_encrypted_options
191
190
  assert !User.attr_encrypted_options.empty?
192
191
  assert_equal User.attr_encrypted_options, Admin.attr_encrypted_options
193
192
  end
194
-
193
+
195
194
  def test_should_not_inherit_unrelated_attributes
196
195
  assert SomeOtherClass.attr_encrypted_options.empty?
197
196
  assert SomeOtherClass.encrypted_attributes.empty?
198
197
  end
199
-
198
+
200
199
  def test_should_evaluate_a_symbol_option
201
- assert_equal Object, Object.send(:evaluate_attr_encrypted_option, :class, Object.new)
200
+ assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, :class)
202
201
  end
203
-
202
+
204
203
  def test_should_evaluate_a_proc_option
205
- assert_equal Object, Object.send(:evaluate_attr_encrypted_option, proc { |object| object.class }, Object.new)
204
+ assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, proc { |object| object.class })
206
205
  end
207
-
206
+
208
207
  def test_should_evaluate_a_lambda_option
209
- assert_equal Object, Object.send(:evaluate_attr_encrypted_option, lambda { |object| object.class }, Object.new)
208
+ assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, lambda { |object| object.class })
210
209
  end
211
-
210
+
212
211
  def test_should_evaluate_a_method_option
213
- assert_equal Object, Object.send(:evaluate_attr_encrypted_option, SomeOtherClass.method(:call), Object.new)
212
+ assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, SomeOtherClass.method(:call))
214
213
  end
215
-
214
+
216
215
  def test_should_return_a_string_option
217
- assert_equal 'Object', Object.send(:evaluate_attr_encrypted_option, 'Object', Object.new)
216
+ assert_equal 'Object', Object.new.send(:evaluate_attr_encrypted_option, 'Object')
218
217
  end
219
-
218
+
220
219
  def test_should_encrypt_with_true_if
221
220
  @user = User.new
222
221
  assert_nil @user.encrypted_with_true_if
@@ -224,7 +223,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
224
223
  assert_not_nil @user.encrypted_with_true_if
225
224
  assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key'), @user.encrypted_with_true_if
226
225
  end
227
-
226
+
228
227
  def test_should_not_encrypt_with_false_if
229
228
  @user = User.new
230
229
  assert_nil @user.encrypted_with_false_if
@@ -232,7 +231,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
232
231
  assert_not_nil @user.encrypted_with_false_if
233
232
  assert_equal 'testing', @user.encrypted_with_false_if
234
233
  end
235
-
234
+
236
235
  def test_should_encrypt_with_false_unless
237
236
  @user = User.new
238
237
  assert_nil @user.encrypted_with_false_unless
@@ -240,7 +239,7 @@ class AttrEncryptedTest < Test::Unit::TestCase
240
239
  assert_not_nil @user.encrypted_with_false_unless
241
240
  assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key'), @user.encrypted_with_false_unless
242
241
  end
243
-
242
+
244
243
  def test_should_not_encrypt_with_true_unless
245
244
  @user = User.new
246
245
  assert_nil @user.encrypted_with_true_unless
@@ -248,11 +247,11 @@ class AttrEncryptedTest < Test::Unit::TestCase
248
247
  assert_not_nil @user.encrypted_with_true_unless
249
248
  assert_equal 'testing', @user.encrypted_with_true_unless
250
249
  end
251
-
250
+
252
251
  def test_should_work_with_aliased_attr_encryptor
253
- assert User.encrypted_attributes.include?('aliased')
252
+ assert User.encrypted_attributes.include?(:aliased)
254
253
  end
255
-
254
+
256
255
  def test_should_always_reset_options
257
256
  @user = User.new
258
257
  @user.with_if_changed = "encrypt_stuff"
@@ -261,12 +260,12 @@ class AttrEncryptedTest < Test::Unit::TestCase
261
260
  assert_raise RuntimeError do
262
261
  @user.with_if_changed
263
262
  end
264
-
263
+
265
264
  @user = User.new
266
265
  @user.should_encrypt = false
267
266
  @user.with_if_changed = "not_encrypted_stuff"
268
267
  assert_equal "not_encrypted_stuff", @user.with_if_changed
269
268
  assert_equal "not_encrypted_stuff", @user.encrypted_with_if_changed
270
269
  end
271
-
270
+
272
271
  end