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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YTZhOWU5OTA1YzJkYTU5MmFiYWQyMWYxMWYyMjQyZjczZDA0Y2RhNg==
4
+ YjE0YjFiMmY0YzBhMTk5YWUwMDAxNGJiMGEyZmY5OWJiYzY1NWE5OQ==
5
5
  data.tar.gz: !binary |-
6
- MTc5ZjRjNDMzOTE0OWQ1OTU3NmVlYWRlNGZlY2EyYTU1NjZjM2QxZA==
6
+ MjE2MjYyZjA1NTRlYmUxZjE5MmQ2YTI2ZDUyOWNlZmFiYjUxOTc2Mw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YTc1NTFiODYxZmUwZmUxYTM3MDMwZWZmNTE2NTJlMDE4MmEzMzk1ZmM0OTg3
10
- MmZlYmRhNzdiNjMyNmUyNmJlMjkwMGUzZTk4YTE1NzZjNGZmNmJmYzQ2MTE5
11
- Y2UyMWQzOTAyZmE5MzBlZGI0ZjMyZDMwZTU5OGVhMWYzZmU1ZTg=
9
+ M2U1MGQ0NDUxMzdjYmRlMWQzNGU4MGRmYmEwZTYzYWQ0NzhhYjdiMzRmMTNl
10
+ OWRlZDZlYWRiY2VjOTRiNDYzYjBmMjZhZTZkZTMxMWQ1NDliMTNkZWUxNWVl
11
+ YmU2NzI2ZWEzOGQ4OThkNmE2OTY0MmJmZjJlMjM4ZTljZmEwYjI=
12
12
  data.tar.gz: !binary |-
13
- MjIxZTNmMjMwNTI2ZTcxMWEyNTFjMGNkM2EyMTgyOWJjNDdmMzA3MmRlY2Zm
14
- NzMwMzk0N2VjNjRkOWJhMjRhOTI1MzllZGU4MGYzNjk2YzI0N2E0ZjEwMjM0
15
- MjY3YTEzMDEyMDVmZjQ4ZTc0MjM1OWUxODNiMTg3ZWQyNWM4ZDc=
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 = self.password_digest unless @old_password_digest or self.password_digest.blank?
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.3'
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 attributes
30
- keys = [ 'password', 'password_confirmation' ]
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_editable_password
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francesco Boffa