has_secure_attribute 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/lib/active_model/secure_attribute/has_secure_attribute.rb +9 -4
- data/lib/has_secure_attribute/version.rb +1 -1
- data/spec/factories/test_model_with_attributes.rb +8 -0
- data/spec/models/has_secure_attribute_spec.rb +11 -0
- data/spec/models/test_model_with_attribute_disable_confirmation.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: 9365979f3bd3c6800d9815e398ac86e02f7f4b41
|
4
|
+
data.tar.gz: 4ccae4ca00ef2afbc27e76b1a972c6018424a1c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7554a58cdbf1569be7aba7b2a0a58304764f153807aa4e561f88245c6bfbd394548dfedee91c0188b2b0f6be3dfaa98a87e7a4cffbdd47cff882394a96b0d6eb
|
7
|
+
data.tar.gz: 9baf44120d62ebc15e3d1b1f30d5fadabcfcfa4e3b285f67b7afe989169ebe649d4abccd7294c176b29cca4177b2146baf17fd6ecdda6451b70c5273c50ec73e
|
data/README.md
CHANGED
@@ -29,14 +29,15 @@ In the above example:
|
|
29
29
|
* Your should have a `users` table that has one column: `security_answer_digest`.
|
30
30
|
* It creates a reader: `security_answer`.
|
31
31
|
* It creates a writer: `security_answer=(value)` which basically saves the security answer given into the database on column `security_answer_digest` but is saves it encrypted.
|
32
|
-
* It adds some validations (if you want to avoid having these validations: `has_secure_security_answer :
|
32
|
+
* It adds some validations (if you want to avoid having these validations: `has_secure_security_answer validations: false`).
|
33
33
|
* It creates a confirmation validation on `security_answer` but only if `security_answer` is given (for confirmation validations see [this](http://http://guides.rubyonrails.org/active_record_validations.html#confirmation)).
|
34
34
|
* It creates a presence validation on `security_answer` but only on create.
|
35
35
|
* It creates a presence validation on `security_answer_confirmation` but only if `security_answer` has been given.
|
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
|
39
|
+
__Case Insensitive Values__: you can do `has_secure_security_answer 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
|
+
__Do not use confirmation__: you can do `has_secure_security_answer confirm: false` if you do not want to have confirmation attribute for the attribute you are securing.
|
40
41
|
|
41
42
|
Do you want to test it?
|
42
43
|
------------------------
|
@@ -21,12 +21,11 @@ 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 = {validations: true, protect_setter_for_digest: false, case_sensitive: true}
|
24
|
+
options = {validations: true, protect_setter_for_digest: false, case_sensitive: true, confirmation: true}
|
25
25
|
options.merge! args[0] unless args.blank?
|
26
26
|
if options[:validations]
|
27
|
-
|
28
|
-
validates attribute_sym,
|
29
|
-
validates "#{attribute_sym}_confirmation".to_sym, presence: true, if: lambda { |m| m.send(attribute_sym).present? }
|
27
|
+
confirm attribute_sym if options[:confirmation]
|
28
|
+
validates attribute_sym, presence: true, on: :create
|
30
29
|
before_create { raise "#{attribute_sym}_digest missing on new record" if send("#{attribute_sym}_digest").blank? }
|
31
30
|
end
|
32
31
|
|
@@ -36,6 +35,11 @@ module ActiveModel
|
|
36
35
|
define_authenticate_method(attribute_sym, options)
|
37
36
|
end
|
38
37
|
|
38
|
+
def confirm(attribute_sym)
|
39
|
+
validates attribute_sym, confirmation: true, if: lambda { |m| m.send(attribute_sym).present? }
|
40
|
+
validates "#{attribute_sym}_confirmation".to_sym, presence: true, if: lambda { |m| m.send(attribute_sym).present? }
|
41
|
+
end
|
42
|
+
|
39
43
|
def define_setter(attribute_sym, options)
|
40
44
|
define_method "#{attribute_sym.to_s}=" do |unencrypted_value|
|
41
45
|
unless unencrypted_value.blank?
|
@@ -60,6 +64,7 @@ module ActiveModel
|
|
60
64
|
end
|
61
65
|
|
62
66
|
protected :has_secure_attribute
|
67
|
+
protected :confirm
|
63
68
|
protected :define_setter
|
64
69
|
protected :protect_setter_for_digest
|
65
70
|
protected :define_authenticate_method
|
@@ -33,4 +33,12 @@ FactoryGirl.define do
|
|
33
33
|
security_answer 'answer'
|
34
34
|
security_answer_confirmation 'answer'
|
35
35
|
end
|
36
|
+
|
37
|
+
factory :test_model_with_attribute_disable_confirmation do
|
38
|
+
username 'username_protect'
|
39
|
+
password 'password'
|
40
|
+
password_confirmation 'password'
|
41
|
+
security_question 'question'
|
42
|
+
security_answer 'answer'
|
43
|
+
end
|
36
44
|
end
|
@@ -171,3 +171,14 @@ describe TestModelWithAttributeWithCaseSensitive do
|
|
171
171
|
t.authenticate_security_answer('answer').should eq t
|
172
172
|
end
|
173
173
|
end
|
174
|
+
|
175
|
+
describe TestModelWithAttributeDisableConfirmation do
|
176
|
+
it { should_not respond_to(:security_answer_confirmation) }
|
177
|
+
it { should_not respond_to(:security_answer_confirmation=) }
|
178
|
+
it 'should allow to create and save without any confirmation on security answer' do
|
179
|
+
t = FactoryGirl.create :test_model_with_attribute_disable_confirmation, security_answer: 'Answer'
|
180
|
+
t.save!
|
181
|
+
t.authenticate_security_answer('another answer').should be_false
|
182
|
+
t.authenticate_security_answer('Answer').should eq t
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class TestModelWithAttributeDisableConfirmation < ActiveRecord::Base
|
2
|
+
self.table_name = "test_model_with_attributes"
|
3
|
+
has_secure_password
|
4
|
+
has_secure_security_answer confirmation: 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
@@ -8,6 +8,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
10
|
require File.expand_path("../models/test_model_with_attribute_with_case_sensitive", __FILE__)
|
11
|
+
require File.expand_path("../models/test_model_with_attribute_disable_confirmation", __FILE__)
|
11
12
|
|
12
13
|
require 'factory_girl'
|
13
14
|
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.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Panayotis Matsinopoulos
|
@@ -125,6 +125,7 @@ files:
|
|
125
125
|
- spec/models/has_secure_attribute_spec.rb
|
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
|
+
- spec/models/test_model_with_attribute_disable_confirmation.rb
|
128
129
|
- spec/models/test_model_with_attribute.rb
|
129
130
|
- spec/models/test_model_with_attribute_with_case_sensitive.rb
|
130
131
|
- spec/db/migrate/db_helper.rb
|