has_editable_password 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/has_editable_password.rb +27 -1
- data/lib/version.rb +1 -1
- data/spec/has_editable_password_spec.rb +42 -0
- data/spec/spec_helper.rb +4 -7
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YjE0YjFiMmY0YzBhMTk5YWUwMDAxNGJiMGEyZmY5OWJiYzY1NWE5OQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MjE2MjYyZjA1NTRlYmUxZjE5MmQ2YTI2ZDUyOWNlZmFiYjUxOTc2Mw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
M2U1MGQ0NDUxMzdjYmRlMWQzNGU4MGRmYmEwZTYzYWQ0NzhhYjdiMzRmMTNl
|
10
|
+
OWRlZDZlYWRiY2VjOTRiNDYzYjBmMjZhZTZkZTMxMWQ1NDliMTNkZWUxNWVl
|
11
|
+
YmU2NzI2ZWEzOGQ4OThkNmE2OTY0MmJmZjJlMjM4ZTljZmEwYjI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZDMyZTJhNmQ4YmFkZjY3NWZjMTdmYTFjZjIxMTU2MGY3ZDg3NWU3OGY3NDdl
|
14
|
+
MWY5ZDc5MWJiYjYzMTBlMjMxOWE2MTVmMjljODMwZDgzNmY4YmY5YTAyYWJk
|
15
|
+
ZjMzNTMxOWI4ZWNkN2ZiYjE1MGZlNTFmZDE3OTM0YmM5NTZkYmY=
|
@@ -15,11 +15,30 @@ module HasEditablePassword
|
|
15
15
|
validate :password_change, on: :update, if: :password_digest_changed?
|
16
16
|
|
17
17
|
def password=(value)
|
18
|
-
@old_password_digest =
|
18
|
+
@old_password_digest = password_digest unless @old_password_digest or password_digest.blank?
|
19
|
+
|
20
|
+
unless password_digest.blank? or password_digest_changed?
|
21
|
+
self.previous_password_digest = password_digest if respond_to? :previous_password_digest=
|
22
|
+
self.password_digest_updated = Time.now if respond_to? :password_digest_updated=
|
23
|
+
end
|
24
|
+
|
19
25
|
super(value)
|
20
26
|
end
|
21
27
|
end
|
22
28
|
|
29
|
+
##
|
30
|
+
# Creates a new +password_recovery_token+
|
31
|
+
#
|
32
|
+
# If a token was already there it is discarded. Also sets
|
33
|
+
# +password_recovery_token_creation+ to the current time.
|
34
|
+
# Unless specified it calls +save+ to store the token in the database.
|
35
|
+
#
|
36
|
+
# options[:length] - this is the length of the SecureRandom string generated
|
37
|
+
# as the token. Since the token is base64_encoded it will be longer than
|
38
|
+
# that. Default is 32.
|
39
|
+
# options[:save] - you can use this if you don't want save to be called.
|
40
|
+
# generate_recovery_token(save: false)
|
41
|
+
#
|
23
42
|
def generate_recovery_token(options = {})
|
24
43
|
token = SecureRandom.urlsafe_base64(options.delete(:length) || 32)
|
25
44
|
self.password_recovery_token = BCrypt::Password.create(token)
|
@@ -28,10 +47,17 @@ module HasEditablePassword
|
|
28
47
|
token
|
29
48
|
end
|
30
49
|
|
50
|
+
##
|
51
|
+
# Returns true if the +recovery_token+ matches with the stored one and the
|
52
|
+
# token creation time is less than 24 hours ago
|
53
|
+
#
|
31
54
|
def valid_recovery_token?
|
32
55
|
recovery_token_match? and !recovery_token_expired?
|
33
56
|
end
|
34
57
|
|
58
|
+
##
|
59
|
+
# Returns true if +current_password+ matches the stored +password_digest+.
|
60
|
+
#
|
35
61
|
def current_password_match?
|
36
62
|
if @current_password
|
37
63
|
if @old_password_digest
|
data/lib/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
VERSION = '0.0
|
1
|
+
VERSION = '0.1.0'
|
@@ -33,6 +33,48 @@ describe HasEditablePassword do
|
|
33
33
|
user.password = 'secret'
|
34
34
|
expect(BCrypt::Password.new(user.password_digest)).to eq 'secret'
|
35
35
|
end
|
36
|
+
|
37
|
+
context 'previous_password_digest= exists' do
|
38
|
+
it 'sets the previous_password_digest field' do
|
39
|
+
expect(user).to receive :previous_password_digest=
|
40
|
+
user.password = 'new_secret'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'previous_password_digest= does not exist' do
|
45
|
+
before { user.stub(:respond_to?).and_return false }
|
46
|
+
|
47
|
+
it 'does not set the previous_password_digest field' do
|
48
|
+
expect(user).to_not receive :previous_password_digest=
|
49
|
+
user.password = 'new_secret'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'password_digest_updated= exists' do
|
54
|
+
it 'sets the password_digest_updated field' do
|
55
|
+
expect(user).to receive(:password_digest_updated=)
|
56
|
+
user.password = 'new_secret'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'password_digest_updated= does not exist' do
|
61
|
+
before { user.stub(:respond_to?).and_return false }
|
62
|
+
|
63
|
+
it 'does not set the password_digest_updated field' do
|
64
|
+
expect(user).to_not receive(:password_digest_updated=)
|
65
|
+
user.password = 'new_secret'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'only updates the previous_password and password_updated fields once' do
|
70
|
+
user.password = 'new_secret'
|
71
|
+
user.stub(:password_digest_changed?).and_return true
|
72
|
+
user.password = 'banana'
|
73
|
+
|
74
|
+
# Twice just to improve comprension
|
75
|
+
expect(BCrypt::Password.new(user.previous_password_digest)).to_not eq 'new_secret'
|
76
|
+
expect(BCrypt::Password.new(user.previous_password_digest)).to eq 'secret'
|
77
|
+
end
|
36
78
|
end
|
37
79
|
|
38
80
|
describe '#generate_recovery_token' do
|
data/spec/spec_helper.rb
CHANGED
@@ -19,6 +19,8 @@ class User
|
|
19
19
|
attr_accessor :password_digest
|
20
20
|
attr_accessor :password_recovery_token
|
21
21
|
attr_accessor :password_recovery_token_creation
|
22
|
+
attr_accessor :previous_password_digest
|
23
|
+
attr_accessor :password_digest_updated
|
22
24
|
|
23
25
|
def initialize(hash = {})
|
24
26
|
hash.each do |k, v|
|
@@ -26,13 +28,8 @@ class User
|
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
29
|
-
def
|
30
|
-
|
31
|
-
values = keys.map do |k|
|
32
|
-
send(k)
|
33
|
-
end
|
34
|
-
|
35
|
-
Hash[keys.zip(values)]
|
31
|
+
def password_digest_changed?
|
32
|
+
false
|
36
33
|
end
|
37
34
|
|
38
35
|
def save
|