authenticate 0.2.3 → 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/.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
|