authentication-zero 2.10.0 → 2.11.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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +15 -0
  3. data/CHANGELOG.md +6 -0
  4. data/Gemfile.lock +1 -1
  5. data/README.md +1 -1
  6. data/authentication-zero-api.md +0 -3
  7. data/lib/authentication_zero/version.rb +1 -1
  8. data/lib/generators/authentication/authentication_generator.rb +18 -13
  9. data/lib/generators/authentication/templates/controllers/api/application_controller.rb.tt +3 -2
  10. data/lib/generators/authentication/templates/controllers/api/identity/emails_controller.rb.tt +3 -2
  11. data/lib/generators/authentication/templates/controllers/api/sessions/sudos_controller.rb.tt +1 -1
  12. data/lib/generators/authentication/templates/controllers/html/application_controller.rb.tt +3 -2
  13. data/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt +3 -2
  14. data/lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt +1 -1
  15. data/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt +13 -0
  16. data/lib/generators/authentication/templates/controllers/html/two_factor_authentication/totps_controller.rb.tt +3 -2
  17. data/lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt +5 -0
  18. data/lib/generators/authentication/templates/erb/two_factor_authentication/totps/new.html.erb.tt +5 -0
  19. data/lib/generators/authentication/templates/migrations/create_sessions_migration.rb.tt +0 -3
  20. data/lib/generators/authentication/templates/models/session.rb.tt +8 -1
  21. data/lib/generators/authentication/templates/test_unit/application_system_test_case.rb.tt +1 -1
  22. data/lib/generators/authentication/templates/test_unit/controllers/api/identity/email_verifications_controller_test.rb.tt +8 -4
  23. data/lib/generators/authentication/templates/test_unit/controllers/api/identity/emails_controller_test.rb.tt +9 -7
  24. data/lib/generators/authentication/templates/test_unit/controllers/api/identity/password_resets_controller_test.rb.tt +0 -3
  25. data/lib/generators/authentication/templates/test_unit/controllers/api/passwords_controller_test.rb.tt +6 -2
  26. data/lib/generators/authentication/templates/test_unit/controllers/api/sessions_controller_test.rb.tt +7 -3
  27. data/lib/generators/authentication/templates/test_unit/controllers/html/identity/emails_controller_test.rb.tt +5 -12
  28. data/lib/generators/authentication/templates/test_unit/controllers/html/identity/password_resets_controller_test.rb.tt +0 -3
  29. data/lib/generators/authentication/templates/test_unit/system/identity/emails_test.rb.tt +1 -0
  30. data/lib/generators/authentication/templates/test_unit/system/identity/password_resets_test.rb.tt +0 -3
  31. metadata +3 -6
  32. data/lib/generators/authentication/templates/controllers/html/sessions_controller_two_factor.rb.tt +0 -41
  33. data/lib/generators/authentication/templates/test_unit/controllers/api/sessions/sudos_controller_test.rb.tt +0 -20
  34. data/lib/generators/authentication/templates/test_unit/controllers/html/sessions/sudos_controller_test.rb.tt +0 -22
  35. data/lib/generators/authentication/templates/test_unit/system/sessions/sudos_test.rb.tt +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c0ad4048d0c9df83173acebd1bbf770f519a7bb2a8b5b45c7e9af3c268904052
4
- data.tar.gz: 06a897ebfc48122cfaf151a49b7412ef13b098069eb3bc7a2a4c088bcc711c90
3
+ metadata.gz: 702b78645aff0919daf1e518101731363068e6aef74fac0591f3257b5bf6b7a3
4
+ data.tar.gz: d07d22eb48277537484ef5f5c1cd4fd78f65e65d739fb7031384e3a594248e3a
5
5
  SHA512:
6
- metadata.gz: fd26a42853d553616f366e1ddc57439ce91ba039f2cf25a5d3c80be48a6b0f0e7fee6816ead70587780ebc8a358e74e53543c0b6438eb39d7baf818aacc5191c
7
- data.tar.gz: 657bb45b7e9edfd6a036e9df9a2df41a2b2001199e65586d82548d7bd4ade28946be06ec3dbb28ba6fba100e275881c1a02dbb3de29b8546899393829b4cdc97
6
+ metadata.gz: 99224479fcc817abaeed4492a5a48d071e98e3e32fcea32ec56e77007031b186feb0978405e5ec5f90750cf434bc86a554df73dea88245aa6185f18a16d7d2e3
7
+ data.tar.gz: 344af675d6c106d41c3a34dc2fdd04d93ca6028c83bc5acda497791a70a220a7854455cb336345d00d9371b529b7581d64617f4c244b1c15182bf5a869ada997
data/.rubocop.yml ADDED
@@ -0,0 +1,15 @@
1
+ inherit_from: https://raw.githubusercontent.com/rails/rails/master/.rubocop.yml
2
+
3
+ Performance:
4
+ Exclude:
5
+ - 'test/**/*'
6
+
7
+ Style/FrozenStringLiteralComment:
8
+ Enabled: false
9
+
10
+ Style/StringLiterals:
11
+ Enabled: true
12
+ EnforcedStyle: double_quotes
13
+ Include:
14
+ - 'app/**/*'
15
+ - 'test/**/*'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## Authentication Zero 2.11.0 (March 27, 2022) ##
2
+
3
+ * Remove sudo from default generator
4
+ * Remove sudo_at from database
5
+ * Implement sudoable using redis
6
+
1
7
  ## Authentication Zero 2.10.0 (March 2, 2022) ##
2
8
 
3
9
  * Implement two-factor
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- authentication-zero (2.10.0)
4
+ authentication-zero (2.11.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -13,7 +13,7 @@ The purpose of authentication zero is to generate a pre-built authentication sys
13
13
  - Authentication by token (--api)
14
14
  - Two factor authentication (--two-factor)
15
15
  - Social Login with OmniAuth (--omniauthable)
16
- - Ask password before sensitive data changes, aka: sudo
16
+ - Ask password before sensitive data changes, aka: sudo (--sudoable)
17
17
  - Reset the user password and send reset instructions
18
18
  - Reset the user password only from verified emails
19
19
  - Lock sending reset password email after many attempts (--lockable)
@@ -78,7 +78,6 @@ This endpoint will return `201 Created` with the current JSON representation of
78
78
  "user_id": 1,
79
79
  "user_agent": "insomnia/2022.1.0",
80
80
  "ip_address": "127.0.0.1",
81
- "sudo_at": "2022-03-04T17:20:33.632Z",
82
81
  "created_at": "2022-03-04T17:20:33.632Z",
83
82
  "updated_at": "2022-03-04T17:20:33.632Z"
84
83
  },
@@ -87,7 +86,6 @@ This endpoint will return `201 Created` with the current JSON representation of
87
86
  "user_id": 1,
88
87
  "user_agent": "insomnia/2022.1.0",
89
88
  "ip_address": "127.0.0.1",
90
- "sudo_at": "2022-03-04T17:14:03.386Z",
91
89
  "created_at": "2022-03-04T17:14:03.386Z",
92
90
  "updated_at": "2022-03-04T17:14:03.386Z"
93
91
  }
@@ -106,7 +104,6 @@ This endpoint will return `201 Created` with the current JSON representation of
106
104
  "user_id": 1,
107
105
  "user_agent": "insomnia/2022.1.0",
108
106
  "ip_address": "127.0.0.1",
109
- "sudo_at": "2022-03-04T17:14:03.386Z",
110
107
  "created_at": "2022-03-04T17:14:03.386Z",
111
108
  "updated_at": "2022-03-04T17:14:03.386Z"
112
109
  }
@@ -1,3 +1,3 @@
1
1
  module AuthenticationZero
2
- VERSION = "2.10.0"
2
+ VERSION = "2.11.0"
3
3
  end
@@ -5,6 +5,7 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
5
5
 
6
6
  class_option :api, type: :boolean, desc: "Generates API authentication"
7
7
  class_option :pwned, type: :boolean, desc: "Add pwned password validation"
8
+ class_option :sudoable, type: :boolean, desc: "Add password request before sensitive data changes"
8
9
  class_option :lockable, type: :boolean, desc: "Add password reset locking"
9
10
  class_option :ratelimit, type: :boolean, desc: "Add request rate limiting"
10
11
  class_option :omniauthable, type: :boolean, desc: "Add social login support"
@@ -15,8 +16,8 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
15
16
 
16
17
  def add_gems
17
18
  uncomment_lines "Gemfile", /"bcrypt"/
18
- uncomment_lines "Gemfile", /"redis"/ if options.lockable?
19
- uncomment_lines "Gemfile", /"kredis"/ if options.lockable?
19
+ uncomment_lines "Gemfile", /"redis"/ if redis?
20
+ uncomment_lines "Gemfile", /"kredis"/ if redis?
20
21
 
21
22
  if options.pwned?
22
23
  gem "pwned", comment: "Use Pwned to check if a password has been found in any of the huge data breaches [https://github.com/philnash/pwned]"
@@ -38,7 +39,7 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
38
39
  end
39
40
 
40
41
  def create_configuration_files
41
- copy_file "config/redis/shared.yml", "config/redis/shared.yml" if options.lockable?
42
+ copy_file "config/redis/shared.yml", "config/redis/shared.yml" if redis?
42
43
  copy_file "config/initializers/omniauth.rb", "config/initializers/omniauth.rb" if omniauthable?
43
44
  end
44
45
 
@@ -72,17 +73,12 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
72
73
  def create_controllers
73
74
  template "controllers/#{format_folder}/application_controller.rb", "app/controllers/application_controller.rb", force: true
74
75
 
75
- if two_factor?
76
- directory "controllers/#{format_folder}/two_factor_authentication", "app/controllers/two_factor_authentication"
77
- template "controllers/#{format_folder}/sessions_controller_two_factor.rb", "app/controllers/sessions_controller.rb"
78
- else
79
- template "controllers/#{format_folder}/sessions_controller.rb", "app/controllers/sessions_controller.rb"
80
- end
81
-
82
76
  directory "controllers/#{format_folder}/identity", "app/controllers/identity"
77
+ directory "controllers/#{format_folder}/two_factor_authentication", "app/controllers/two_factor_authentication" if two_factor?
78
+ template "controllers/#{format_folder}/sessions_controller.rb", "app/controllers/sessions_controller.rb"
83
79
  template "controllers/#{format_folder}/passwords_controller.rb", "app/controllers/passwords_controller.rb"
84
80
  template "controllers/#{format_folder}/registrations_controller.rb", "app/controllers/registrations_controller.rb"
85
- template "controllers/#{format_folder}/sessions/sudos_controller.rb", "app/controllers/sessions/sudos_controller.rb"
81
+ template "controllers/#{format_folder}/sessions/sudos_controller.rb", "app/controllers/sessions/sudos_controller.rb" if options.sudoable?
86
82
  template "controllers/#{format_folder}/sessions/omniauth_controller.rb", "app/controllers/sessions/omniauth_controller.rb" if omniauthable?
87
83
  template "controllers/#{format_folder}/authentications/events_controller.rb", "app/controllers/authentications/events_controller.rb" if options.trackable?
88
84
  end
@@ -98,7 +94,12 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
98
94
  directory "erb/identity", "app/views/identity"
99
95
  directory "erb/passwords", "app/views/passwords"
100
96
  directory "erb/registrations", "app/views/registrations"
101
- directory "erb/sessions", "app/views/sessions"
97
+
98
+ template "erb/sessions/index.html.erb", "app/views/sessions/index.html.erb"
99
+ template "erb/sessions/new.html.erb", "app/views/sessions/new.html.erb"
100
+
101
+ directory "erb/sessions/sudos", "app/views/sessions/sudos" if options.sudoable?
102
+
102
103
  directory "erb/two_factor_authentication", "app/views/two_factor_authentication" if two_factor?
103
104
  directory "erb/authentications/events", "app/views/authentications/events" if options.trackable?
104
105
  end
@@ -127,7 +128,7 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
127
128
  route "resource :password_reset, only: [:new, :edit, :create, :update]", namespace: :identity
128
129
  route "resource :email_verification, only: [:edit, :create]", namespace: :identity
129
130
  route "resource :email, only: [:edit, :update]", namespace: :identity
130
- route "resource :sudo, only: [:new, :create]", namespace: :sessions
131
+ route "resource :sudo, only: [:new, :create]", namespace: :sessions if options.sudoable?
131
132
  route "resource :password, only: [:edit, :update]"
132
133
  route "resources :sessions, only: [:index, :show, :destroy]"
133
134
  route "post 'sign_up', to: 'registrations#create'"
@@ -155,4 +156,8 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
155
156
  def two_factor?
156
157
  options.two_factor? && !options.api?
157
158
  end
159
+
160
+ def redis?
161
+ options.lockable? || options.sudoable?
162
+ end
158
163
  end
@@ -3,12 +3,13 @@ class ApplicationController < ActionController::API
3
3
 
4
4
  before_action :set_current_request_details
5
5
  before_action :authenticate
6
-
6
+ <%- if options.sudoable? %>
7
7
  def require_sudo
8
- if Current.session.sudo_at < 30.minutes.ago
8
+ unless Current.session.sudo?
9
9
  render json: { error: "Enter your password to continue" }, status: :forbidden
10
10
  end
11
11
  end
12
+ <%- end -%>
12
13
 
13
14
  private
14
15
  def authenticate
@@ -1,9 +1,10 @@
1
1
  class Identity::EmailsController < ApplicationController
2
- before_action :require_sudo
3
2
  before_action :set_<%= singular_table_name %>
4
3
 
5
4
  def update
6
- if @<%= singular_table_name %>.update(<%= "#{singular_table_name}_params" %>)
5
+ if !@<%= singular_table_name %>.authenticate(params[:current_password])
6
+ render json: { error: "The password you entered is incorrect" }, status: :bad_request
7
+ elsif @<%= singular_table_name %>.update(<%= "#{singular_table_name}_params" %>)
7
8
  render json: @<%= singular_table_name %>
8
9
  else
9
10
  render json: @<%= singular_table_name %>.errors, status: :unprocessable_entity
@@ -3,7 +3,7 @@ class Sessions::SudosController < ApplicationController
3
3
  session = Current.session
4
4
 
5
5
  if session.<%= singular_table_name %>.authenticate(params[:password])
6
- session.update! sudo_at: Time.current
6
+ session.sudo.mark expires_in: 30.minutes
7
7
  else
8
8
  render json: { error: "The password you entered is incorrect" }, status: :bad_request
9
9
  end
@@ -1,12 +1,13 @@
1
1
  class ApplicationController < ActionController::Base
2
2
  before_action :set_current_request_details
3
3
  before_action :authenticate
4
-
4
+ <%- if options.sudoable? %>
5
5
  def require_sudo
6
- if Current.session.sudo_at < 30.minutes.ago
6
+ unless Current.session.sudo?
7
7
  redirect_to new_sessions_sudo_path(proceed_to_url: request.url)
8
8
  end
9
9
  end
10
+ <%- end -%>
10
11
 
11
12
  private
12
13
  def authenticate
@@ -1,12 +1,13 @@
1
1
  class Identity::EmailsController < ApplicationController
2
- before_action :require_sudo
3
2
  before_action :set_<%= singular_table_name %>
4
3
 
5
4
  def edit
6
5
  end
7
6
 
8
7
  def update
9
- if @<%= singular_table_name %>.update(<%= "#{singular_table_name}_params" %>)
8
+ if !@<%= singular_table_name %>.authenticate(params[:current_password])
9
+ redirect_to edit_identity_email_path, alert: "The password you entered is incorrect"
10
+ elsif @<%= singular_table_name %>.update(<%= "#{singular_table_name}_params" %>)
10
11
  redirect_to root_path, notice: "Your email has been changed"
11
12
  else
12
13
  render :edit, status: :unprocessable_entity
@@ -10,7 +10,7 @@ class Sessions::SudosController < ApplicationController
10
10
  <%- else -%>
11
11
  if session.<%= singular_table_name %>.authenticate(params[:password])
12
12
  <%- end -%>
13
- session.update!(sudo_at: Time.current); redirect_to(params[:proceed_to_url])
13
+ session.sudo.mark(expires_in: 30.minutes); redirect_to(params[:proceed_to_url])
14
14
  else
15
15
  redirect_to new_sessions_sudo_path(proceed_to_url: params[:proceed_to_url]), alert: "The password you entered is incorrect"
16
16
  end
@@ -15,10 +15,23 @@ class SessionsController < ApplicationController
15
15
  <%= singular_table_name %> = <%= class_name %>.find_by(email: params[:email])
16
16
 
17
17
  if <%= singular_table_name %> && <%= singular_table_name %>.authenticate(params[:password])
18
+ <%- if two_factor? -%>
19
+ if <%= singular_table_name %>.otp_secret
20
+ signed_id = <%= singular_table_name %>.signed_id(purpose: :authentication_challenge, expires_in: 20.minutes)
21
+
22
+ redirect_to new_two_factor_authentication_challenge_path(token: signed_id)
23
+ else
24
+ @session = <%= singular_table_name %>.sessions.create!
25
+ cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true }
26
+
27
+ redirect_to root_path, notice: "Signed in successfully"
28
+ end
29
+ <%- else -%>
18
30
  @session = <%= singular_table_name %>.sessions.create!
19
31
  cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true }
20
32
 
21
33
  redirect_to root_path, notice: "Signed in successfully"
34
+ <%- end -%>
22
35
  else
23
36
  redirect_to sign_in_path(email_hint: params[:email]), alert: "That email or password is incorrect"
24
37
  end
@@ -1,5 +1,4 @@
1
1
  class TwoFactorAuthentication::TotpsController < ApplicationController
2
- before_action :require_sudo
3
2
  before_action :set_<%= singular_table_name %>
4
3
  before_action :set_totp
5
4
 
@@ -8,7 +7,9 @@ class TwoFactorAuthentication::TotpsController < ApplicationController
8
7
  end
9
8
 
10
9
  def create
11
- if @totp.verify(params[:code], drift_behind: 15)
10
+ if !@<%= singular_table_name %>.authenticate(params[:current_password])
11
+ redirect_to two_factor_authentication_totp_path, alert: "The password you entered is incorrect"
12
+ elsif @totp.verify(params[:code], drift_behind: 15)
12
13
  @<%= singular_table_name %>.update! otp_secret: params[:secret]
13
14
  redirect_to root_path, notice: "2FA is enabled on your account"
14
15
  else
@@ -21,6 +21,11 @@
21
21
  </div>
22
22
  <%% end %>
23
23
 
24
+ <div>
25
+ <%%= form.label :current_password, style: "display: block" %>
26
+ <%%= form.password_field :current_password, required: true, autofocus: true, autocomplete: "current-password" %>
27
+ </div>
28
+
24
29
  <div>
25
30
  <%%= form.label :email, "New email", style: "display: block" %>
26
31
  <%%= form.email_field :email %>
@@ -17,6 +17,11 @@
17
17
  <%%= form_with(url: two_factor_authentication_totp_path) do |form| %>
18
18
  <%%= form.hidden_field :secret, value: @totp.secret %>
19
19
 
20
+ <div>
21
+ <%%= form.label :current_password, style: "display: block" %>
22
+ <%%= form.password_field :current_password, required: true, autofocus: true, autocomplete: "current-password" %>
23
+ </div>
24
+
20
25
  <div>
21
26
  <%%= form.label :code, "After scanning with your camera, the app will generate a six-digit code. Enter it here:", style: "display: block" %>
22
27
  <%%= form.text_field :code, autofocus: true, required: true, autocomplete: :off %>
@@ -2,12 +2,9 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
2
2
  def change
3
3
  create_table :sessions do |t|
4
4
  t.references :<%= singular_table_name %>, null: false, foreign_key: true
5
-
6
5
  t.string :user_agent
7
6
  t.string :ip_address
8
7
 
9
- t.datetime :sudo_at, null: false
10
-
11
8
  t.timestamps
12
9
  end
13
10
  end
@@ -1,11 +1,18 @@
1
1
  class Session < ApplicationRecord
2
2
  belongs_to :<%= singular_table_name %>
3
+ <%- if options.sudoable? %>
4
+ kredis_flag :sudo
5
+ <%- end -%>
3
6
 
4
7
  before_create do
5
8
  self.user_agent = Current.user_agent
6
9
  self.ip_address = Current.ip_address
7
- self.sudo_at = Time.current
8
10
  end
11
+ <%- if options.sudoable? %>
12
+ after_create_commit do
13
+ self.sudo.mark expires_in: 30.minutes
14
+ end
15
+ <%- end -%>
9
16
 
10
17
  after_create_commit do
11
18
  SessionMailer.with(session: self).signed_in_notification.deliver_later
@@ -10,6 +10,6 @@ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
10
10
  click_on "Sign in"
11
11
 
12
12
  assert_current_path root_url
13
- return <%= singular_table_name %>
13
+ <%= singular_table_name %>
14
14
  end
15
15
  end
@@ -9,21 +9,25 @@ class Identity::EmailVerificationsControllerTest < ActionDispatch::IntegrationTe
9
9
  @<%= singular_table_name %>.update! verified: false
10
10
  end
11
11
 
12
+ def default_headers
13
+ { "Authorization" => "Bearer #{@token}" }
14
+ end
15
+
12
16
  test "should send a verification email" do
13
17
  assert_enqueued_email_with IdentityMailer, :email_verify_confirmation, args: { <%= singular_table_name %>: @<%= singular_table_name %> } do
14
- post identity_email_verification_url, headers: { "Authorization" => "Bearer #{@token}" }
18
+ post identity_email_verification_url, headers: default_headers
15
19
  end
16
20
 
17
21
  assert_response :no_content
18
22
  end
19
23
 
20
24
  test "should verify email" do
21
- get edit_identity_email_verification_url, params: { token: @sid, email: @<%= singular_table_name %>.email }, headers: { "Authorization" => "Bearer #{@token}" }
25
+ get edit_identity_email_verification_url, params: { token: @sid, email: @<%= singular_table_name %>.email }, headers: default_headers
22
26
  assert_response :no_content
23
27
  end
24
28
 
25
29
  test "should not verify email with expired token" do
26
- get edit_identity_email_verification_url, params: { token: @sid_exp, email: @<%= singular_table_name %>.email }, headers: { "Authorization" => "Bearer #{@token}" }
30
+ get edit_identity_email_verification_url, params: { token: @sid_exp, email: @<%= singular_table_name %>.email }, headers: default_headers
27
31
 
28
32
  assert_response :bad_request
29
33
  assert_equal "That email verification link is invalid", response.parsed_body["error"]
@@ -32,7 +36,7 @@ class Identity::EmailVerificationsControllerTest < ActionDispatch::IntegrationTe
32
36
  test "should not verify email with previous token" do
33
37
  @<%= singular_table_name %>.update! email: "other_email@hey.com"
34
38
 
35
- get edit_identity_email_verification_url, params: { token: @sid, email: @<%= singular_table_name %>.email_previously_was }, headers: { "Authorization" => "Bearer #{@token}" }
39
+ get edit_identity_email_verification_url, params: { token: @sid, email: @<%= singular_table_name %>.email_previously_was }, headers: default_headers
36
40
 
37
41
  assert_response :bad_request
38
42
  assert_equal "That email verification link is invalid", response.parsed_body["error"]
@@ -5,17 +5,19 @@ class Identity::EmailsControllerTest < ActionDispatch::IntegrationTest
5
5
  @<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
6
  end
7
7
 
8
+ def default_headers
9
+ { "Authorization" => "Bearer #{@token}" }
10
+ end
11
+
8
12
  test "should update email" do
9
- patch identity_email_url, params: { email: "new_email@hey.com" }, headers: { "Authorization" => "Bearer #{@token}" }
13
+ patch identity_email_url, params: { email: "new_email@hey.com", current_password: "Secret1*3*5*" }, headers: default_headers
10
14
  assert_response :success
11
15
  end
12
16
 
13
- test "should not update email without sudo" do
14
- @<%= singular_table_name %>.sessions.last.update! sudo_at: 1.day.ago
15
-
16
- patch identity_email_url, params: { email: "new_email@hey.com" }, headers: { "Authorization" => "Bearer #{@token}" }
17
+ test "should not update email with wrong current password" do
18
+ patch identity_email_url, params: { email: "new_email@hey.com", current_password: "SecretWrong1*3" }, headers: default_headers
17
19
 
18
- assert_response :forbidden
19
- assert_equal "Enter your password to continue", response.parsed_body["error"]
20
+ assert_response :bad_request
21
+ assert_equal "The password you entered is incorrect", response.parsed_body["error"]
20
22
  end
21
23
  end
@@ -6,9 +6,6 @@ class Identity::PasswordResetsControllerTest < ActionDispatch::IntegrationTest
6
6
  @sid = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 20.minutes)
7
7
  @sid_exp = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 0.minutes)
8
8
  end
9
- <%- if options.lockable? %>
10
- teardown { Kredis.clear_all }
11
- <%- end -%>
12
9
 
13
10
  test "should send a password reset email" do
14
11
  assert_enqueued_email_with IdentityMailer, :password_reset_provision, args: { <%= singular_table_name %>: @<%= singular_table_name %> } do
@@ -5,13 +5,17 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
5
5
  @<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
6
  end
7
7
 
8
+ def default_headers
9
+ { "Authorization" => "Bearer #{@token}" }
10
+ end
11
+
8
12
  test "should update password" do
9
- patch password_url, params: { current_password: "Secret1*3*5*", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers: { "Authorization" => "Bearer #{@token}" }
13
+ patch password_url, params: { current_password: "Secret1*3*5*", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers: default_headers
10
14
  assert_response :success
11
15
  end
12
16
 
13
17
  test "should not update password with wrong current password" do
14
- patch password_url, params: { current_password: "SecretWrong1*3", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers: { "Authorization" => "Bearer #{@token}" }
18
+ patch password_url, params: { current_password: "SecretWrong1*3", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers: default_headers
15
19
 
16
20
  assert_response :bad_request
17
21
  assert_equal "The current password you entered is incorrect", response.parsed_body["error"]
@@ -5,13 +5,17 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
5
5
  @<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
6
  end
7
7
 
8
+ def default_headers
9
+ { "Authorization" => "Bearer #{@token}" }
10
+ end
11
+
8
12
  test "should get index" do
9
- get sessions_url, headers: { "Authorization" => "Bearer #{@token}" }
13
+ get sessions_url, headers: default_headers
10
14
  assert_response :success
11
15
  end
12
16
 
13
17
  test "should show session" do
14
- get session_url(@<%= singular_table_name %>.sessions.last), headers: { "Authorization" => "Bearer #{@token}" }
18
+ get session_url(@<%= singular_table_name %>.sessions.last), headers: default_headers
15
19
  assert_response :success
16
20
  end
17
21
 
@@ -28,7 +32,7 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
28
32
  end
29
33
 
30
34
  test "should sign out" do
31
- delete session_url(@<%= singular_table_name %>.sessions.last), headers: { "Authorization" => "Bearer #{@token}" }
35
+ delete session_url(@<%= singular_table_name %>.sessions.last), headers: default_headers
32
36
  assert_response :no_content
33
37
  end
34
38
  end
@@ -10,22 +10,15 @@ class Identity::EmailsControllerTest < ActionDispatch::IntegrationTest
10
10
  assert_response :success
11
11
  end
12
12
 
13
- test "should not get edit without sudo" do
14
- @<%= singular_table_name %>.sessions.last.update! sudo_at: 1.day.ago
15
-
16
- get edit_identity_email_url
17
- assert_redirected_to new_sessions_sudo_url(proceed_to_url: edit_identity_email_url)
18
- end
19
-
20
13
  test "should update email" do
21
- patch identity_email_url, params: { email: "new_email@hey.com" }
14
+ patch identity_email_url, params: { email: "new_email@hey.com", current_password: "Secret1*3*5*" }
22
15
  assert_redirected_to root_url
23
16
  end
24
17
 
25
- test "should not update email without sudo" do
26
- @<%= singular_table_name %>.sessions.last.update! sudo_at: 1.day.ago
18
+ test "should not update email with wrong current password" do
19
+ patch identity_email_url, params: { email: "new_email@hey.com", current_password: "SecretWrong1*3" }
27
20
 
28
- patch identity_email_url, params: { email: "new_email@hey.com" }
29
- assert_redirected_to new_sessions_sudo_url(proceed_to_url: identity_email_url)
21
+ assert_redirected_to edit_identity_email_url
22
+ assert_equal "The password you entered is incorrect", flash[:alert]
30
23
  end
31
24
  end
@@ -6,9 +6,6 @@ class Identity::PasswordResetsControllerTest < ActionDispatch::IntegrationTest
6
6
  @sid = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 20.minutes)
7
7
  @sid_exp = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 0.minutes)
8
8
  end
9
- <%- if options.lockable? %>
10
- teardown { Kredis.clear_all }
11
- <%- end -%>
12
9
 
13
10
  test "should get new" do
14
11
  get new_identity_password_reset_url
@@ -8,6 +8,7 @@ class Identity::EmailsTest < ApplicationSystemTestCase
8
8
  test "updating the email" do
9
9
  click_on "Change email address"
10
10
 
11
+ fill_in "Current password", with: "Secret1*3*5*"
11
12
  fill_in "New email", with: "new_email@hey.com"
12
13
  click_on "Save changes"
13
14
 
@@ -5,9 +5,6 @@ class Identity::PasswordResetsTest < ApplicationSystemTestCase
5
5
  @<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
6
6
  @sid = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 20.minutes)
7
7
  end
8
- <%- if options.lockable? %>
9
- teardown { Kredis.clear_all }
10
- <%- end -%>
11
8
 
12
9
  test "sending a password reset email" do
13
10
  visit sign_in_url
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authentication-zero
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.0
4
+ version: 2.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nixon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-14 00:00:00.000000000 Z
11
+ date: 2022-03-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -19,6 +19,7 @@ extra_rdoc_files: []
19
19
  files:
20
20
  - ".github/FUNDING.yml"
21
21
  - ".gitignore"
22
+ - ".rubocop.yml"
22
23
  - CHANGELOG.md
23
24
  - CODE_OF_CONDUCT.md
24
25
  - Gemfile
@@ -54,7 +55,6 @@ files:
54
55
  - lib/generators/authentication/templates/controllers/html/sessions/omniauth_controller.rb.tt
55
56
  - lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt
56
57
  - lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt
57
- - lib/generators/authentication/templates/controllers/html/sessions_controller_two_factor.rb.tt
58
58
  - lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenges_controller.rb.tt
59
59
  - lib/generators/authentication/templates/controllers/html/two_factor_authentication/totps_controller.rb.tt
60
60
  - lib/generators/authentication/templates/erb/authentications/events/index.html.erb
@@ -90,21 +90,18 @@ files:
90
90
  - lib/generators/authentication/templates/test_unit/controllers/api/identity/password_resets_controller_test.rb.tt
91
91
  - lib/generators/authentication/templates/test_unit/controllers/api/passwords_controller_test.rb.tt
92
92
  - lib/generators/authentication/templates/test_unit/controllers/api/registrations_controller_test.rb.tt
93
- - lib/generators/authentication/templates/test_unit/controllers/api/sessions/sudos_controller_test.rb.tt
94
93
  - lib/generators/authentication/templates/test_unit/controllers/api/sessions_controller_test.rb.tt
95
94
  - lib/generators/authentication/templates/test_unit/controllers/html/identity/email_verifications_controller_test.rb.tt
96
95
  - lib/generators/authentication/templates/test_unit/controllers/html/identity/emails_controller_test.rb.tt
97
96
  - lib/generators/authentication/templates/test_unit/controllers/html/identity/password_resets_controller_test.rb.tt
98
97
  - lib/generators/authentication/templates/test_unit/controllers/html/passwords_controller_test.rb.tt
99
98
  - lib/generators/authentication/templates/test_unit/controllers/html/registrations_controller_test.rb.tt
100
- - lib/generators/authentication/templates/test_unit/controllers/html/sessions/sudos_controller_test.rb.tt
101
99
  - lib/generators/authentication/templates/test_unit/controllers/html/sessions_controller_test.rb.tt
102
100
  - lib/generators/authentication/templates/test_unit/fixtures.yml.tt
103
101
  - lib/generators/authentication/templates/test_unit/system/identity/emails_test.rb.tt
104
102
  - lib/generators/authentication/templates/test_unit/system/identity/password_resets_test.rb.tt
105
103
  - lib/generators/authentication/templates/test_unit/system/passwords_test.rb.tt
106
104
  - lib/generators/authentication/templates/test_unit/system/registrations_test.rb.tt
107
- - lib/generators/authentication/templates/test_unit/system/sessions/sudos_test.rb.tt
108
105
  - lib/generators/authentication/templates/test_unit/system/sessions_test.rb.tt
109
106
  - lib/generators/authentication/templates/test_unit/test_helper.rb.tt
110
107
  homepage: https://github.com/lazaronixon/authentication-zero
@@ -1,41 +0,0 @@
1
- class SessionsController < ApplicationController
2
- skip_before_action :authenticate, only: %i[ new create ]
3
-
4
- before_action :set_session, only: :destroy
5
-
6
- def index
7
- @sessions = Current.<%= singular_table_name %>.sessions.order(created_at: :desc)
8
- end
9
-
10
- def new
11
- @<%= singular_table_name %> = <%= class_name %>.new
12
- end
13
-
14
- def create
15
- <%= singular_table_name %> = <%= class_name %>.find_by(email: params[:email])
16
-
17
- if <%= singular_table_name %> && <%= singular_table_name %>.authenticate(params[:password])
18
- if <%= singular_table_name %>.otp_secret
19
- signed_id = <%= singular_table_name %>.signed_id(purpose: :authentication_challenge, expires_in: 20.minutes)
20
-
21
- redirect_to new_two_factor_authentication_challenge_path(token: signed_id)
22
- else
23
- @session = <%= singular_table_name %>.sessions.create!
24
- cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true }
25
-
26
- redirect_to root_path, notice: "Signed in successfully"
27
- end
28
- else
29
- redirect_to sign_in_path(email_hint: params[:email]), alert: "That email or password is incorrect"
30
- end
31
- end
32
-
33
- def destroy
34
- @session.destroy; redirect_to(sessions_path, notice: "That session has been logged out")
35
- end
36
-
37
- private
38
- def set_session
39
- @session = Current.<%= singular_table_name %>.sessions.find(params[:id])
40
- end
41
- end
@@ -1,20 +0,0 @@
1
- require "test_helper"
2
-
3
- class Sessions::SudosControllerTest < ActionDispatch::IntegrationTest
4
- setup do
5
- @<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
- @<%= singular_table_name %>.sessions.last.update! sudo_at: 1.day.ago
7
- end
8
-
9
- test "should sudo" do
10
- post sessions_sudo_url, params: { password: "Secret1*3*5*" }, headers: { "Authorization" => "Bearer #{@token}" }
11
- assert_response :no_content
12
- end
13
-
14
- test "should not sudo with wrong password" do
15
- post sessions_sudo_url, params: { password: "SecretWrong1*3" }, headers: { "Authorization" => "Bearer #{@token}" }
16
-
17
- assert_response :bad_request
18
- assert_equal "The password you entered is incorrect", response.parsed_body["error"]
19
- end
20
- end
@@ -1,22 +0,0 @@
1
- require "test_helper"
2
-
3
- class Sessions::SudosControllerTest < ActionDispatch::IntegrationTest
4
- setup do
5
- @<%= singular_table_name %> = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
- end
7
-
8
- test "should get new" do
9
- get new_sessions_sudo_url(proceed_to_url: edit_password_url)
10
- assert_response :success
11
- end
12
-
13
- test "should sudo" do
14
- post sessions_sudo_url, params: { password: "Secret1*3*5*", proceed_to_url: edit_password_url }
15
- assert_redirected_to edit_password_url
16
- end
17
-
18
- test "should not sudo with wrong password" do
19
- post sessions_sudo_url, params: { password: "SecretWrong1*3", proceed_to_url: edit_password_url }
20
- assert_redirected_to new_sessions_sudo_url(proceed_to_url: edit_password_url)
21
- end
22
- end
@@ -1,15 +0,0 @@
1
- require "application_system_test_case"
2
-
3
- class Sessions::SudosTest < ApplicationSystemTestCase
4
- setup do
5
- @<%= singular_table_name %> = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
- end
7
-
8
- test "executing sudo" do
9
- visit new_sessions_sudo_url(proceed_to_url: edit_password_url)
10
- fill_in :password, with: "Secret1*3*5*"
11
- click_on "Continue"
12
-
13
- assert_selector "h1", text: "Change your password"
14
- end
15
- end