authenticate 0.2.3 → 0.3.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/.gitignore +4 -4
- data/CHANGELOG.md +12 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +21 -6
- data/app/controllers/authenticate/passwords_controller.rb +1 -1
- data/authenticate.gemspec +7 -3
- data/config/locales/authenticate.en.yml +1 -1
- data/gemfiles/rails42.gemfile +6 -1
- data/lib/authenticate/callbacks/brute_force.rb +3 -4
- data/lib/authenticate/configuration.rb +2 -2
- data/lib/authenticate/controller.rb +1 -2
- data/lib/authenticate/model/brute_force.rb +2 -2
- data/lib/authenticate/model/db_password.rb +2 -3
- data/lib/authenticate/model/email.rb +3 -6
- data/lib/authenticate/model/lifetimed.rb +1 -1
- data/lib/authenticate/model/password_reset.rb +1 -1
- data/lib/authenticate/model/timeoutable.rb +2 -2
- data/lib/authenticate/model/trackable.rb +1 -1
- data/lib/authenticate/model/username.rb +1 -1
- data/lib/authenticate/session.rb +0 -4
- data/lib/authenticate/user.rb +12 -0
- data/lib/authenticate/version.rb +1 -1
- data/spec/controllers/passwords_controller_spec.rb +119 -0
- data/spec/controllers/secured_controller_spec.rb +70 -0
- data/spec/controllers/sessions_controller_spec.rb +86 -0
- data/spec/controllers/users_controller_spec.rb +82 -0
- data/spec/dummy/app/controllers/application_controller.rb +2 -0
- data/spec/dummy/app/controllers/welcome_controller.rb +4 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/welcome/index.html.erb +4 -0
- data/spec/dummy/config/application.rb +2 -0
- data/spec/dummy/config/environments/production.rb +12 -0
- data/spec/dummy/config/initializers/authenticate.rb +4 -11
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/factories/users.rb +2 -4
- data/spec/features/brute_force_spec.rb +49 -0
- data/spec/features/max_session_lifetime_spec.rb +30 -0
- data/spec/features/password_reset_spec.rb +69 -0
- data/spec/features/password_update_spec.rb +41 -0
- data/spec/features/sign_in_spec.rb +29 -0
- data/spec/features/sign_out_spec.rb +22 -0
- data/spec/features/sign_up_spec.rb +42 -0
- data/spec/features/timeoutable_spec.rb +30 -0
- data/spec/model/brute_force_spec.rb +26 -29
- data/spec/model/configuration_spec.rb +61 -0
- data/spec/model/db_password_spec.rb +8 -9
- data/spec/model/email_spec.rb +0 -1
- data/spec/model/lifetimed_spec.rb +6 -18
- data/spec/model/password_reset_spec.rb +2 -9
- data/spec/model/session_spec.rb +16 -23
- data/spec/model/timeoutable_spec.rb +8 -7
- data/spec/model/trackable_spec.rb +0 -1
- data/spec/model/user_spec.rb +1 -2
- data/spec/spec_helper.rb +33 -131
- data/spec/support/controllers/controller_helpers.rb +24 -0
- data/spec/support/features/feature_helpers.rb +36 -0
- metadata +80 -8
- data/spec/configuration_spec.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 314ba694f7183f9f3a7ed5c239c1ec1dc7e45298
|
4
|
+
data.tar.gz: dabffa423ced67c1f8bf767befdee51979ef3989
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e3cc55ad8b83ab460966a9bfd9000c7799ed5792cc0402c8ce90eb22d3f055b0b3dadf146038c46c844f5278e4a233c6237992febf2679ddc95838c0ad0d4b8
|
7
|
+
data.tar.gz: 24f500d3c8917867c2a16c7b3ba2f0bcf44c47dfe5ea83ffb949c9bb03c864f880a30ccab3f7e7f755cb4fa7039f12926b42cd01d30fbab9482a7c0851c8ff1a
|
data/.gitignore
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
authenticate-*.gem
|
3
3
|
log/*.log
|
4
4
|
pkg/
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
spec/dummy/db/*.sqlite3
|
6
|
+
spec/dummy/db/*.sqlite3-journal
|
7
|
+
spec/dummy/log/*.log
|
8
|
+
spec/dummy/tmp/
|
9
9
|
spec/dummy/log/test.log
|
10
10
|
spec/dummy/log/development.log
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Authenticate Changelog
|
2
2
|
|
3
|
+
## [0.3.0] - February 24, 2016
|
4
|
+
|
5
|
+
Moved normalize_email and find_normalized_email methods to base User module.
|
6
|
+
Added full suite of controller and feature tests.
|
7
|
+
Bug fixes:
|
8
|
+
* failed login count fix was off by one.
|
9
|
+
* password validation now done only in correct circumstances
|
10
|
+
|
11
|
+
[0.3.0]: https://github.com/tomichj/authenticate/compare/v0.2.2...v0.3.0
|
12
|
+
|
13
|
+
|
14
|
+
|
3
15
|
## [0.2.3] - February 13, 2016
|
4
16
|
|
5
17
|
Small bugfix for :username authentication.
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
authenticate (0.
|
4
|
+
authenticate (0.3.0)
|
5
5
|
bcrypt
|
6
6
|
email_validator (~> 1.6)
|
7
7
|
rails (>= 4.0, < 5.1)
|
@@ -44,20 +44,26 @@ GEM
|
|
44
44
|
minitest (~> 5.1)
|
45
45
|
thread_safe (~> 0.3, >= 0.3.4)
|
46
46
|
tzinfo (~> 1.1)
|
47
|
+
addressable (2.4.0)
|
47
48
|
arel (6.0.3)
|
48
49
|
bcrypt (3.1.10)
|
49
50
|
builder (3.2.2)
|
51
|
+
capybara (2.6.2)
|
52
|
+
addressable
|
53
|
+
mime-types (>= 1.16)
|
54
|
+
nokogiri (>= 1.3.3)
|
55
|
+
rack (>= 1.0.0)
|
56
|
+
rack-test (>= 0.5.4)
|
57
|
+
xpath (~> 2.0)
|
50
58
|
coderay (1.1.0)
|
51
59
|
concurrent-ruby (1.0.0)
|
60
|
+
database_cleaner (1.5.1)
|
52
61
|
diff-lcs (1.2.5)
|
53
62
|
email_validator (1.6.0)
|
54
63
|
activemodel
|
55
64
|
erubis (2.7.0)
|
56
65
|
factory_girl (4.4.0)
|
57
66
|
activesupport (>= 3.0.0)
|
58
|
-
factory_girl_rails (4.4.1)
|
59
|
-
factory_girl (~> 4.4.0)
|
60
|
-
railties (>= 3.0.0)
|
61
67
|
globalid (0.3.6)
|
62
68
|
activesupport (>= 4.1.0)
|
63
69
|
i18n (0.7.0)
|
@@ -120,6 +126,8 @@ GEM
|
|
120
126
|
rspec-mocks (~> 3.1.0)
|
121
127
|
rspec-support (~> 3.1.0)
|
122
128
|
rspec-support (3.1.2)
|
129
|
+
shoulda-matchers (2.8.0)
|
130
|
+
activesupport (>= 3.0.0)
|
123
131
|
slop (3.6.0)
|
124
132
|
sprockets (3.5.2)
|
125
133
|
concurrent-ruby (~> 1.0)
|
@@ -131,18 +139,25 @@ GEM
|
|
131
139
|
sqlite3 (1.3.11)
|
132
140
|
thor (0.19.1)
|
133
141
|
thread_safe (0.3.5)
|
142
|
+
timecop (0.8.0)
|
134
143
|
tzinfo (1.2.2)
|
135
144
|
thread_safe (~> 0.1)
|
145
|
+
xpath (2.0.0)
|
146
|
+
nokogiri (~> 1.3)
|
136
147
|
|
137
148
|
PLATFORMS
|
138
149
|
ruby
|
139
150
|
|
140
151
|
DEPENDENCIES
|
141
152
|
authenticate!
|
142
|
-
|
153
|
+
capybara (~> 2.6.2)
|
154
|
+
database_cleaner (~> 1.5.1)
|
155
|
+
factory_girl
|
143
156
|
pry
|
144
|
-
rspec-rails
|
157
|
+
rspec-rails (~> 3.1.0)
|
158
|
+
shoulda-matchers (~> 2.8)
|
145
159
|
sqlite3
|
160
|
+
timecop (~> 0.8.0)
|
146
161
|
|
147
162
|
BUNDLED WITH
|
148
163
|
1.11.2
|
@@ -68,7 +68,7 @@ class Authenticate::PasswordsController < Authenticate::AuthenticateController
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def find_user_for_create
|
71
|
-
Authenticate.configuration.user_model_class.
|
71
|
+
Authenticate.configuration.user_model_class.find_by_normalized_email params[:password][:email]
|
72
72
|
end
|
73
73
|
|
74
74
|
def find_user_for_edit
|
data/authenticate.gemspec
CHANGED
@@ -25,11 +25,15 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_dependency 'email_validator', '~> 1.6'
|
26
26
|
s.add_dependency 'rails', '>= 4.0', '< 5.1'
|
27
27
|
|
28
|
-
# s.add_development_dependency '
|
29
|
-
s.add_development_dependency '
|
30
|
-
s.add_development_dependency 'rspec-rails'
|
28
|
+
# s.add_development_dependency 'factory_girl_rails', '~> 4.4.1'
|
29
|
+
s.add_development_dependency 'factory_girl'
|
30
|
+
s.add_development_dependency 'rspec-rails', '~> 3.1.0'
|
31
31
|
s.add_development_dependency 'pry'
|
32
32
|
s.add_development_dependency 'sqlite3'
|
33
|
+
s.add_development_dependency 'shoulda-matchers', '~> 2.8'
|
34
|
+
s.add_development_dependency 'capybara', '~> 2.6.2'
|
35
|
+
s.add_development_dependency 'database_cleaner', '~> 1.5.1'
|
36
|
+
s.add_development_dependency 'timecop', '~> 0.8.0'
|
33
37
|
|
34
38
|
s.required_ruby_version = Gem::Requirement.new('>= 2.0')
|
35
39
|
end
|
data/gemfiles/rails42.gemfile
CHANGED
@@ -2,8 +2,13 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
+
gem 'shoulda-matchers', '~> 2.8'
|
6
|
+
gem 'capybara', '~> 2.6.2'
|
7
|
+
gem 'database_cleaner', '~> 1.5.1'
|
8
|
+
gem 'timecop', '~> 0.8.0'
|
9
|
+
|
5
10
|
gem "bundler", "~> 1.3"
|
6
|
-
gem "
|
11
|
+
gem "factory_girl", "~> 4.4"
|
7
12
|
gem "rspec-rails", "~> 3.1"
|
8
13
|
gem "sqlite3", "~> 1.3"
|
9
14
|
gem "pry", :require => false
|
@@ -6,7 +6,7 @@ Authenticate.lifecycle.prepend_after_authentication name: 'brute force protectio
|
|
6
6
|
unless session.authenticated? || Authenticate.configuration.max_consecutive_bad_logins_allowed.nil?
|
7
7
|
user_credentials = User.credentials(session.request.params)
|
8
8
|
user ||= User.find_by_credentials(user_credentials)
|
9
|
-
if user
|
9
|
+
if user && user.respond_to?(:register_failed_login!)
|
10
10
|
user.register_failed_login!
|
11
11
|
user.save!
|
12
12
|
end
|
@@ -14,14 +14,13 @@ Authenticate.lifecycle.prepend_after_authentication name: 'brute force protectio
|
|
14
14
|
|
15
15
|
# if user is locked, and we allow a lockout period, then unlock the user if they've waited
|
16
16
|
# longer than the lockout period.
|
17
|
-
if user && !Authenticate.configuration.bad_login_lockout_period.nil?
|
17
|
+
if user && user.respond_to?(:locked?) && user.locked? && !Authenticate.configuration.bad_login_lockout_period.nil?
|
18
18
|
user.unlock! if user.lock_expires_at <= Time.now.utc
|
19
19
|
end
|
20
20
|
|
21
21
|
# if the user is still locked, let them know how long they are locked for.
|
22
|
-
if user && user.locked?
|
22
|
+
if user && user.respond_to?(:locked?) && user.locked?
|
23
23
|
remaining = time_ago_in_words(user.lock_expires_at)
|
24
|
-
# throw(:failure, "Your account is locked, will unlock in #{remaining.to_s}")
|
25
24
|
throw(:failure, I18n.t('callbacks.brute_force.failure', time_remaining: remaining.to_s))
|
26
25
|
end
|
27
26
|
|
@@ -206,12 +206,12 @@ module Authenticate
|
|
206
206
|
|
207
207
|
def user_model_route_key
|
208
208
|
return :users if @user_model == '::User' # avoid nil in generator
|
209
|
-
|
209
|
+
user_model_class.model_name.route_key
|
210
210
|
end
|
211
211
|
|
212
212
|
def user_model_param_key
|
213
213
|
return :user if @user_model == '::User' # avoid nil in generator
|
214
|
-
|
214
|
+
user_model_class.model_name.param_key
|
215
215
|
end
|
216
216
|
|
217
217
|
# The name of foreign key parameter for the configured user model.
|
@@ -12,9 +12,7 @@ module Authenticate
|
|
12
12
|
# Validate a user's identity with (typically) email/ID & password, and return the User if valid, or nil.
|
13
13
|
# After calling this, call login(user) to complete the process.
|
14
14
|
def authenticate(params)
|
15
|
-
# todo: get params from User model
|
16
15
|
credentials = Authenticate.configuration.user_model_class.credentials(params)
|
17
|
-
debug "Controller::credentials: #{credentials.inspect}"
|
18
16
|
Authenticate.configuration.user_model_class.authenticate(credentials)
|
19
17
|
end
|
20
18
|
|
@@ -102,6 +100,7 @@ module Authenticate
|
|
102
100
|
|
103
101
|
# User is not authorized, bounce 'em to sign in
|
104
102
|
def unauthorized(msg = t('flashes.failure_when_not_signed_in'))
|
103
|
+
authenticate_session.deauthenticate
|
105
104
|
respond_to do |format|
|
106
105
|
format.any(:js, :json, :xml) { head :unauthorized }
|
107
106
|
format.any {
|
@@ -33,7 +33,7 @@ module Authenticate
|
|
33
33
|
module BruteForce
|
34
34
|
extend ActiveSupport::Concern
|
35
35
|
|
36
|
-
def self.required_fields(
|
36
|
+
def self.required_fields(_klass)
|
37
37
|
[:failed_logins_count, :lock_expires_at]
|
38
38
|
end
|
39
39
|
|
@@ -41,7 +41,7 @@ module Authenticate
|
|
41
41
|
def register_failed_login!
|
42
42
|
self.failed_logins_count ||= 0
|
43
43
|
self.failed_logins_count += 1
|
44
|
-
lock! if self.failed_logins_count
|
44
|
+
lock! if self.failed_logins_count > max_bad_logins
|
45
45
|
end
|
46
46
|
|
47
47
|
def lock!
|
@@ -26,7 +26,7 @@ module Authenticate
|
|
26
26
|
module DbPassword
|
27
27
|
extend ActiveSupport::Concern
|
28
28
|
|
29
|
-
def self.required_fields(
|
29
|
+
def self.required_fields(_klass)
|
30
30
|
[:encrypted_password]
|
31
31
|
end
|
32
32
|
|
@@ -72,8 +72,7 @@ module Authenticate
|
|
72
72
|
|
73
73
|
# If we already have an encrypted password and it's not changing, skip the validation.
|
74
74
|
def skip_password_validation?
|
75
|
-
|
76
|
-
false
|
75
|
+
encrypted_password.present? && !password_changing
|
77
76
|
end
|
78
77
|
|
79
78
|
end
|
@@ -25,7 +25,7 @@ module Authenticate
|
|
25
25
|
module Email
|
26
26
|
extend ActiveSupport::Concern
|
27
27
|
|
28
|
-
def self.required_fields(
|
28
|
+
def self.required_fields(_klass)
|
29
29
|
[:email]
|
30
30
|
end
|
31
31
|
|
@@ -41,6 +41,7 @@ module Authenticate
|
|
41
41
|
module ClassMethods
|
42
42
|
|
43
43
|
def credentials(params)
|
44
|
+
return [] if params.nil? || params[:session].nil?
|
44
45
|
[params[:session][:email], params[:session][:password]]
|
45
46
|
end
|
46
47
|
|
@@ -51,11 +52,7 @@ module Authenticate
|
|
51
52
|
|
52
53
|
def find_by_credentials(credentials)
|
53
54
|
email = credentials[0]
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
def normalize_email(email)
|
58
|
-
email.to_s.downcase.gsub(/\s+/, '')
|
55
|
+
find_by_normalized_email(email)
|
59
56
|
end
|
60
57
|
|
61
58
|
end
|
@@ -29,7 +29,7 @@ module Authenticate
|
|
29
29
|
module Timeoutable
|
30
30
|
extend ActiveSupport::Concern
|
31
31
|
|
32
|
-
def self.required_fields(
|
32
|
+
def self.required_fields(_klass)
|
33
33
|
[:last_access_at]
|
34
34
|
end
|
35
35
|
|
@@ -45,6 +45,6 @@ module Authenticate
|
|
45
45
|
def timeout_in
|
46
46
|
Authenticate.configuration.timeout_in
|
47
47
|
end
|
48
|
-
|
48
|
+
end
|
49
49
|
end
|
50
50
|
end
|
data/lib/authenticate/session.rb
CHANGED
@@ -21,8 +21,6 @@ module Authenticate
|
|
21
21
|
def login(user, &block)
|
22
22
|
debug 'session.login()'
|
23
23
|
@current_user = user
|
24
|
-
debug "session.login @current_user: #{@current_user.inspect}"
|
25
|
-
# todo extract token gen to two different strategies
|
26
24
|
@current_user.generate_session_token if user.present?
|
27
25
|
|
28
26
|
message = catch(:failure) do
|
@@ -44,7 +42,6 @@ module Authenticate
|
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
47
|
-
|
48
45
|
# Get the user represented by this session.
|
49
46
|
#
|
50
47
|
# @return [User]
|
@@ -64,7 +61,6 @@ module Authenticate
|
|
64
61
|
current_user.present?
|
65
62
|
end
|
66
63
|
|
67
|
-
|
68
64
|
# Invalidate the session token, unset the current user and remove the cookie.
|
69
65
|
#
|
70
66
|
# @return [void]
|
data/lib/authenticate/user.rb
CHANGED
@@ -49,6 +49,18 @@ module Authenticate
|
|
49
49
|
save validate: false
|
50
50
|
end
|
51
51
|
|
52
|
+
module ClassMethods
|
53
|
+
|
54
|
+
def normalize_email(email)
|
55
|
+
email.to_s.downcase.gsub(/\s+/, '')
|
56
|
+
end
|
57
|
+
|
58
|
+
# We need to find users by email even if they don't use email to log in
|
59
|
+
def find_by_normalized_email(email)
|
60
|
+
find_by_email normalize_email(email)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
52
64
|
|
53
65
|
end
|
54
66
|
end
|
data/lib/authenticate/version.rb
CHANGED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/controllers/controller_helpers'
|
3
|
+
|
4
|
+
describe Authenticate::PasswordsController, type: :controller do
|
5
|
+
it { is_expected.to be_a Authenticate::Controller }
|
6
|
+
|
7
|
+
describe 'get to #new' do
|
8
|
+
it 'renders the new form' do
|
9
|
+
get :new
|
10
|
+
expect(response).to be_success
|
11
|
+
expect(response).to render_template(:new)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'post to #create' do
|
16
|
+
context 'with email for an existing user' do
|
17
|
+
it 'generates a password_reset_token' do
|
18
|
+
user = create(:user)
|
19
|
+
post :create, password: { email: user.email.upcase }
|
20
|
+
expect(user.reload.password_reset_token).not_to be_nil
|
21
|
+
end
|
22
|
+
it 'sends a password reset email' do
|
23
|
+
ActionMailer::Base.deliveries.clear
|
24
|
+
user = create(:user)
|
25
|
+
post :create, password: { email: user.email }
|
26
|
+
email = ActionMailer::Base.deliveries.last
|
27
|
+
expect(email.subject).to match(/change your password/i)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
context 'with email that does not belong to an existing user' do
|
31
|
+
bad_email = 'bunk_email_address@non_existent_domain.com'
|
32
|
+
it 'does not send an email' do
|
33
|
+
ActionMailer::Base.deliveries.clear
|
34
|
+
post :create, password: { email: bad_email}
|
35
|
+
expect(ActionMailer::Base.deliveries).to be_empty
|
36
|
+
end
|
37
|
+
it 'always responds with redirect to avoid leaking user information' do
|
38
|
+
post :create, password: { email: bad_email }
|
39
|
+
expect(response).to be_redirect
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'get to #edit' do
|
45
|
+
context 'with a valid password_reset_token and timestamp' do
|
46
|
+
it 'renders password update form' do
|
47
|
+
user = create(:user, :with_password_reset_token_and_timestamp)
|
48
|
+
get :edit, id: user.id, token: user.password_reset_token
|
49
|
+
expect(response).to be_success
|
50
|
+
expect(response).to render_template(:edit)
|
51
|
+
expect(assigns(:user)).to eq user
|
52
|
+
end
|
53
|
+
end
|
54
|
+
context 'with a valid timestamp but invalid password_reset_token' do
|
55
|
+
it 'renders #new password form with notice' do
|
56
|
+
user = create(:user, :with_password_reset_token_and_timestamp)
|
57
|
+
get :edit, id: user.id, token: 'bad token'
|
58
|
+
expect(response).to be_success
|
59
|
+
expect(response).to render_template(:new)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
context 'with a valid password_reset_token but invalid timestamp' do
|
63
|
+
it 'renders #new password form with notice' do
|
64
|
+
user = create(:user, :with_password_reset_token_and_timestamp, password_reset_sent_at: 2.years.ago)
|
65
|
+
get :edit, id: user.id, token: user.password_reset_token
|
66
|
+
expect(response).to be_redirect
|
67
|
+
expect(flash[:notice]).to match /password change request has expired/
|
68
|
+
end
|
69
|
+
end
|
70
|
+
context 'with a blank password_reset_token' do
|
71
|
+
it 'renders #new password form with notice' do
|
72
|
+
user = create(:user)
|
73
|
+
get :edit, id: user.id, token: nil
|
74
|
+
expect(response).to be_success
|
75
|
+
expect(response).to render_template(:new)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'put to #update' do
|
81
|
+
context 'with valid password_reset_token and new password' do
|
82
|
+
it 'updates the user password' do
|
83
|
+
user = create(:user, :with_password_reset_token_and_timestamp)
|
84
|
+
old_encrypted_password = user.encrypted_password
|
85
|
+
put :update, update_params(user, new_password: 'new_password')
|
86
|
+
expect(user.reload.encrypted_password).not_to eq old_encrypted_password
|
87
|
+
end
|
88
|
+
it 'signs in the user' do
|
89
|
+
user = create(:user, :with_password_reset_token_and_timestamp)
|
90
|
+
put :update, update_params(user, new_password: 'new_password')
|
91
|
+
expect(cookies[:authenticate_session_token]).to be_present
|
92
|
+
expect(cookies[:authenticate_session_token]).to eq user.reload.session_token
|
93
|
+
end
|
94
|
+
it 'redirects user' do
|
95
|
+
user = create(:user, :with_password_reset_token_and_timestamp)
|
96
|
+
put :update, update_params(user, new_password: 'new_password')
|
97
|
+
expect(response).to redirect_to(Authenticate.configuration.redirect_url)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
context 'with invalid new password' do
|
101
|
+
it 're-renders password edit form' do
|
102
|
+
user = create(:user, :with_password_reset_token_and_timestamp)
|
103
|
+
put :update, update_params(user, new_password: 'short')
|
104
|
+
expect(response).to render_template(:edit)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
def update_params(user, options = {})
|
111
|
+
new_password = options.fetch(:new_password)
|
112
|
+
{
|
113
|
+
id: user,
|
114
|
+
token: user.password_reset_token,
|
115
|
+
password_reset: { password: new_password }
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|