has_editable_password 0.0.3 → 0.1.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 +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
|