authenticate 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +27 -0
  3. data/CHANGELOG.md +6 -0
  4. data/CONTRIBUTING.md +59 -0
  5. data/Gemfile +0 -1
  6. data/Gemfile.lock +11 -11
  7. data/README.md +37 -4
  8. data/Rakefile +2 -4
  9. data/app/controllers/authenticate/passwords_controller.rb +3 -3
  10. data/app/controllers/authenticate/sessions_controller.rb +4 -4
  11. data/app/controllers/authenticate/users_controller.rb +5 -7
  12. data/app/mailers/authenticate_mailer.rb +6 -8
  13. data/authenticate.gemspec +8 -9
  14. data/lib/authenticate.rb +1 -1
  15. data/lib/authenticate/callbacks/authenticatable.rb +1 -2
  16. data/lib/authenticate/callbacks/brute_force.rb +1 -3
  17. data/lib/authenticate/callbacks/lifetimed.rb +2 -1
  18. data/lib/authenticate/callbacks/timeoutable.rb +3 -2
  19. data/lib/authenticate/callbacks/trackable.rb +1 -1
  20. data/lib/authenticate/configuration.rb +11 -7
  21. data/lib/authenticate/controller.rb +32 -23
  22. data/lib/authenticate/crypto/bcrypt.rb +3 -3
  23. data/lib/authenticate/debug.rb +7 -7
  24. data/lib/authenticate/engine.rb +4 -2
  25. data/lib/authenticate/lifecycle.rb +12 -22
  26. data/lib/authenticate/login_status.rb +4 -3
  27. data/lib/authenticate/model/brute_force.rb +4 -6
  28. data/lib/authenticate/model/db_password.rb +5 -14
  29. data/lib/authenticate/model/email.rb +7 -9
  30. data/lib/authenticate/model/lifetimed.rb +1 -2
  31. data/lib/authenticate/model/password_reset.rb +1 -3
  32. data/lib/authenticate/model/timeoutable.rb +14 -15
  33. data/lib/authenticate/model/trackable.rb +5 -4
  34. data/lib/authenticate/model/username.rb +3 -5
  35. data/lib/authenticate/modules.rb +37 -39
  36. data/lib/authenticate/session.rb +15 -23
  37. data/lib/authenticate/token.rb +3 -0
  38. data/lib/authenticate/user.rb +2 -6
  39. data/lib/authenticate/version.rb +1 -1
  40. data/lib/generators/authenticate/controllers/controllers_generator.rb +1 -2
  41. data/lib/generators/authenticate/helpers.rb +1 -2
  42. data/lib/generators/authenticate/install/install_generator.rb +31 -32
  43. data/lib/generators/authenticate/install/templates/authenticate.rb +0 -1
  44. data/lib/generators/authenticate/routes/routes_generator.rb +1 -2
  45. data/lib/generators/authenticate/views/USAGE +3 -2
  46. data/lib/generators/authenticate/views/views_generator.rb +1 -2
  47. data/spec/controllers/passwords_controller_spec.rb +5 -7
  48. data/spec/controllers/secured_controller_spec.rb +6 -6
  49. data/spec/controllers/sessions_controller_spec.rb +2 -2
  50. data/spec/controllers/users_controller_spec.rb +4 -4
  51. data/spec/features/brute_force_spec.rb +0 -2
  52. data/spec/features/max_session_lifetime_spec.rb +0 -1
  53. data/spec/features/password_reset_spec.rb +10 -19
  54. data/spec/features/password_update_spec.rb +0 -2
  55. data/spec/features/sign_out_spec.rb +0 -1
  56. data/spec/features/sign_up_spec.rb +0 -1
  57. data/spec/features/timeoutable_spec.rb +0 -1
  58. data/spec/model/brute_force_spec.rb +2 -3
  59. data/spec/model/configuration_spec.rb +2 -7
  60. data/spec/model/db_password_spec.rb +4 -6
  61. data/spec/model/email_spec.rb +1 -3
  62. data/spec/model/lifetimed_spec.rb +0 -3
  63. data/spec/model/modules_spec.rb +22 -0
  64. data/spec/model/password_reset_spec.rb +3 -10
  65. data/spec/model/session_spec.rb +4 -5
  66. data/spec/model/timeoutable_spec.rb +0 -1
  67. data/spec/model/token_spec.rb +1 -3
  68. data/spec/model/trackable_spec.rb +1 -2
  69. data/spec/model/user_spec.rb +0 -1
  70. data/spec/orm/active_record.rb +1 -1
  71. data/spec/spec_helper.rb +3 -11
  72. data/spec/support/controllers/controller_helpers.rb +1 -2
  73. data/spec/support/features/feature_helpers.rb +2 -4
  74. metadata +29 -26
@@ -1,3 +1,3 @@
1
1
  module Authenticate
2
- VERSION = '0.3.1'
2
+ VERSION = '0.3.2'.freeze
3
3
  end
@@ -6,7 +6,7 @@ require 'rails/generators/base'
6
6
  module Authenticate
7
7
  module Generators
8
8
  class ControllersGenerator < Rails::Generators::Base
9
- source_root File.expand_path("../../../../..", __FILE__)
9
+ source_root File.expand_path('../../../../..', __FILE__)
10
10
 
11
11
  def create_controllers
12
12
  directory 'app/controllers'
@@ -15,7 +15,6 @@ module Authenticate
15
15
  def create_mailers
16
16
  directory 'app/mailers'
17
17
  end
18
-
19
18
  end
20
19
  end
21
20
  end
@@ -21,7 +21,7 @@ module Authenticate
21
21
  end
22
22
 
23
23
  def namespaced?
24
- !!namespace
24
+ !namespace.nil?
25
25
  end
26
26
 
27
27
  def model_name
@@ -56,7 +56,6 @@ module Authenticate
56
56
  @class_path.map!(&:underscore)
57
57
  @file_name = @class_path.pop
58
58
  end
59
-
60
59
  end
61
60
  end
62
61
  end
@@ -9,8 +9,10 @@ module Authenticate
9
9
  include Authenticate::Generators::Helpers
10
10
 
11
11
  source_root File.expand_path('../templates', __FILE__)
12
-
13
- class_option :model, optional: true, type: :string, banner: 'model',
12
+ class_option :model,
13
+ optional: true,
14
+ type: :string,
15
+ banner: 'model',
14
16
  desc: "Specify the model class name if you will use anything other than 'User'"
15
17
 
16
18
  def initialize(*)
@@ -19,7 +21,7 @@ module Authenticate
19
21
  end
20
22
 
21
23
  def verify
22
- if options[:model] && !File.exists?(model_path)
24
+ if options[:model] && !File.exist?(model_path)
23
25
  puts "Exiting: the model class you specified, #{options[:model]}, is not found."
24
26
  exit 1
25
27
  end
@@ -49,9 +51,9 @@ module Authenticate
49
51
 
50
52
  def inject_into_application_controller
51
53
  inject_into_class(
52
- 'app/controllers/application_controller.rb',
53
- ApplicationController,
54
- " include Authenticate::Controller\n\n"
54
+ 'app/controllers/application_controller.rb',
55
+ ApplicationController,
56
+ " include Authenticate::Controller\n\n"
55
57
  )
56
58
  end
57
59
 
@@ -59,20 +61,19 @@ module Authenticate
59
61
  copy_file 'authenticate.rb', 'config/initializers/authenticate.rb'
60
62
  if options[:model]
61
63
  inject_into_file(
62
- 'config/initializers/authenticate.rb',
63
- " config.user_model = '#{options[:model]}' \n",
64
- after: "Authenticate.configure do |config|\n",
64
+ 'config/initializers/authenticate.rb',
65
+ " config.user_model = '#{options[:model]}' \n",
66
+ after: "Authenticate.configure do |config|\n"
65
67
  )
66
68
  end
67
69
  end
68
70
 
69
-
70
71
  private
71
72
 
72
73
  def create_new_users_migration
73
74
  config = {
74
- new_columns: new_columns,
75
- new_indexes: new_indexes
75
+ new_columns: new_columns,
76
+ new_indexes: new_indexes
76
77
  }
77
78
  copy_migration 'create_users.rb', config
78
79
  end
@@ -80,8 +81,8 @@ module Authenticate
80
81
  def create_add_columns_migration
81
82
  if migration_needed?
82
83
  config = {
83
- new_columns: new_columns,
84
- new_indexes: new_indexes
84
+ new_columns: new_columns,
85
+ new_indexes: new_indexes
85
86
  }
86
87
  copy_migration('add_authenticate_to_users.rb', config)
87
88
  end
@@ -90,9 +91,9 @@ module Authenticate
90
91
  def copy_migration(migration_name, config = {})
91
92
  unless migration_exists?(migration_name)
92
93
  migration_template(
93
- "db/migrate/#{migration_name}",
94
- "db/migrate/#{migration_name}",
95
- config
94
+ "db/migrate/#{migration_name}",
95
+ "db/migrate/#{migration_name}",
96
+ config
96
97
  )
97
98
  end
98
99
  end
@@ -103,23 +104,23 @@ module Authenticate
103
104
 
104
105
  def new_columns
105
106
  @new_columns ||= {
106
- email: 't.string :email',
107
- encrypted_password: 't.string :encrypted_password, limit: 128',
108
- session_token: 't.string :session_token, limit: 128',
109
-
110
- # trackable, lifetimed
111
- current_sign_in_at: 't.datetime :current_sign_in_at',
112
- current_sign_in_ip: 't.string :current_sign_in_ip, limit: 128',
113
- last_sign_in_at: 't.datetime :last_sign_in_at',
114
- last_sign_in_ip: 't.string :last_sign_in_ip, limit: 128',
115
- sign_in_count: 't.integer :sign_in_count'
107
+ email: 't.string :email',
108
+ encrypted_password: 't.string :encrypted_password, limit: 128',
109
+ session_token: 't.string :session_token, limit: 128',
110
+
111
+ # trackable, lifetimed
112
+ current_sign_in_at: 't.datetime :current_sign_in_at',
113
+ current_sign_in_ip: 't.string :current_sign_in_ip, limit: 128',
114
+ last_sign_in_at: 't.datetime :last_sign_in_at',
115
+ last_sign_in_ip: 't.string :last_sign_in_ip, limit: 128',
116
+ sign_in_count: 't.integer :sign_in_count'
116
117
  }.reject { |column| existing_users_columns.include?(column.to_s) }
117
118
  end
118
119
 
119
120
  def new_indexes
120
121
  @new_indexes ||= {
121
- index_users_on_email: "add_index :#{table_name}, :email",
122
- index_users_on_session_token: "add_index :#{table_name}, :session_token"
122
+ index_users_on_email: "add_index :#{table_name}, :email",
123
+ index_users_on_session_token: "add_index :#{table_name}, :session_token"
123
124
  }.reject { |index| existing_users_indexes.include?(index.to_s) }
124
125
  end
125
126
 
@@ -128,7 +129,7 @@ module Authenticate
128
129
  end
129
130
 
130
131
  def existing_migrations
131
- @existing_migrations ||= Dir.glob("db/migrate/*.rb").map do |file|
132
+ @existing_migrations ||= Dir.glob('db/migrate/*.rb').map do |file|
132
133
  migration_name_without_timestamp(file)
133
134
  end
134
135
  end
@@ -155,8 +156,6 @@ module Authenticate
155
156
  def self.next_migration_number(dir)
156
157
  ActiveRecord::Generators::Base.next_migration_number(dir)
157
158
  end
158
-
159
-
160
159
  end
161
160
  end
162
161
  end
@@ -1,5 +1,4 @@
1
1
  Authenticate.configure do |config|
2
-
3
2
  # config.user_model = 'User'
4
3
 
5
4
  # config.cookie_name = 'authenticate_session_token'
@@ -16,7 +16,7 @@ module Authenticate
16
16
  inject_into_file(
17
17
  'config/initializers/authenticate.rb',
18
18
  " config.routes = false \n",
19
- after: "Authenticate.configure do |config|\n",
19
+ after: "Authenticate.configure do |config|\n"
20
20
  )
21
21
  end
22
22
 
@@ -30,7 +30,6 @@ module Authenticate
30
30
  def routes_file_path
31
31
  File.expand_path(find_in_source_paths('routes.rb'))
32
32
  end
33
-
34
33
  end
35
34
  end
36
35
  end
@@ -1,6 +1,6 @@
1
1
  Description:
2
- Override the default authenticate views. This generator will copy all of the
3
- base authenticate views into your project.
2
+ Override the default authenticate views and locale file. This generator will copy all of the
3
+ base authenticate views and locale file into your project.
4
4
 
5
5
  Examples:
6
6
  rails generate authenticate:views
@@ -11,3 +11,4 @@ Examples:
11
11
  View: app/views/passwords/new.html.erb
12
12
  View: app/views/sessions/new.html.erb
13
13
  View: app/views/users/new.html.erb
14
+ Locale: config/locales/en.yml
@@ -6,7 +6,7 @@ require 'rails/generators/base'
6
6
  module Authenticate
7
7
  module Generators
8
8
  class ViewsGenerator < Rails::Generators::Base
9
- source_root File.expand_path("../../../../..", __FILE__)
9
+ source_root File.expand_path('../../../../..', __FILE__)
10
10
 
11
11
  def create_views
12
12
  directory 'app/views'
@@ -15,7 +15,6 @@ module Authenticate
15
15
  def create_locales
16
16
  directory 'config/locales'
17
17
  end
18
-
19
18
  end
20
19
  end
21
20
  end
@@ -31,7 +31,7 @@ describe Authenticate::PasswordsController, type: :controller do
31
31
  bad_email = 'bunk_email_address@non_existent_domain.com'
32
32
  it 'does not send an email' do
33
33
  ActionMailer::Base.deliveries.clear
34
- post :create, password: { email: bad_email}
34
+ post :create, password: { email: bad_email }
35
35
  expect(ActionMailer::Base.deliveries).to be_empty
36
36
  end
37
37
  it 'always responds with redirect to avoid leaking user information' do
@@ -64,7 +64,7 @@ describe Authenticate::PasswordsController, type: :controller do
64
64
  user = create(:user, :with_password_reset_token_and_timestamp, password_reset_sent_at: 2.years.ago)
65
65
  get :edit, id: user.id, token: user.password_reset_token
66
66
  expect(response).to be_redirect
67
- expect(flash[:notice]).to match /password change request has expired/
67
+ expect(flash[:notice]).to match(/password change request has expired/)
68
68
  end
69
69
  end
70
70
  context 'with a blank password_reset_token' do
@@ -104,16 +104,14 @@ describe Authenticate::PasswordsController, type: :controller do
104
104
  expect(response).to render_template(:edit)
105
105
  end
106
106
  end
107
-
108
107
  end
109
108
 
110
109
  def update_params(user, options = {})
111
110
  new_password = options.fetch(:new_password)
112
111
  {
113
- id: user,
114
- token: user.password_reset_token,
115
- password_reset: { password: new_password }
112
+ id: user,
113
+ token: user.password_reset_token,
114
+ password_reset: { password: new_password }
116
115
  }
117
116
  end
118
-
119
117
  end
@@ -6,18 +6,19 @@ RSpec::Matchers.define :deny_access do
6
6
  match do |controller|
7
7
  redirects_to_sign_in?(controller) && sets_flash?(controller)
8
8
  end
9
- def redirects_to_sign_in? controller
9
+
10
+ def redirects_to_sign_in?(controller)
10
11
  expect(controller).to redirect_to(controller.sign_in_url)
11
12
  end
12
- def sets_flash? controller
13
- controller.flash[:notice].match /sign in to continue/
13
+
14
+ def sets_flash?(controller)
15
+ controller.flash[:notice].match(/sign in to continue/)
14
16
  end
15
17
  end
16
18
 
17
-
19
+ # A dummy 'secured' controller to test
18
20
  class SecuredAppsController < ActionController::Base
19
21
  include Authenticate::Controller
20
-
21
22
  before_action :require_authentication, only: :show
22
23
 
23
24
  def new
@@ -29,7 +30,6 @@ class SecuredAppsController < ActionController::Base
29
30
  end
30
31
  end
31
32
 
32
-
33
33
  describe SecuredAppsController, type: :controller do
34
34
  before do
35
35
  Rails.application.routes.draw do
@@ -37,7 +37,7 @@ describe Authenticate::SessionsController, type: :controller do
37
37
  context 'with good password' do
38
38
  before do
39
39
  @user = create(:user)
40
- post :create, session:{ email: @user.email, password: @user.password }
40
+ post :create, session: { email: @user.email, password: @user.password }
41
41
  end
42
42
  it { is_expected.to respond_with 302 }
43
43
 
@@ -63,6 +63,7 @@ describe Authenticate::SessionsController, type: :controller do
63
63
 
64
64
  it { is_expected.to redirect_to sign_in_url }
65
65
  end
66
+
66
67
  context 'with a session cookie' do
67
68
  before do
68
69
  @user = create(:user, session_token: 'old-session-token')
@@ -82,5 +83,4 @@ describe Authenticate::SessionsController, type: :controller do
82
83
  end
83
84
  end
84
85
  end
85
-
86
86
  end
@@ -26,6 +26,7 @@ describe Authenticate::UsersController, type: :controller do
26
26
  end
27
27
  end
28
28
  end
29
+
29
30
  describe 'post to #create' do
30
31
  context 'not signed in' do
31
32
  context 'with valid attributes' do
@@ -33,7 +34,7 @@ describe Authenticate::UsersController, type: :controller do
33
34
  subject { post :create, user: user_attributes }
34
35
 
35
36
  it 'creates user' do
36
- expect{ subject }.to change{ User.count }.by(1)
37
+ expect { subject }.to change { User.count }.by(1)
37
38
  end
38
39
 
39
40
  it 'assigned user' do
@@ -55,7 +56,7 @@ describe Authenticate::UsersController, type: :controller do
55
56
  subject { post :create, user: user_attributes }
56
57
 
57
58
  it 'creates user' do
58
- expect{ subject }.to change{ User.count }.by(1)
59
+ expect { subject }.to change { User.count }.by(1)
59
60
  end
60
61
 
61
62
  it 'assigned user' do
@@ -68,8 +69,8 @@ describe Authenticate::UsersController, type: :controller do
68
69
  expect(response).to redirect_to '/url_in_the_session'
69
70
  end
70
71
  end
71
-
72
72
  end
73
+
73
74
  context 'signed in' do
74
75
  it 'redirects to redirect_url' do
75
76
  sign_in
@@ -78,5 +79,4 @@ describe Authenticate::UsersController, type: :controller do
78
79
  end
79
80
  end
80
81
  end
81
-
82
82
  end
@@ -36,10 +36,8 @@ feature 'visitor has consecutive bad logins' do
36
36
  expect_user_to_be_signed_in
37
37
  end
38
38
  end
39
-
40
39
  end
41
40
 
42
-
43
41
  def expect_locked_account
44
42
  expect(page).to have_content 'Your account is locked'
45
43
  end
@@ -26,5 +26,4 @@ feature 'visitor has consecutive bad logins' do
26
26
  expect_user_to_be_signed_out
27
27
  end
28
28
  end
29
-
30
29
  end
@@ -36,8 +36,7 @@ feature 'visitor requests password reset' do
36
36
  end
37
37
  end
38
38
 
39
-
40
- def request_password_reset_for email
39
+ def request_password_reset_for(email)
41
40
  visit new_password_path
42
41
  fill_in 'password_email', with: email
43
42
  click_button 'Reset password'
@@ -47,20 +46,18 @@ def expect_password_change_request_success_message
47
46
  expect(page).to have_content I18n.t('passwords.create.description')
48
47
  end
49
48
 
50
- def expect_user_to_have_password_reset_attributes user
49
+ def expect_user_to_have_password_reset_attributes(user)
51
50
  user.reload
52
51
  expect(user.password_reset_token).not_to be_blank
53
52
  expect(user.password_reset_sent_at).not_to be_blank
54
53
  end
55
54
 
56
- def expect_password_reset_email_for user
57
- recipient = user.email
58
- token = user.password_reset_token
55
+ def expect_password_reset_email_for(user)
59
56
  expect(ActionMailer::Base.deliveries).not_to be_empty
60
57
  ActionMailer::Base.deliveries.any? do |email|
61
- email.to == [recipient] &&
62
- email.html_part.body =~ /#{token}/ &&
63
- email.text_part.body =~ /#{token}/
58
+ email.to == [user.email] &&
59
+ email.html_part.body =~ /#{user.password_reset_token}/ &&
60
+ email.text_part.body =~ /#{user.password_reset_token}/
64
61
  end
65
62
  end
66
63
 
@@ -68,15 +65,11 @@ def expect_mailer_to_have_no_deliveries
68
65
  expect(ActionMailer::Base.deliveries).to be_empty
69
66
  end
70
67
 
71
-
72
-
73
-
74
-
75
68
  feature 'visitor sets new password' do
76
69
  scenario 'requests password change' do
77
70
  user = given_user_with_password_reset_token
78
71
  visit_password_update_page_for user
79
- request_password_change_for user
72
+ request_password_change
80
73
  expect_password_is_changed_for user
81
74
  expect_redirect_to_root
82
75
  end
@@ -88,7 +81,6 @@ feature 'visitor sets new password' do
88
81
  end
89
82
  end
90
83
 
91
-
92
84
  def given_user_with_fake_password_reset_token
93
85
  user = create :user
94
86
  user.password_reset_token = 'big_fake_token'
@@ -99,16 +91,16 @@ def given_user_with_password_reset_token
99
91
  create :user, :with_password_reset_token_and_timestamp
100
92
  end
101
93
 
102
- def visit_password_update_page_for user
94
+ def visit_password_update_page_for(user)
103
95
  visit edit_users_password_path(user.id, token: user.password_reset_token)
104
96
  end
105
97
 
106
- def request_password_change_for user
98
+ def request_password_change
107
99
  fill_in 'password_reset_password', with: 'new_dumb_password'
108
100
  click_button 'Save this password'
109
101
  end
110
102
 
111
- def expect_password_is_changed_for user
103
+ def expect_password_is_changed_for(user)
112
104
  old_encrypted_password = user.encrypted_password
113
105
  expect(user.reload.encrypted_password).to_not eq old_encrypted_password
114
106
  end
@@ -120,4 +112,3 @@ end
120
112
  def expect_failure_flash
121
113
  expect(page).to have_content 'Please double check the URL or try submitting the form again.'
122
114
  end
123
-