has_secure_attribute 0.1.1 → 0.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.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/lib/active_model/secure_attribute/has_secure_attribute.rb +7 -7
- data/lib/has_secure_attribute/version.rb +1 -1
- data/spec/factories/test_model_with_attributes.rb +9 -0
- data/spec/models/has_secure_attribute_spec.rb +8 -0
- data/spec/models/test_model_with_attribute_with_case_sensitive.rb +8 -0
- data/spec/spec_helper.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21d52ef0208b3210f48d7968e7f28b608039353f
|
4
|
+
data.tar.gz: 283b78f054f1610670abebc05b7a280a42c693bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 427ce061b78c731ade3192481bde53975f5fffd3f88d0dac299ae99e4de2fc6d409c5aa5faafd82392055369c6b7cee693d8cffe73f532f2070d1b11eb820fce
|
7
|
+
data.tar.gz: 687b7590e7250bad4ca8214c42834073e21703249625f41279bd90c9cafec56f36e9ec4b98a27a3d9cc5d0276093382a5df0859cd407868e5ecfebe394b90ea8
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
`has_secure_attribute`
|
2
2
|
======================
|
3
3
|
|
4
|
-
Why have `has_secure_password` and not any attribute that you want
|
4
|
+
Why have `has_secure_password` and not any attribute that you want? I believe that, quite often, we want to one-way encrypt one attribute and authenticate against its value, and this is not only the `password` case.
|
5
5
|
|
6
6
|
Requires
|
7
7
|
--------
|
@@ -36,6 +36,8 @@ In the above example:
|
|
36
36
|
* It raises an exception if `security_answer_digest` is empty on create.
|
37
37
|
* It defines the method `authenticate_security_answer(answer_to_authenticate)` which returns `false` if the answer given does not correspond to the saved digest, or returns the object instance itself if it does.
|
38
38
|
|
39
|
+
__Case Insensitive Values__: you can pass `case_insensitive => false` if you want to handle values that match even if they differ on case. Then, `answer` will match `Answer`, for example.
|
40
|
+
|
39
41
|
Do you want to test it?
|
40
42
|
------------------------
|
41
43
|
|
@@ -21,7 +21,7 @@ module ActiveModel
|
|
21
21
|
def has_secure_attribute(meth, *args, &block)
|
22
22
|
attribute_sym = meth.to_sym
|
23
23
|
attr_reader attribute_sym # setter is defined later on
|
24
|
-
options = {:
|
24
|
+
options = {validations: true, protect_setter_for_digest: false, case_sensitive: true}
|
25
25
|
options.merge! args[0] unless args.blank?
|
26
26
|
if options[:validations]
|
27
27
|
validates attribute_sym, confirmation: true, if: lambda { |m| m.send(attribute_sym).present? }
|
@@ -30,18 +30,18 @@ module ActiveModel
|
|
30
30
|
before_create { raise "#{attribute_sym}_digest missing on new record" if send("#{attribute_sym}_digest").blank? }
|
31
31
|
end
|
32
32
|
|
33
|
-
define_setter(attribute_sym)
|
33
|
+
define_setter(attribute_sym, options)
|
34
34
|
protect_setter_for_digest(attribute_sym) if options[:protect_setter_for_digest]
|
35
35
|
|
36
|
-
define_authenticate_method(attribute_sym)
|
36
|
+
define_authenticate_method(attribute_sym, options)
|
37
37
|
end
|
38
38
|
|
39
|
-
def define_setter(attribute_sym)
|
39
|
+
def define_setter(attribute_sym, options)
|
40
40
|
define_method "#{attribute_sym.to_s}=" do |unencrypted_value|
|
41
41
|
unless unencrypted_value.blank?
|
42
42
|
instance_variable_set("@#{attribute_sym.to_s}".to_sym, unencrypted_value)
|
43
43
|
cost = ActiveModel::SecureAttribute.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine::DEFAULT_COST
|
44
|
-
send("#{attribute_sym.to_s}_digest=".to_sym, BCrypt::Password.create(unencrypted_value, cost: cost))
|
44
|
+
send("#{attribute_sym.to_s}_digest=".to_sym, BCrypt::Password.create(options[:case_sensitive] ? unencrypted_value : unencrypted_value.downcase, cost: cost))
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -53,9 +53,9 @@ module ActiveModel
|
|
53
53
|
protected "#{attribute_sym}_digest=".to_sym
|
54
54
|
end
|
55
55
|
|
56
|
-
def define_authenticate_method(attribute_sym)
|
56
|
+
def define_authenticate_method(attribute_sym, options)
|
57
57
|
define_method "authenticate_#{attribute_sym}" do |value|
|
58
|
-
BCrypt::Password.new(send("#{attribute_sym}_digest")) == value && self
|
58
|
+
BCrypt::Password.new(send("#{attribute_sym}_digest")) == (options[:case_sensitive] ? value : value.downcase) && self
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -24,4 +24,13 @@ FactoryGirl.define do
|
|
24
24
|
security_answer 'answer'
|
25
25
|
security_answer_confirmation 'answer'
|
26
26
|
end
|
27
|
+
|
28
|
+
factory :test_model_with_attribute_with_case_sensitive do
|
29
|
+
username 'username_protect'
|
30
|
+
password 'password'
|
31
|
+
password_confirmation 'password'
|
32
|
+
security_question 'question'
|
33
|
+
security_answer 'answer'
|
34
|
+
security_answer_confirmation 'answer'
|
35
|
+
end
|
27
36
|
end
|
@@ -163,3 +163,11 @@ describe TestModelWithAttributeProtectSetterForDigest do
|
|
163
163
|
end.should raise_error NoMethodError
|
164
164
|
end
|
165
165
|
end
|
166
|
+
|
167
|
+
describe TestModelWithAttributeWithCaseSensitive do
|
168
|
+
it 'should authenticate even if answer is of different case' do
|
169
|
+
t = FactoryGirl.create :test_model_with_attribute_with_case_sensitive, security_answer: 'Answer', security_answer_confirmation: 'Answer'
|
170
|
+
|
171
|
+
t.authenticate_security_answer('answer').should eq t
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class TestModelWithAttributeWithCaseSensitive < ActiveRecord::Base
|
2
|
+
self.table_name = "test_model_with_attributes"
|
3
|
+
has_secure_password
|
4
|
+
has_secure_security_answer :case_sensitive => false
|
5
|
+
|
6
|
+
validates :username, :presence => true, :uniqueness => {:case_sensitive => false}
|
7
|
+
validates :security_question, :presence => true
|
8
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,6 +7,7 @@ require File.expand_path("../../lib/active_model/secure_attribute/has_secure_att
|
|
7
7
|
require File.expand_path("../models/test_model_with_attribute", __FILE__)
|
8
8
|
require File.expand_path("../models/test_model_with_attribute_no_validation", __FILE__)
|
9
9
|
require File.expand_path("../models/test_model_with_attribute_protect_setter_for_digest", __FILE__)
|
10
|
+
require File.expand_path("../models/test_model_with_attribute_with_case_sensitive", __FILE__)
|
10
11
|
|
11
12
|
require 'factory_girl'
|
12
13
|
FactoryGirl.find_definitions
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: has_secure_attribute
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Panayotis Matsinopoulos
|
@@ -126,6 +126,7 @@ files:
|
|
126
126
|
- spec/models/test_model_with_attribute_no_validation.rb
|
127
127
|
- spec/models/test_model_with_attribute_protect_setter_for_digest.rb
|
128
128
|
- spec/models/test_model_with_attribute.rb
|
129
|
+
- spec/models/test_model_with_attribute_with_case_sensitive.rb
|
129
130
|
- spec/db/migrate/db_helper.rb
|
130
131
|
- spec/db/migrate/create_test_model_with_attributes.rb
|
131
132
|
- README.md
|