authenticate 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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