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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -4
  3. data/CHANGELOG.md +12 -0
  4. data/Gemfile +1 -0
  5. data/Gemfile.lock +21 -6
  6. data/app/controllers/authenticate/passwords_controller.rb +1 -1
  7. data/authenticate.gemspec +7 -3
  8. data/config/locales/authenticate.en.yml +1 -1
  9. data/gemfiles/rails42.gemfile +6 -1
  10. data/lib/authenticate/callbacks/brute_force.rb +3 -4
  11. data/lib/authenticate/configuration.rb +2 -2
  12. data/lib/authenticate/controller.rb +1 -2
  13. data/lib/authenticate/model/brute_force.rb +2 -2
  14. data/lib/authenticate/model/db_password.rb +2 -3
  15. data/lib/authenticate/model/email.rb +3 -6
  16. data/lib/authenticate/model/lifetimed.rb +1 -1
  17. data/lib/authenticate/model/password_reset.rb +1 -1
  18. data/lib/authenticate/model/timeoutable.rb +2 -2
  19. data/lib/authenticate/model/trackable.rb +1 -1
  20. data/lib/authenticate/model/username.rb +1 -1
  21. data/lib/authenticate/session.rb +0 -4
  22. data/lib/authenticate/user.rb +12 -0
  23. data/lib/authenticate/version.rb +1 -1
  24. data/spec/controllers/passwords_controller_spec.rb +119 -0
  25. data/spec/controllers/secured_controller_spec.rb +70 -0
  26. data/spec/controllers/sessions_controller_spec.rb +86 -0
  27. data/spec/controllers/users_controller_spec.rb +82 -0
  28. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  29. data/spec/dummy/app/controllers/welcome_controller.rb +4 -0
  30. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  31. data/spec/dummy/app/views/welcome/index.html.erb +4 -0
  32. data/spec/dummy/config/application.rb +2 -0
  33. data/spec/dummy/config/environments/production.rb +12 -0
  34. data/spec/dummy/config/initializers/authenticate.rb +4 -11
  35. data/spec/dummy/config/routes.rb +3 -0
  36. data/spec/dummy/db/test.sqlite3 +0 -0
  37. data/spec/factories/users.rb +2 -4
  38. data/spec/features/brute_force_spec.rb +49 -0
  39. data/spec/features/max_session_lifetime_spec.rb +30 -0
  40. data/spec/features/password_reset_spec.rb +69 -0
  41. data/spec/features/password_update_spec.rb +41 -0
  42. data/spec/features/sign_in_spec.rb +29 -0
  43. data/spec/features/sign_out_spec.rb +22 -0
  44. data/spec/features/sign_up_spec.rb +42 -0
  45. data/spec/features/timeoutable_spec.rb +30 -0
  46. data/spec/model/brute_force_spec.rb +26 -29
  47. data/spec/model/configuration_spec.rb +61 -0
  48. data/spec/model/db_password_spec.rb +8 -9
  49. data/spec/model/email_spec.rb +0 -1
  50. data/spec/model/lifetimed_spec.rb +6 -18
  51. data/spec/model/password_reset_spec.rb +2 -9
  52. data/spec/model/session_spec.rb +16 -23
  53. data/spec/model/timeoutable_spec.rb +8 -7
  54. data/spec/model/trackable_spec.rb +0 -1
  55. data/spec/model/user_spec.rb +1 -2
  56. data/spec/spec_helper.rb +33 -131
  57. data/spec/support/controllers/controller_helpers.rb +24 -0
  58. data/spec/support/features/feature_helpers.rb +36 -0
  59. metadata +80 -8
  60. data/spec/configuration_spec.rb +0 -60
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+ require 'support/features/feature_helpers'
3
+
4
+ feature 'visitor requests password reset' do
5
+ before(:each) do
6
+ ActionMailer::Base.deliveries.clear
7
+ end
8
+
9
+ scenario 'navigates to Forgot Password page' do
10
+ visit sign_in_path
11
+ click_link 'Forgot Password'
12
+ expect(current_path).to eq new_password_path
13
+ end
14
+
15
+ scenario 'uses valid email' do
16
+ user = create(:user)
17
+ request_password_reset_for user.email
18
+
19
+ expect_password_change_request_success_message
20
+ expect_user_to_have_password_reset_attributes user
21
+ expect_password_reset_email_for user
22
+ end
23
+
24
+ scenario 'with a non-user-account email' do
25
+ request_password_reset_for 'fake.email@example.com'
26
+
27
+ expect_password_change_request_success_message
28
+ expect_mailer_to_have_no_deliveries
29
+ end
30
+
31
+ scenario 'with invalid email' do
32
+ request_password_reset_for 'not_an_email_address'
33
+
34
+ expect_password_change_request_success_message
35
+ expect_mailer_to_have_no_deliveries
36
+ end
37
+ end
38
+
39
+
40
+ def request_password_reset_for email
41
+ visit new_password_path
42
+ fill_in 'password_email', with: email
43
+ click_button 'Reset password'
44
+ end
45
+
46
+ def expect_password_change_request_success_message
47
+ expect(page).to have_content I18n.t('passwords.create.description')
48
+ end
49
+
50
+ def expect_user_to_have_password_reset_attributes user
51
+ user.reload
52
+ expect(user.password_reset_token).not_to be_blank
53
+ expect(user.password_reset_sent_at).not_to be_blank
54
+ end
55
+
56
+ def expect_password_reset_email_for user
57
+ recipient = user.email
58
+ token = user.password_reset_token
59
+ expect(ActionMailer::Base.deliveries).not_to be_empty
60
+ ActionMailer::Base.deliveries.any? do |email|
61
+ email.to == [recipient] &&
62
+ email.html_part.body =~ /#{token}/ &&
63
+ email.text_part.body =~ /#{token}/
64
+ end
65
+ end
66
+
67
+ def expect_mailer_to_have_no_deliveries
68
+ expect(ActionMailer::Base.deliveries).to be_empty
69
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'support/features/feature_helpers'
3
+
4
+ feature 'visitor updates password' do
5
+ before(:each) do
6
+ @user = create(:user, :with_password_reset_token_and_timestamp)
7
+ end
8
+
9
+ scenario 'with a valid password' do
10
+ update_password @user, 'newpassword'
11
+
12
+ expect_user_to_be_signed_in
13
+ end
14
+
15
+ scenario 'with a blank password' do
16
+ update_password @user, ''
17
+
18
+ expect(page).to have_content I18n.t('flashes.failure_after_update')
19
+ expect_user_to_be_signed_out
20
+ end
21
+
22
+ scenario 'signs in with new password' do
23
+ update_password @user, 'newpassword'
24
+
25
+ sign_out
26
+ sign_in_with @user.email, 'newpassword'
27
+ expect_user_to_be_signed_in
28
+ end
29
+ end
30
+
31
+
32
+ def update_password(user, password)
33
+ visit_password_reset_page_for user
34
+ fill_in 'password_reset_password', with: password
35
+ click_button 'Save this password'
36
+ end
37
+
38
+ def visit_password_reset_page_for(user)
39
+ visit edit_users_password_path(id: user, token: user.password_reset_token)
40
+ end
41
+
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ require 'support/features/feature_helpers'
3
+
4
+ feature 'visitor signs in' do
5
+ scenario 'with valid email and password' do
6
+ user = create(:user)
7
+ sign_in_with user.email, user.password
8
+ expect_user_to_be_signed_in
9
+ end
10
+
11
+ scenario 'with valid mixed-case email and password' do
12
+ user = create(:user, email: 'test.user@example.com')
13
+ sign_in_with 'Test.USER@example.com', user.password
14
+ expect_user_to_be_signed_in
15
+ end
16
+
17
+ scenario 'with invalid password' do
18
+ user = create(:user)
19
+ sign_in_with user.email, 'invalid password'
20
+ expect_page_to_display_sign_in_error
21
+ expect_user_to_be_signed_out
22
+ end
23
+
24
+ scenario 'with invalid email' do
25
+ sign_in_with 'unknown@example.com', 'password'
26
+ expect_page_to_display_sign_in_error
27
+ expect_user_to_be_signed_out
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require 'support/features/feature_helpers'
3
+
4
+ feature 'visitor signs out' do
5
+ before do
6
+ @user = create(:user)
7
+ end
8
+
9
+ scenario 'sign in and sign out' do
10
+ sign_in_with(@user.email, @user.password)
11
+ sign_out
12
+ expect_user_to_be_signed_out
13
+ end
14
+
15
+ scenario 'sign out and sign out again' do
16
+ sign_in_with(@user.email, @user.password)
17
+ visit sign_out_path
18
+ visit sign_out_path
19
+ expect_user_to_be_signed_out
20
+ end
21
+
22
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'support/features/feature_helpers'
3
+
4
+ feature 'visitor signs up' do
5
+ scenario 'navigates to sign up page' do
6
+ visit sign_in_path
7
+ click_link 'Sign Up'
8
+ expect_sign_up_page
9
+ end
10
+
11
+ scenario 'signs up with valid email and password' do
12
+ sign_up_with 'valid@example.com', 'password'
13
+ expect_user_to_be_signed_in
14
+ end
15
+
16
+ scenario 'signs up with invalid email' do
17
+ sign_up_with 'bad_email', 'password'
18
+ expect_user_to_be_signed_out
19
+ end
20
+
21
+ scenario 'signs up with invalid short password' do
22
+ sign_up_with 'bad_email', '111'
23
+ expect_user_to_be_signed_out
24
+ end
25
+
26
+ scenario 'signs up with blank password' do
27
+ sign_up_with 'bad_email', ''
28
+ expect_user_to_be_signed_out
29
+ end
30
+ end
31
+
32
+
33
+ def expect_sign_up_page
34
+ expect(current_path).to eq sign_up_path
35
+ end
36
+
37
+ def sign_up_with(email, password)
38
+ visit sign_up_path
39
+ fill_in 'user_email', with: email
40
+ fill_in 'user_password', with: password
41
+ click_button 'Sign up'
42
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'support/features/feature_helpers'
3
+
4
+ feature 'visitor session time' do
5
+ before do
6
+ @user = create(:user)
7
+ end
8
+
9
+ scenario 'visitor logs in, subsequent click within timeout' do
10
+ sign_in_with @user.email, @user.password
11
+ expect_user_to_be_signed_in
12
+
13
+ Timecop.travel 10.minutes do
14
+ visit root_path
15
+ expect_user_to_be_signed_in
16
+ end
17
+ end
18
+
19
+ scenario 'visitor logs in, subsequent click after session times out' do
20
+ sign_in_with @user.email, @user.password
21
+ expect_user_to_be_signed_in
22
+
23
+ Timecop.travel 21.minutes do
24
+ visit root_path
25
+ expect(current_path).to eq sign_in_path
26
+ expect_user_to_be_signed_out
27
+ end
28
+ end
29
+
30
+ end
@@ -3,61 +3,58 @@ require 'authenticate/model/brute_force'
3
3
 
4
4
 
5
5
  describe Authenticate::Model::BruteForce do
6
- before {
7
- Authenticate.configure do |config|
8
- config.max_consecutive_bad_logins_allowed = 2
9
- config.bad_login_lockout_period = 2.minutes
10
- end
11
- }
6
+ before(:each) do
7
+ @user = create(:user)
8
+ end
9
+
10
+ it 'responds to locked?' do
11
+ expect(@user).to respond_to :locked?
12
+ end
12
13
 
13
14
  it 'knows when it is locked' do
14
- user = User.new
15
- expect(user.locked?).to be_falsey
16
- user.lock!
17
- expect(user.locked?).to be_truthy
15
+ expect(@user.locked?).to be_falsey
16
+ @user.lock!
17
+ expect(@user.locked?).to be_truthy
18
18
  end
19
19
 
20
20
  context '#register_failed_login!' do
21
21
  it 'locks when failed login count reaches max' do
22
- user = User.new
23
- user.register_failed_login!
24
- user.register_failed_login!
25
- expect(user.locked?).to be_truthy
22
+ @user.register_failed_login!
23
+ @user.register_failed_login!
24
+ @user.register_failed_login!
25
+ expect(@user.locked?).to be_truthy
26
26
  end
27
27
 
28
28
  it 'sets lockout period' do
29
- user = User.new
30
- user.register_failed_login!
31
- user.register_failed_login!
32
- expect(user.lock_expires_at).to_not be_nil
29
+ @user.register_failed_login!
30
+ @user.register_failed_login!
31
+ @user.register_failed_login!
32
+ expect(@user.lock_expires_at).to_not be_nil
33
33
  end
34
34
  end
35
35
 
36
36
  context '#lock!' do
37
37
  it 'before lock, locked_expires_at is nil' do
38
- user = User.new
39
- expect(user.lock_expires_at).to be_nil
38
+ expect(@user.lock_expires_at).to be_nil
40
39
  end
41
40
 
42
41
  it 'sets locked_expires_at' do
43
- user = User.new
44
- user.lock!
45
- expect(user.lock_expires_at).to_not be_nil
46
- expect(user.lock_expires_at).to be_utc
42
+ @user.lock!
43
+ expect(@user.lock_expires_at).to_not be_nil
44
+ expect(@user.lock_expires_at).to be_utc
47
45
  end
48
46
  end
49
47
 
50
48
  context '#unlock!' do
51
- let(:user) { User.new }
52
49
  before(:each) {
53
- user.lock!
54
- user.unlock!
50
+ @user.lock!
51
+ @user.unlock!
55
52
  }
56
53
  it 'zeros failed_logins_count' do
57
- expect(user.failed_logins_count).to be(0)
54
+ expect(@user.failed_logins_count).to be(0)
58
55
  end
59
56
  it 'nils lock_expires_at' do
60
- expect(user.lock_expires_at).to be_nil
57
+ expect(@user.lock_expires_at).to be_nil
61
58
  end
62
59
  end
63
60
  end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'authenticate/configuration'
3
+
4
+ describe Authenticate::Configuration do
5
+
6
+ context 'user model' do
7
+ module Gug
8
+ class Profile
9
+ extend ActiveModel::Naming
10
+ end
11
+ end
12
+
13
+ before(:each) do
14
+ @conf = Authenticate::Configuration.new
15
+ @conf.user_model = 'Gug::Profile'
16
+ end
17
+
18
+ it 'gets a class for a user model' do
19
+ expect(@conf.user_model_class).to be(Gug::Profile)
20
+ end
21
+
22
+ it 'get a route key for a user model' do
23
+ expect(@conf.user_model_route_key).to eq('gug_profiles')
24
+ end
25
+
26
+ it 'get a param key for a user model' do
27
+ expect(@conf.user_model_param_key).to eq('gug_profile')
28
+ end
29
+
30
+ describe '#authentication_strategy' do
31
+ context 'with no strategy set' do
32
+ it 'defaults to email' do
33
+ expect(@conf.authentication_strategy).to eq :email
34
+ end
35
+ it 'includes email in modules' do
36
+ expect(@conf.modules).to include :email
37
+ end
38
+ it 'does not include username in modules' do
39
+ expect(@conf.modules).to_not include :username
40
+ end
41
+ end
42
+
43
+ context 'with strategy set to username' do
44
+ before do
45
+ @conf.authentication_strategy = :username
46
+ end
47
+ it 'includes username in modules' do
48
+ expect(@conf.modules).to include :username
49
+ end
50
+ it 'does not include email in modules' do
51
+ expect(@conf.modules).to_not include :email
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+
60
+
61
+ end
@@ -4,7 +4,6 @@ require 'authenticate/model/db_password'
4
4
 
5
5
  describe Authenticate::Model::DbPassword do
6
6
  describe 'Passwords' do
7
-
8
7
  context '#password_match?' do
9
8
  subject { create(:user, password: 'password') }
10
9
 
@@ -26,12 +25,6 @@ describe Authenticate::Model::DbPassword do
26
25
  end
27
26
 
28
27
  describe 'Validations' do
29
- before(:all) {
30
- Authenticate.configure do |config|
31
- config.password_length = 8..128
32
- end
33
- }
34
-
35
28
  context 'on a new user' do
36
29
  it 'should not be valid without a password' do
37
30
  user = build(:user, :without_password)
@@ -39,12 +32,16 @@ describe Authenticate::Model::DbPassword do
39
32
  end
40
33
 
41
34
  it 'should be not be valid with a short password' do
42
- user = build(:user, password: 'short')
35
+ user = build(:user)
36
+ user.password = 'short'
37
+ user.password_changing = true
43
38
  expect(user).to_not be_valid
44
39
  end
45
40
 
46
41
  it 'is valid with a long password' do
47
- user = build(:user, password: 'thisisalongpassword')
42
+ user = build(:user)
43
+ user.password = 'thisisalongpassword'
44
+ user.password_changing = true
48
45
  expect(user).to be_valid
49
46
  end
50
47
  end
@@ -56,11 +53,13 @@ describe Authenticate::Model::DbPassword do
56
53
 
57
54
  it 'should not be valid with an empty password' do
58
55
  subject.password = ''
56
+ subject.password_changing = true
59
57
  expect(subject).to_not be_valid
60
58
  end
61
59
 
62
60
  it 'should be valid with a new (valid) password' do
63
61
  subject.password = 'new password'
62
+ subject.password_changing = true
64
63
  expect(subject).to be_valid
65
64
  end
66
65
  end