authenticate 0.3.1 → 0.3.2

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 (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
-