authentication-zero 2.16.36 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/CI.yml +6 -5
  3. data/.rubocop.yml +8 -0
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile.lock +1 -1
  6. data/README.md +8 -0
  7. data/lib/authentication_zero/version.rb +1 -1
  8. data/lib/generators/authentication/authentication_generator.rb +0 -4
  9. data/lib/generators/authentication/templates/controllers/api/identity/email_verifications_controller.rb.tt +1 -1
  10. data/lib/generators/authentication/templates/controllers/api/identity/emails_controller.rb.tt +5 -3
  11. data/lib/generators/authentication/templates/controllers/api/identity/password_resets_controller.rb.tt +2 -6
  12. data/lib/generators/authentication/templates/controllers/api/passwords_controller.rb.tt +2 -4
  13. data/lib/generators/authentication/templates/controllers/api/sessions_controller.rb.tt +1 -3
  14. data/lib/generators/authentication/templates/controllers/html/identity/email_verifications_controller.rb.tt +1 -1
  15. data/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt +5 -3
  16. data/lib/generators/authentication/templates/controllers/html/identity/password_resets_controller.rb.tt +2 -6
  17. data/lib/generators/authentication/templates/controllers/html/passwords_controller.rb.tt +2 -4
  18. data/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt +1 -3
  19. data/lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt +2 -2
  20. data/lib/generators/authentication/templates/erb/passwords/edit.html.erb.tt +2 -2
  21. data/lib/generators/authentication/templates/lib/account_middleware.rb +4 -6
  22. data/lib/generators/authentication/templates/mailers/user_mailer.rb.tt +3 -3
  23. data/lib/generators/authentication/templates/models/user.rb.tt +4 -5
  24. data/lib/generators/authentication/templates/test_unit/controllers/api/identity/email_verifications_controller_test.rb.tt +7 -4
  25. data/lib/generators/authentication/templates/test_unit/controllers/api/identity/emails_controller_test.rb.tt +5 -5
  26. data/lib/generators/authentication/templates/test_unit/controllers/api/identity/password_resets_controller_test.rb.tt +8 -5
  27. data/lib/generators/authentication/templates/test_unit/controllers/api/passwords_controller_test.rb.tt +5 -5
  28. data/lib/generators/authentication/templates/test_unit/controllers/html/identity/email_verifications_controller_test.rb.tt +6 -4
  29. data/lib/generators/authentication/templates/test_unit/controllers/html/identity/emails_controller_test.rb.tt +6 -5
  30. data/lib/generators/authentication/templates/test_unit/controllers/html/identity/password_resets_controller_test.rb.tt +8 -5
  31. data/lib/generators/authentication/templates/test_unit/controllers/html/passwords_controller_test.rb.tt +5 -5
  32. data/lib/generators/authentication/templates/test_unit/system/identity/emails_test.rb.tt +1 -1
  33. data/lib/generators/authentication/templates/test_unit/system/identity/password_resets_test.rb.tt +1 -1
  34. data/lib/generators/authentication/templates/test_unit/system/passwords_test.rb.tt +1 -1
  35. metadata +3 -7
  36. data/lib/generators/authentication/templates/migrations/create_email_verification_tokens_migration.rb.tt +0 -7
  37. data/lib/generators/authentication/templates/migrations/create_password_reset_tokens_migration.rb.tt +0 -7
  38. data/lib/generators/authentication/templates/models/email_verification_token.rb.tt +0 -3
  39. data/lib/generators/authentication/templates/models/password_reset_token.rb.tt +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01c6ab07811e6c670432fb66c4ceb3580c69cb45c438e18a947b231d86041b35
4
- data.tar.gz: de1d633031898842969cebc414d84c543e7efcf7675b65e2b552e5ec2c318bf3
3
+ metadata.gz: 1a3d3b8586f1e31b0110ad4dab428c38798c8a014f3f305a128bd90b8f51efe0
4
+ data.tar.gz: 4064bc5928d671f0403c12537d4b65adbbc4940d0efa8e8cfbaffd709b7677e4
5
5
  SHA512:
6
- metadata.gz: 1b1eacc6b8b9551a63d8bce3a49780f12dfa999901169e51370c34a4e272bccf885e00a5dcd69e9c163a216729fa1f1f8673ec6969613b2f4c444cbdfbd381ea
7
- data.tar.gz: 82084da636d5b44ed85ee1c2c9c928ffe40549ecf742a93206f9d804a0bc6d4c4e63dc414fb558d4a551e7e73fc76ae96159ec45eb3cfde98d143dd4b1920aa9
6
+ metadata.gz: e08062d6b3710305fa2e7ac251bf816761cfd80aa8a4d0662b03cef95f072bc6a2a60803d66150e7d34830fd54abf33d20073730e6818a4aaf009a421beb9971
7
+ data.tar.gz: c0388c5e3a9f2eb9628a4fd1bd031543f4dbd56072631d5da7312cd3fbc3b4bd9d0ba873037218c274cecb25522154ca4ad6ed40221def8e1607d4ed410984de
@@ -18,10 +18,11 @@ jobs:
18
18
  - name: Install Ruby and gems
19
19
  uses: ruby/setup-ruby@v1
20
20
  with:
21
+ ruby-version: "3.2"
21
22
  bundler-cache: true
22
23
 
23
24
  - name: Install the latest Rails gem
24
- run: gem install rails -v "~> 7.0.0"
25
+ run: gem install rails -v "7.1.0"
25
26
 
26
27
  - name: Install Rubocop
27
28
  run: gem install rubocop rubocop-performance rubocop-minitest rubocop-packaging rubocop-minitest rubocop-rails
@@ -31,7 +32,7 @@ jobs:
31
32
 
32
33
  - name: Create fresh Rails app and run generator
33
34
  run: |
34
- rails new test-app
35
+ rails new test-app --skip-action-mailbox --skip-action-text --skip-active-storage
35
36
  cp .rubocop.yml test-app/.rubocop.yml
36
37
  cd test-app
37
38
  bundle add authentication-zero --path ..
@@ -61,10 +62,11 @@ jobs:
61
62
  - name: Install Ruby and gems
62
63
  uses: ruby/setup-ruby@v1
63
64
  with:
65
+ ruby-version: "3.2"
64
66
  bundler-cache: true
65
67
 
66
68
  - name: Install the latest Rails gem
67
- run: gem install rails -v "~> 7.0.0"
69
+ run: gem install rails -v "7.1.0"
68
70
 
69
71
  - name: Install Rubocop
70
72
  run: gem install rubocop rubocop-performance rubocop-minitest rubocop-packaging rubocop-minitest rubocop-rails
@@ -74,7 +76,7 @@ jobs:
74
76
 
75
77
  - name: Create fresh Rails app and run generator
76
78
  run: |
77
- rails new test-app
79
+ rails new test-app --skip-action-mailbox --skip-action-text --skip-active-storage
78
80
  cp .rubocop.yml test-app/.rubocop.yml
79
81
  cd test-app
80
82
  bundle add authentication-zero --path ..
@@ -90,4 +92,3 @@ jobs:
90
92
 
91
93
  - name: Tests
92
94
  run: cd test-app && bin/rails test
93
-
data/.rubocop.yml CHANGED
@@ -4,5 +4,13 @@ Style/HashSyntax:
4
4
  Exclude:
5
5
  - Gemfile
6
6
 
7
+ Layout/EmptyLinesAroundBlockBody:
8
+ Exclude:
9
+ - Gemfile
10
+
11
+ Layout/TrailingWhitespace:
12
+ Exclude:
13
+ - config/initializers/filter_parameter_logging.rb
14
+
7
15
  Style/FrozenStringLiteralComment:
8
16
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## Authentication Zero 3.0.0 ##
2
+
3
+ * Use the new normalizes API
4
+ * Use the new password_challenge API
5
+ * Use the new authenticate_by API
6
+ * Use the new generates_token_for API
7
+
1
8
  ## Authentication Zero 2.16.35 ##
2
9
 
3
10
  * Adjust relationship so that account has many users
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- authentication-zero (2.16.36)
4
+ authentication-zero (3.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -8,6 +8,12 @@ The purpose of authentication zero is to generate a pre-built authentication sys
8
8
  $ bundle add authentication-zero
9
9
  ```
10
10
 
11
+ If you are using Rails < 7.1, you must use version 2.
12
+
13
+ ```
14
+ $ bundle add authentication-zero --version "~> 2"
15
+ ```
16
+
11
17
  ## Usage
12
18
 
13
19
  ```
@@ -51,6 +57,8 @@ Since Authentication Zero generates this code into your application instead of b
51
57
  ## Generated code
52
58
 
53
59
  - [has_secure_password](https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password): Adds methods to set and authenticate against a bcrypt password.
60
+ - [authenticate_by](https://edgeapi.rubyonrails.org/classes/ActiveRecord/SecurePassword/ClassMethods.html#method-i-authenticate_by): Given a set of attributes, finds a record using the non-password attributes, and then authenticates that record using the password attributes.
61
+ - [generates_token_for](https://edgeapi.rubyonrails.org/classes/ActiveRecord/TokenFor/ClassMethods.html#method-i-generates_token_for): Defines the behavior of tokens generated for a specific purpose.
54
62
  - [signed cookies](https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html): Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from the cookie again.
55
63
  - [httponly cookies](https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html): A cookie with the httponly attribute is inaccessible to the JavaScript, this precaution helps mitigate cross-site scripting (XSS) attacks.
56
64
  - [signed_id](https://api.rubyonrails.org/classes/ActiveRecord/SignedId.html): Returns a signed id that is tamper proof, so it's safe to send in an email or otherwise share with the outside world.
@@ -1,3 +1,3 @@
1
1
  module AuthenticationZero
2
- VERSION = "2.16.36"
2
+ VERSION = "3.0.0"
3
3
  end
@@ -70,8 +70,6 @@ class AuthenticationGenerator < Rails::Generators::Base
70
70
  migration_template "migrations/create_accounts_migration.rb", "#{db_migrate_path}/create_accounts_migration.rb" if options.tenantable?
71
71
  migration_template "migrations/create_users_migration.rb", "#{db_migrate_path}/create_users.rb"
72
72
  migration_template "migrations/create_sessions_migration.rb", "#{db_migrate_path}/create_sessions.rb"
73
- migration_template "migrations/create_password_reset_tokens_migration.rb", "#{db_migrate_path}/create_password_reset_tokens.rb"
74
- migration_template "migrations/create_email_verification_tokens_migration.rb", "#{db_migrate_path}/create_email_verification_tokens.rb"
75
73
  migration_template "migrations/create_events_migration.rb", "#{db_migrate_path}/create_events.rb" if options.trackable?
76
74
  migration_template "migrations/create_recovery_codes_migration.rb", "#{db_migrate_path}/create_recovery_codes.rb" if two_factor?
77
75
  migration_template "migrations/create_security_keys_migration.rb", "#{db_migrate_path}/create_security_keys.rb" if webauthn?
@@ -83,9 +81,7 @@ class AuthenticationGenerator < Rails::Generators::Base
83
81
 
84
82
  template "models/account.rb", "app/models/account.rb" if options.tenantable?
85
83
  template "models/current.rb", "app/models/current.rb"
86
- template "models/email_verification_token.rb", "app/models/email_verification_token.rb"
87
84
  template "models/event.rb", "app/models/event.rb" if options.trackable?
88
- template "models/password_reset_token.rb", "app/models/password_reset_token.rb"
89
85
  template "models/recovery_code.rb", "app/models/recovery_code.rb" if two_factor?
90
86
  template "models/security_key.rb", "app/models/security_key.rb" if webauthn?
91
87
  template "models/session.rb", "app/models/session.rb"
@@ -13,7 +13,7 @@ class Identity::EmailVerificationsController < ApplicationController
13
13
 
14
14
  private
15
15
  def set_user
16
- token = EmailVerificationToken.find_signed!(params[:sid]); @user = token.user
16
+ @user = User.find_by_token_for!(:email_verification, params[:sid])
17
17
  rescue StandardError
18
18
  render json: { error: "That email verification link is invalid" }, status: :bad_request
19
19
  end
@@ -2,9 +2,7 @@ class Identity::EmailsController < ApplicationController
2
2
  before_action :set_user
3
3
 
4
4
  def update
5
- if !@user.authenticate(params[:current_password])
6
- render json: { error: "The password you entered is incorrect" }, status: :bad_request
7
- elsif @user.update(email: params[:email])
5
+ if @user.update(user_params)
8
6
  render_show
9
7
  else
10
8
  render json: @user.errors, status: :unprocessable_entity
@@ -16,6 +14,10 @@ class Identity::EmailsController < ApplicationController
16
14
  @user = Current.user
17
15
  end
18
16
 
17
+ def user_params
18
+ params.permit(:email, :password_challenge).with_defaults(password_challenge: "")
19
+ end
20
+
19
21
  def render_show
20
22
  if @user.email_previously_changed?
21
23
  resend_email_verification; render(json: @user)
@@ -20,7 +20,7 @@ class Identity::PasswordResetsController < ApplicationController
20
20
 
21
21
  def update
22
22
  if @user.update(user_params)
23
- revoke_tokens; render(json: @user)
23
+ render json: @user
24
24
  else
25
25
  render json: @user.errors, status: :unprocessable_entity
26
26
  end
@@ -28,7 +28,7 @@ class Identity::PasswordResetsController < ApplicationController
28
28
 
29
29
  private
30
30
  def set_user
31
- token = PasswordResetToken.find_signed!(params[:sid]); @user = token.user
31
+ @user = User.find_by_token_for!(:password_reset, params[:sid])
32
32
  rescue StandardError
33
33
  render json: { error: "That password reset link is invalid" }, status: :bad_request
34
34
  end
@@ -36,8 +36,4 @@ class Identity::PasswordResetsController < ApplicationController
36
36
  def user_params
37
37
  params.permit(:password, :password_confirmation)
38
38
  end
39
-
40
- def revoke_tokens
41
- @user.password_reset_tokens.delete_all
42
- end
43
39
  end
@@ -2,9 +2,7 @@ class PasswordsController < ApplicationController
2
2
  before_action :set_user
3
3
 
4
4
  def update
5
- if !@user.authenticate(params[:current_password])
6
- render json: { error: "The current password you entered is incorrect" }, status: :bad_request
7
- elsif @user.update(user_params)
5
+ if @user.update(user_params)
8
6
  render json: @user
9
7
  else
10
8
  render json: @user.errors, status: :unprocessable_entity
@@ -17,6 +15,6 @@ class PasswordsController < ApplicationController
17
15
  end
18
16
 
19
17
  def user_params
20
- params.permit(:password, :password_confirmation)
18
+ params.permit(:password, :password_confirmation, :password_challenge).with_defaults(password_challenge: "")
21
19
  end
22
20
  end
@@ -12,9 +12,7 @@ class SessionsController < ApplicationController
12
12
  end
13
13
 
14
14
  def create
15
- user = User.find_by(email: params[:email])
16
-
17
- if user && user.authenticate(params[:password])
15
+ if user = User.authenticate_by(email: params[:email], password: params[:password])
18
16
  @session = user.sessions.create!
19
17
  response.set_header "X-Session-Token", @session.signed_id
20
18
 
@@ -15,7 +15,7 @@ class Identity::EmailVerificationsController < ApplicationController
15
15
 
16
16
  private
17
17
  def set_user
18
- token = EmailVerificationToken.find_signed!(params[:sid]); @user = token.user
18
+ @user = User.find_by_token_for!(:email_verification, params[:sid])
19
19
  rescue StandardError
20
20
  redirect_to edit_identity_email_path, alert: "That email verification link is invalid"
21
21
  end
@@ -5,9 +5,7 @@ class Identity::EmailsController < ApplicationController
5
5
  end
6
6
 
7
7
  def update
8
- if !@user.authenticate(params[:current_password])
9
- redirect_to edit_identity_email_path, alert: "The password you entered is incorrect"
10
- elsif @user.update(email: params[:email])
8
+ if @user.update(user_params)
11
9
  redirect_to_root
12
10
  else
13
11
  render :edit, status: :unprocessable_entity
@@ -19,6 +17,10 @@ class Identity::EmailsController < ApplicationController
19
17
  @user = Current.user
20
18
  end
21
19
 
20
+ def user_params
21
+ params.permit(:email, :password_challenge).with_defaults(password_challenge: "")
22
+ end
23
+
22
24
  def redirect_to_root
23
25
  if @user.email_previously_changed?
24
26
  resend_email_verification
@@ -23,7 +23,7 @@ class Identity::PasswordResetsController < ApplicationController
23
23
 
24
24
  def update
25
25
  if @user.update(user_params)
26
- revoke_tokens; redirect_to(sign_in_path, notice: "Your password was reset successfully. Please sign in")
26
+ redirect_to sign_in_path, notice: "Your password was reset successfully. Please sign in"
27
27
  else
28
28
  render :edit, status: :unprocessable_entity
29
29
  end
@@ -31,7 +31,7 @@ class Identity::PasswordResetsController < ApplicationController
31
31
 
32
32
  private
33
33
  def set_user
34
- token = PasswordResetToken.find_signed!(params[:sid]); @user = token.user
34
+ @user = User.find_by_token_for!(:password_reset, params[:sid])
35
35
  rescue StandardError
36
36
  redirect_to new_identity_password_reset_path, alert: "That password reset link is invalid"
37
37
  end
@@ -43,8 +43,4 @@ class Identity::PasswordResetsController < ApplicationController
43
43
  def send_password_reset_email
44
44
  UserMailer.with(user: @user).password_reset.deliver_later
45
45
  end
46
-
47
- def revoke_tokens
48
- @user.password_reset_tokens.delete_all
49
- end
50
46
  end
@@ -5,9 +5,7 @@ class PasswordsController < ApplicationController
5
5
  end
6
6
 
7
7
  def update
8
- if !@user.authenticate(params[:current_password])
9
- redirect_to edit_password_path, alert: "The current password you entered is incorrect"
10
- elsif @user.update(user_params)
8
+ if @user.update(user_params)
11
9
  redirect_to root_path, notice: "Your password has been changed"
12
10
  else
13
11
  render :edit, status: :unprocessable_entity
@@ -20,6 +18,6 @@ class PasswordsController < ApplicationController
20
18
  end
21
19
 
22
20
  def user_params
23
- params.permit(:password, :password_confirmation)
21
+ params.permit(:password, :password_confirmation, :password_challenge).with_defaults(password_challenge: "")
24
22
  end
25
23
  end
@@ -11,9 +11,7 @@ class SessionsController < ApplicationController
11
11
  end
12
12
 
13
13
  def create
14
- user = User.find_by(email: params[:email])
15
-
16
- if user && user.authenticate(params[:password])
14
+ if user = User.authenticate_by(email: params[:email], password: params[:password])
17
15
  <%- if two_factor? -%>
18
16
  if user.otp_required_for_sign_in?
19
17
  session[:challenge_token] = user.signed_id(purpose: :authentication_challenge, expires_in: 20.minutes)
@@ -27,8 +27,8 @@
27
27
  </div>
28
28
 
29
29
  <div>
30
- <%%= form.label :current_password, style: "display: block" %>
31
- <%%= form.password_field :current_password, required: true, autocomplete: "current-password" %>
30
+ <%%= form.label :password_challenge, style: "display: block" %>
31
+ <%%= form.password_field :password_challenge, required: true, autocomplete: "current-password" %>
32
32
  </div>
33
33
 
34
34
  <div>
@@ -16,8 +16,8 @@
16
16
  <%% end %>
17
17
 
18
18
  <div>
19
- <%%= form.label :current_password, style: "display: block" %>
20
- <%%= form.password_field :current_password, required: true, autofocus: true, autocomplete: "current-password" %>
19
+ <%%= form.label :password_challenge, style: "display: block" %>
20
+ <%%= form.password_field :password_challenge, required: true, autofocus: true, autocomplete: "current-password" %>
21
21
  </div>
22
22
 
23
23
  <div>
@@ -6,13 +6,11 @@ class AccountMiddleware
6
6
  def call(env)
7
7
  request = ActionDispatch::Request.new(env)
8
8
 
9
- _, account_id, request_path = request.path.split("/", 3)
10
-
11
- if account_id !~ /\D/
9
+ if m = /\A(\/(\d{1,}))/.match(request.path_info)
10
+ script_name, account_id, path_info = [m[1], m[2], m.post_match]
11
+ request.script_name = script_name
12
+ request.path_info = path_info.presence || "/"
12
13
  set_current_account(account_id)
13
-
14
- request.script_name = "/#{account_id}"
15
- request.path_info = "/#{request_path}"
16
14
  @app.call(request.env)
17
15
  else
18
16
  @app.call(request.env)
@@ -1,14 +1,14 @@
1
1
  class UserMailer < ApplicationMailer
2
2
  def password_reset
3
3
  @user = params[:user]
4
- @signed_id = @user.password_reset_tokens.create.signed_id(expires_in: 20.minutes)
4
+ @signed_id = @user.generate_token_for(:password_reset)
5
5
 
6
6
  mail to: @user.email, subject: "Reset your password"
7
7
  end
8
8
 
9
9
  def email_verification
10
10
  @user = params[:user]
11
- @signed_id = @user.email_verification_tokens.create.signed_id(expires_in: 2.days)
11
+ @signed_id = @user.generate_token_for(:email_verification)
12
12
 
13
13
  mail to: @user.email, subject: "Verify your email"
14
14
  end
@@ -23,7 +23,7 @@ class UserMailer < ApplicationMailer
23
23
  <%- if invitable? %>
24
24
  def invitation_instructions
25
25
  @user = params[:user]
26
- @signed_id = @user.password_reset_tokens.create.signed_id(expires_in: 2.days)
26
+ @signed_id = @user.generate_token_for(:password_reset)
27
27
 
28
28
  mail to: @user.email, subject: "Invitation instructions"
29
29
  end
@@ -1,11 +1,12 @@
1
1
  class User < ApplicationRecord
2
2
  has_secure_password
3
+
4
+ generates_token_for :email_verification, expires_in: 2.days { email }
5
+ generates_token_for :password_reset, expires_in: 20.minutes { password_salt.last(10) }
3
6
  <%- if options.tenantable? %>
4
7
  belongs_to :account
5
8
  <%- end -%>
6
9
 
7
- has_many :email_verification_tokens, dependent: :destroy
8
- has_many :password_reset_tokens, dependent: :destroy
9
10
  has_many :sessions, dependent: :destroy
10
11
  <%- if two_factor? -%>
11
12
  has_many :recovery_codes, dependent: :destroy
@@ -26,9 +27,7 @@ class User < ApplicationRecord
26
27
  validates :password, not_pwned: { message: "might easily be guessed" }
27
28
  <%- end -%>
28
29
 
29
- before_validation if: -> { email.present? } do
30
- self.email = email.downcase.strip
31
- end
30
+ normalizes :email, with: -> { _1.strip.downcase }
32
31
 
33
32
  before_validation if: :email_changed?, on: :update do
34
33
  self.verified = false
@@ -11,7 +11,7 @@ class Identity::EmailVerificationsControllerTest < ActionDispatch::IntegrationTe
11
11
  end
12
12
 
13
13
  test "should send a verification email" do
14
- assert_enqueued_email_with UserMailer, :email_verification, args: { user: @user } do
14
+ assert_enqueued_email_with UserMailer, :email_verification, params: { user: @user } do
15
15
  post identity_email_verification_url, headers: default_headers
16
16
  end
17
17
 
@@ -19,16 +19,19 @@ class Identity::EmailVerificationsControllerTest < ActionDispatch::IntegrationTe
19
19
  end
20
20
 
21
21
  test "should verify email" do
22
- sid = @user.email_verification_tokens.create.signed_id(expires_in: 2.days)
22
+ sid = @user.generate_token_for(:email_verification)
23
23
 
24
24
  get identity_email_verification_url, params: { sid: sid }, headers: default_headers
25
25
  assert_response :no_content
26
26
  end
27
27
 
28
28
  test "should not verify email with expired token" do
29
- sid_exp = @user.email_verification_tokens.create.signed_id(expires_in: 0.minutes)
29
+ sid = @user.generate_token_for(:email_verification)
30
+
31
+ travel 3.days
32
+
33
+ get identity_email_verification_url, params: { sid: sid }, headers: default_headers
30
34
 
31
- get identity_email_verification_url, params: { sid: sid_exp }, headers: default_headers
32
35
  assert_response :bad_request
33
36
  assert_equal "That email verification link is invalid", response.parsed_body["error"]
34
37
  end
@@ -10,14 +10,14 @@ class Identity::EmailsControllerTest < ActionDispatch::IntegrationTest
10
10
  end
11
11
 
12
12
  test "should update email" do
13
- patch identity_email_url, params: { email: "new_email@hey.com", current_password: "Secret1*3*5*" }, headers: default_headers
13
+ patch identity_email_url, params: { email: "new_email@hey.com", password_challenge: "Secret1*3*5*" }, headers: default_headers
14
14
  assert_response :success
15
15
  end
16
16
 
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
+ test "should not update email with wrong password challenge" do
18
+ patch identity_email_url, params: { email: "new_email@hey.com", password_challenge: "SecretWrong1*3" }, headers: default_headers
19
19
 
20
- assert_response :bad_request
21
- assert_equal "The password you entered is incorrect", response.parsed_body["error"]
20
+ assert_response :unprocessable_entity
21
+ assert_equal ["is invalid"], response.parsed_body["password_challenge"]
22
22
  end
23
23
  end
@@ -6,14 +6,14 @@ class Identity::PasswordResetsControllerTest < ActionDispatch::IntegrationTest
6
6
  end
7
7
 
8
8
  test "should get edit" do
9
- sid = @user.password_reset_tokens.create.signed_id(expires_in: 20.minutes)
9
+ sid = @user.generate_token_for(:password_reset)
10
10
 
11
11
  get edit_identity_password_reset_url(sid: sid)
12
12
  assert_response :no_content
13
13
  end
14
14
 
15
15
  test "should send a password reset email" do
16
- assert_enqueued_email_with UserMailer, :password_reset, args: { user: @user } do
16
+ assert_enqueued_email_with UserMailer, :password_reset, params: { user: @user } do
17
17
  post identity_password_reset_url, params: { email: @user.email }
18
18
  end
19
19
 
@@ -41,16 +41,19 @@ class Identity::PasswordResetsControllerTest < ActionDispatch::IntegrationTest
41
41
  end
42
42
 
43
43
  test "should update password" do
44
- sid = @user.password_reset_tokens.create.signed_id(expires_in: 20.minutes)
44
+ sid = @user.generate_token_for(:password_reset)
45
45
 
46
46
  patch identity_password_reset_url, params: { sid: sid, password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
47
47
  assert_response :success
48
48
  end
49
49
 
50
50
  test "should not update password with expired token" do
51
- sid_exp = @user.password_reset_tokens.create.signed_id(expires_in: 0.minutes)
51
+ sid = @user.generate_token_for(:password_reset)
52
+
53
+ travel 30.minutes
54
+
55
+ patch identity_password_reset_url, params: { sid: sid, password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
52
56
 
53
- patch identity_password_reset_url, params: { sid: sid_exp, password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
54
57
  assert_response :bad_request
55
58
  assert_equal "That password reset link is invalid", response.parsed_body["error"]
56
59
  end
@@ -10,14 +10,14 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
10
10
  end
11
11
 
12
12
  test "should update password" do
13
- patch password_url, params: { current_password: "Secret1*3*5*", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers: default_headers
13
+ patch password_url, params: { password_challenge: "Secret1*3*5*", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers: default_headers
14
14
  assert_response :success
15
15
  end
16
16
 
17
- test "should not update password with wrong current password" do
18
- patch password_url, params: { current_password: "SecretWrong1*3", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers: default_headers
17
+ test "should not update password with wrong password challenge" do
18
+ patch password_url, params: { password_challenge: "SecretWrong1*3", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }, headers: default_headers
19
19
 
20
- assert_response :bad_request
21
- assert_equal "The current password you entered is incorrect", response.parsed_body["error"]
20
+ assert_response :unprocessable_entity
21
+ assert_equal ["is invalid"], response.parsed_body["password_challenge"]
22
22
  end
23
23
  end
@@ -7,7 +7,7 @@ class Identity::EmailVerificationsControllerTest < ActionDispatch::IntegrationTe
7
7
  end
8
8
 
9
9
  test "should send a verification email" do
10
- assert_enqueued_email_with UserMailer, :email_verification, args: { user: @user } do
10
+ assert_enqueued_email_with UserMailer, :email_verification, params: { user: @user } do
11
11
  post identity_email_verification_url
12
12
  end
13
13
 
@@ -15,16 +15,18 @@ class Identity::EmailVerificationsControllerTest < ActionDispatch::IntegrationTe
15
15
  end
16
16
 
17
17
  test "should verify email" do
18
- sid = @user.email_verification_tokens.create.signed_id(expires_in: 2.days)
18
+ sid = @user.generate_token_for(:email_verification)
19
19
 
20
20
  get identity_email_verification_url(sid: sid, email: @user.email)
21
21
  assert_redirected_to root_url
22
22
  end
23
23
 
24
24
  test "should not verify email with expired token" do
25
- sid_exp = @user.email_verification_tokens.create.signed_id(expires_in: 0.minutes)
25
+ sid = @user.generate_token_for(:email_verification)
26
26
 
27
- get identity_email_verification_url(sid: sid_exp, email: @user.email)
27
+ travel 3.days
28
+
29
+ get identity_email_verification_url(sid: sid, email: @user.email)
28
30
 
29
31
  assert_redirected_to edit_identity_email_url
30
32
  assert_equal "That email verification link is invalid", flash[:alert]
@@ -11,14 +11,15 @@ class Identity::EmailsControllerTest < ActionDispatch::IntegrationTest
11
11
  end
12
12
 
13
13
  test "should update email" do
14
- patch identity_email_url, params: { email: "new_email@hey.com", current_password: "Secret1*3*5*" }
14
+ patch identity_email_url, params: { email: "new_email@hey.com", password_challenge: "Secret1*3*5*" }
15
15
  assert_redirected_to root_url
16
16
  end
17
17
 
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" }
20
18
 
21
- assert_redirected_to edit_identity_email_url
22
- assert_equal "The password you entered is incorrect", flash[:alert]
19
+ test "should not update password with wrong password challenge" do
20
+ patch password_url, params: { password_challenge: "SecretWrong1*3", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
21
+
22
+ assert_response :unprocessable_entity
23
+ assert_select "li", /Password challenge is invalid/
23
24
  end
24
25
  end
@@ -11,14 +11,14 @@ class Identity::PasswordResetsControllerTest < ActionDispatch::IntegrationTest
11
11
  end
12
12
 
13
13
  test "should get edit" do
14
- sid = @user.password_reset_tokens.create.signed_id(expires_in: 20.minutes)
14
+ sid = @user.generate_token_for(:password_reset)
15
15
 
16
16
  get edit_identity_password_reset_url(sid: sid)
17
17
  assert_response :success
18
18
  end
19
19
 
20
20
  test "should send a password reset email" do
21
- assert_enqueued_email_with UserMailer, :password_reset, args: { user: @user } do
21
+ assert_enqueued_email_with UserMailer, :password_reset, params: { user: @user } do
22
22
  post identity_password_reset_url, params: { email: @user.email }
23
23
  end
24
24
 
@@ -46,16 +46,19 @@ class Identity::PasswordResetsControllerTest < ActionDispatch::IntegrationTest
46
46
  end
47
47
 
48
48
  test "should update password" do
49
- sid = @user.password_reset_tokens.create.signed_id(expires_in: 20.minutes)
49
+ sid = @user.generate_token_for(:password_reset)
50
50
 
51
51
  patch identity_password_reset_url, params: { sid: sid, password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
52
52
  assert_redirected_to sign_in_url
53
53
  end
54
54
 
55
55
  test "should not update password with expired token" do
56
- sid_exp = @user.password_reset_tokens.create.signed_id(expires_in: 0.minutes)
56
+ sid = @user.generate_token_for(:password_reset)
57
+
58
+ travel 30.minutes
59
+
60
+ patch identity_password_reset_url, params: { sid: sid, password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
57
61
 
58
- patch identity_password_reset_url, params: { sid: sid_exp, password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
59
62
  assert_redirected_to new_identity_password_reset_url
60
63
  assert_equal "That password reset link is invalid", flash[:alert]
61
64
  end
@@ -11,14 +11,14 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
11
11
  end
12
12
 
13
13
  test "should update password" do
14
- patch password_url, params: { current_password: "Secret1*3*5*", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
14
+ patch password_url, params: { password_challenge: "Secret1*3*5*", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
15
15
  assert_redirected_to root_url
16
16
  end
17
17
 
18
- test "should not update password with wrong current password" do
19
- patch password_url, params: { current_password: "SecretWrong1*3", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
18
+ test "should not update password with wrong password challenge" do
19
+ patch password_url, params: { password_challenge: "SecretWrong1*3", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
20
20
 
21
- assert_redirected_to edit_password_url
22
- assert_equal "The current password you entered is incorrect", flash[:alert]
21
+ assert_response :unprocessable_entity
22
+ assert_select "li", /Password challenge is invalid/
23
23
  end
24
24
  end
@@ -9,7 +9,7 @@ class Identity::EmailsTest < ApplicationSystemTestCase
9
9
  click_on "Change email address"
10
10
 
11
11
  fill_in "New email", with: "new_email@hey.com"
12
- fill_in "Current password", with: "Secret1*3*5*"
12
+ fill_in "Password challenge", with: "Secret1*3*5*"
13
13
  click_on "Save changes"
14
14
 
15
15
  assert_text "Your email has been changed"
@@ -3,7 +3,7 @@ require "application_system_test_case"
3
3
  class Identity::PasswordResetsTest < ApplicationSystemTestCase
4
4
  setup do
5
5
  @user = users(:lazaro_nixon)
6
- @sid = @user.password_reset_tokens.create.signed_id(expires_in: 20.minutes)
6
+ @sid = @user.generate_token_for(:password_reset)
7
7
  end
8
8
 
9
9
  test "sending a password reset email" do
@@ -8,7 +8,7 @@ class PasswordsTest < ApplicationSystemTestCase
8
8
  test "updating the password" do
9
9
  click_on "Change password"
10
10
 
11
- fill_in "Current password", with: "Secret1*3*5*"
11
+ fill_in "Password challenge", with: "Secret1*3*5*"
12
12
  fill_in "New password", with: "Secret6*4*2*"
13
13
  fill_in "Confirm new password", with: "Secret6*4*2*"
14
14
  click_on "Save changes"
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.16.36
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nixon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-17 00:00:00.000000000 Z
11
+ date: 2023-10-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -98,9 +98,7 @@ files:
98
98
  - lib/generators/authentication/templates/lib/account_middleware.rb
99
99
  - lib/generators/authentication/templates/mailers/user_mailer.rb.tt
100
100
  - lib/generators/authentication/templates/migrations/create_accounts_migration.rb.tt
101
- - lib/generators/authentication/templates/migrations/create_email_verification_tokens_migration.rb.tt
102
101
  - lib/generators/authentication/templates/migrations/create_events_migration.rb.tt
103
- - lib/generators/authentication/templates/migrations/create_password_reset_tokens_migration.rb.tt
104
102
  - lib/generators/authentication/templates/migrations/create_recovery_codes_migration.rb.tt
105
103
  - lib/generators/authentication/templates/migrations/create_security_keys_migration.rb.tt
106
104
  - lib/generators/authentication/templates/migrations/create_sessions_migration.rb.tt
@@ -109,9 +107,7 @@ files:
109
107
  - lib/generators/authentication/templates/models/account.rb.tt
110
108
  - lib/generators/authentication/templates/models/concerns/account_scoped.rb
111
109
  - lib/generators/authentication/templates/models/current.rb.tt
112
- - lib/generators/authentication/templates/models/email_verification_token.rb.tt
113
110
  - lib/generators/authentication/templates/models/event.rb.tt
114
- - lib/generators/authentication/templates/models/password_reset_token.rb.tt
115
111
  - lib/generators/authentication/templates/models/recovery_code.rb.tt
116
112
  - lib/generators/authentication/templates/models/security_key.rb.tt
117
113
  - lib/generators/authentication/templates/models/session.rb.tt
@@ -160,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
156
  - !ruby/object:Gem::Version
161
157
  version: '0'
162
158
  requirements: []
163
- rubygems_version: 3.4.10
159
+ rubygems_version: 3.4.19
164
160
  signing_key:
165
161
  specification_version: 4
166
162
  summary: An authentication system generator for Rails applications
@@ -1,7 +0,0 @@
1
- class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
- def change
3
- create_table :email_verification_tokens do |t|
4
- t.references :user, null: false, foreign_key: true
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
- def change
3
- create_table :password_reset_tokens do |t|
4
- t.references :user, null: false, foreign_key: true
5
- end
6
- end
7
- end
@@ -1,3 +0,0 @@
1
- class EmailVerificationToken < ApplicationRecord
2
- belongs_to :user
3
- end
@@ -1,3 +0,0 @@
1
- class PasswordResetToken < ApplicationRecord
2
- belongs_to :user
3
- end