devise 4.8.0 → 4.9.4

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/CHANGELOG.md +60 -1
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +50 -22
  5. data/app/controllers/devise/confirmations_controller.rb +1 -0
  6. data/app/controllers/devise/passwords_controller.rb +2 -2
  7. data/app/controllers/devise/registrations_controller.rb +1 -1
  8. data/app/controllers/devise/sessions_controller.rb +2 -2
  9. data/app/controllers/devise/unlocks_controller.rb +1 -0
  10. data/app/controllers/devise_controller.rb +14 -0
  11. data/app/helpers/devise_helper.rb +1 -1
  12. data/app/views/devise/registrations/edit.html.erb +1 -1
  13. data/app/views/devise/shared/_error_messages.html.erb +1 -1
  14. data/app/views/devise/shared/_links.html.erb +1 -1
  15. data/lib/devise/controllers/helpers.rb +2 -0
  16. data/lib/devise/controllers/responder.rb +35 -0
  17. data/lib/devise/controllers/sign_in_out.rb +2 -2
  18. data/lib/devise/failure_app.rb +16 -3
  19. data/lib/devise/hooks/csrf_cleaner.rb +6 -1
  20. data/lib/devise/models/authenticatable.rb +2 -2
  21. data/lib/devise/models/confirmable.rb +16 -37
  22. data/lib/devise/models/database_authenticatable.rb +11 -30
  23. data/lib/devise/models/lockable.rb +1 -1
  24. data/lib/devise/models/omniauthable.rb +2 -2
  25. data/lib/devise/models/recoverable.rb +6 -17
  26. data/lib/devise/models/rememberable.rb +1 -1
  27. data/lib/devise/models/timeoutable.rb +1 -1
  28. data/lib/devise/models/validatable.rb +4 -9
  29. data/lib/devise/models.rb +1 -0
  30. data/lib/devise/orm.rb +71 -0
  31. data/lib/devise/rails/deprecated_constant_accessor.rb +1 -1
  32. data/lib/devise/rails.rb +4 -0
  33. data/lib/devise/test/controller_helpers.rb +1 -1
  34. data/lib/devise/test_helpers.rb +1 -1
  35. data/lib/devise/version.rb +1 -1
  36. data/lib/devise.rb +34 -7
  37. data/lib/generators/templates/devise.rb +10 -8
  38. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +1 -1
  39. metadata +16 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 197ce185bf22b8dc45c17a615895b60e6b788360113c37d99a116db868197309
4
- data.tar.gz: 8e3fa67c5bcd6c05ac3011e0b35f0cda57596ae74c2affceab84cab1da3aeb58
3
+ metadata.gz: 5ee56c70aa194195a4ce7ee729124c9701fa62a1ca71a0b74fa1d45f7b452c8e
4
+ data.tar.gz: f6d6fbd0a844de35d7a27ebb52eadc8da5440436cd8b037e917be40e8379b670
5
5
  SHA512:
6
- metadata.gz: 8d3f76d9e898d36dc6eb4db5d5b098b76d339aeadac014c772b7097dc6a730a7577049bd00ea7a073beead47454edb91d24fe73b50e90af3555cc5e83886902f
7
- data.tar.gz: 84cbafa77c70de3c204dfdf19e4ce53ac05796eaf959bba4d4909d0c91686baa6da61f732e13bce0892d8932af375d2b81340f6bd1047384f15325f8a24011e0
6
+ metadata.gz: d29b37afe41e4751cdbdc259c3cb7f0926bfde20949054e652677175dec119bfa49054b829103ce382ddb9655f2a51ba9f75576a2ce112bf9e179cf6f617e228
7
+ data.tar.gz: 5bd002f04b9296993f48af6e312fe94a5a0ea80cacaf3226ba78317a3a100fcdd3060c70b6592398fb8206dd98a12aa6ed906ffb29ed589b144fb1f59c923fc9
data/CHANGELOG.md CHANGED
@@ -1,4 +1,63 @@
1
- ### unreleased
1
+ ### 4.9.4 - 2024-04-10
2
+
3
+ * enhancements
4
+ * Add support for Ruby 3.3. (no changes needed)
5
+
6
+ * bug fixes
7
+ * Respect locale set by controller in failure app. Devise will carry over the current I18n.locale option when triggering authentication, and will wrap the failure app call with it. [#5567](https://github.com/heartcombo/devise/pull/5567)
8
+
9
+ ### 4.9.3 - 2023-10-11
10
+
11
+ * enhancements
12
+ * Add support for Rails 7.1.
13
+ * Add `Devise.deprecator` to integrate with new application deprecators in Rails 7.1. (@soartec-lab, @etiennebarrie)
14
+
15
+ ### 4.9.2 - 2023-04-03
16
+
17
+ * deprecations
18
+ * Bring back `Devise.activerecord51?` and deprecate it, in order to avoid breakage with some libraries that apparently relied on it.
19
+
20
+ ### 4.9.1 - 2023-03-31
21
+
22
+ * enhancements
23
+ * Allow resource class scopes to override the global configuration for `sign_in_after_reset_password` behaviour. [#5429](https://github.com/heartcombo/devise/pull/5429) [@mattr](https://github.com/mattr)
24
+ * Refactor conditional dirty tracking logic to a centralized module to simplify usage throughout the codebase. [#5575](https://github.com/heartcombo/devise/pull/5575)
25
+ * Improve support for Devise in apps with Active Record and Mongoid ORMs loaded, so it does not incorrectly uses new Active Record dirty tracking APIs with a Mongoid Devise model. [#5576](https://github.com/heartcombo/devise/pull/5576)
26
+
27
+ * bug fixes
28
+ * Failure app will respond with configured `redirect_status` instead of `error_status` if the recall app returns a redirect status (300..399) [#5573](https://github.com/heartcombo/devise/pull/5573)
29
+ * Fix frozen string exception in validatable. [#5563](https://github.com/heartcombo/devise/pull/5563) [#5465](https://github.com/heartcombo/devise/pull/5465) [@mameier](https://github.com/mameier)
30
+
31
+ ### 4.9.0 - 2023-02-17
32
+
33
+ * enhancements
34
+ * Add support for Ruby 3.1/3.2.
35
+ * Add support for Hotwire + Turbo, default in Rails 7+.
36
+ * Devise uses the latest `responders` version (v3.1.0 or higher), which allows configuring the status used for validation error responses (`error_status`) and for redirects after POST/PUT/PATCH/DELETE requests (`redirect_status`). For backwards compatibility, Devise keeps `error_status` as `:ok` which returns a `200 OK` response, and `redirect_status` to `:found` which returns a `302 Found` response, but you can configure it to return `422 Unprocessable Entity` and `303 See Other` respectively, to match the behavior expected by Hotwire/Turbo:
37
+
38
+ ```ruby
39
+ # config/initializers/devise.rb
40
+ Devise.setup do |config|
41
+ # ...
42
+ config.responder.error_status = :unprocessable_entity
43
+ config.responder.redirect_status = :see_other
44
+ # ...
45
+ end
46
+ ```
47
+
48
+ These configs are already generated by default with new apps, and existing apps may opt-in as described above. Trying to set these with an older version of `responders` will issue a warning and have no effect, so please upgrade the `responders` version if you're upgrading Devise for this integration. Note that these defaults may change in future versions of Devise, to better match the Rails + Hotwire/Turbo defaults across the board.
49
+ * If you have a custom responder set on your application and expect it to affect Devise as well, you may need to override the Devise responder entirely with `config.responder = MyApplicationResponder`, so that it uses your custom one. The main reason Devise uses a custom responder is to be able to configure the statuses as described above, but you can also change that config on your own responder if you want. Check the `responders` readme for more info on that.
50
+ * If you have created a custom responder and/or failure app just to customize responses for better Hotwire/Turbo integration, they should no longer be necessary.
51
+ * `:turbo_stream` is now treated as a navigational format, so it works like HTML navigation when using Turbo. Note: if you relied on `:turbo_stream` to be treated as a non-navigational format before, you can reconfigure your `navigational_formats` in the Devise initializer file to exclude it.
52
+ * OmniAuth "Sign in with" links were changed to buttons that generate HTML forms with method=POST, instead of using link + method=POST that required rails-ujs to work. Since rails-ujs is no longer the default for new Rails apps, this allows the OmniAuth buttons to work in any scenario, with or without rails-ujs and/or Turbo. This only affects apps that are using the default `devise/shared/_links.html.erb` partial from Devise with OmniAuth enabled.
53
+ * The "Cancel my account" button was changed to include the `data-turbo-confirm` option, so that it works with both rails-ujs and Turbo by default.
54
+ * Devise does not provide "sign out" links/buttons in its shared views, but if you're using `sign_out_via` with `:delete` (the default), and are using links with `method: :delete`, those need to be updated with `data: { turbo_method: :delete }` instead for Turbo.
55
+ * Check [this upgrade guide](https://github.com/heartcombo/devise/wiki/How-To:-Upgrade-to-Devise-4.9.0-[Hotwire-Turbo-integration]) for more detailed information.
56
+
57
+ ### 4.8.1 - 2021-12-16
58
+
59
+ * enhancements
60
+ * Add support for Rails 7.0. Please note that Turbo integration is not fully supported by Devise yet.
2
61
 
3
62
  ### 4.8.0 - 2021-04-29
4
63
 
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2020 Rafael França, Leonardo Tegon, Carlos Antônio da Silva.
1
+ Copyright 2020-2024 Rafael França, Leonardo Tegon, Carlos Antônio da Silva.
2
2
  Copyright 2009-2019 Plataformatec.
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
data/README.md CHANGED
@@ -1,6 +1,4 @@
1
- ![Devise Logo](https://raw.github.com/heartcombo/devise/master/devise.png)
2
-
3
- [![Code Climate](https://codeclimate.com/github/heartcombo/devise.svg)](https://codeclimate.com/github/heartcombo/devise)
1
+ ![Devise Logo](https://raw.github.com/heartcombo/devise/main/devise.png)
4
2
 
5
3
  Devise is a flexible authentication solution for Rails based on Warden. It:
6
4
 
@@ -11,16 +9,16 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
11
9
 
12
10
  It's composed of 10 modules:
13
11
 
14
- * [Database Authenticatable](http://www.rubydoc.info/github/heartcombo/devise/master/Devise/Models/DatabaseAuthenticatable): hashes and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
15
- * [Omniauthable](http://www.rubydoc.info/github/heartcombo/devise/master/Devise/Models/Omniauthable): adds OmniAuth (https://github.com/omniauth/omniauth) support.
16
- * [Confirmable](http://www.rubydoc.info/github/heartcombo/devise/master/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
17
- * [Recoverable](http://www.rubydoc.info/github/heartcombo/devise/master/Devise/Models/Recoverable): resets the user password and sends reset instructions.
18
- * [Registerable](http://www.rubydoc.info/github/heartcombo/devise/master/Devise/Models/Registerable): handles signing up users through a registration process, also allowing them to edit and destroy their account.
19
- * [Rememberable](http://www.rubydoc.info/github/heartcombo/devise/master/Devise/Models/Rememberable): manages generating and clearing a token for remembering the user from a saved cookie.
20
- * [Trackable](http://www.rubydoc.info/github/heartcombo/devise/master/Devise/Models/Trackable): tracks sign in count, timestamps and IP address.
21
- * [Timeoutable](http://www.rubydoc.info/github/heartcombo/devise/master/Devise/Models/Timeoutable): expires sessions that have not been active in a specified period of time.
22
- * [Validatable](http://www.rubydoc.info/github/heartcombo/devise/master/Devise/Models/Validatable): provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
23
- * [Lockable](http://www.rubydoc.info/github/heartcombo/devise/master/Devise/Models/Lockable): locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
12
+ * [Database Authenticatable](http://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/DatabaseAuthenticatable): hashes and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
13
+ * [Omniauthable](http://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/Omniauthable): adds OmniAuth (https://github.com/omniauth/omniauth) support.
14
+ * [Confirmable](http://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
15
+ * [Recoverable](http://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/Recoverable): resets the user password and sends reset instructions.
16
+ * [Registerable](http://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/Registerable): handles signing up users through a registration process, also allowing them to edit and destroy their account.
17
+ * [Rememberable](http://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/Rememberable): manages generating and clearing a token for remembering the user from a saved cookie.
18
+ * [Trackable](http://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/Trackable): tracks sign in count, timestamps and IP address.
19
+ * [Timeoutable](http://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/Timeoutable): expires sessions that have not been active in a specified period of time.
20
+ * [Validatable](http://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/Validatable): provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
21
+ * [Lockable](http://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/Lockable): locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
24
22
 
25
23
  ## Table of Contents
26
24
 
@@ -48,7 +46,7 @@ It's composed of 10 modules:
48
46
  - [Integration tests](#integration-tests)
49
47
  - [OmniAuth](#omniauth)
50
48
  - [Configuring multiple models](#configuring-multiple-models)
51
- - [ActiveJob Integration](#activejob-integration)
49
+ - [Active Job Integration](#active-job-integration)
52
50
  - [Password reset tokens and Rails logs](#password-reset-tokens-and-rails-logs)
53
51
  - [Other ORMs](#other-orms)
54
52
  - [Rails API mode](#rails-api-mode)
@@ -91,7 +89,7 @@ https://groups.google.com/group/plataformatec-devise
91
89
 
92
90
  You can view the Devise documentation in RDoc format here:
93
91
 
94
- http://rubydoc.info/github/heartcombo/devise/master/frames
92
+ http://rubydoc.info/github/heartcombo/devise/main/frames
95
93
 
96
94
  If you need to use Devise with previous versions of Rails, you can always run "gem server" from the command line after you install the gem to access the old documentation.
97
95
 
@@ -130,7 +128,7 @@ Please note that the command output will show the variable value being used.
130
128
 
131
129
  ### BUNDLE_GEMFILE
132
130
  We can use this variable to tell bundler what Gemfile it should use (instead of the one in the current directory).
133
- Inside the [gemfiles](https://github.com/heartcombo/devise/tree/master/gemfiles) directory, we have one for each version of Rails we support. When you send us a pull request, it may happen that the test suite breaks using some of them. If that's the case, you can simulate the same environment using the `BUNDLE_GEMFILE` variable.
131
+ Inside the [gemfiles](https://github.com/heartcombo/devise/tree/main/gemfiles) directory, we have one for each version of Rails we support. When you send us a pull request, it may happen that the test suite breaks using some of them. If that's the case, you can simulate the same environment using the `BUNDLE_GEMFILE` variable.
134
132
  For example, if the tests broke using Ruby 2.4.2 and Rails 4.1, you can do the following:
135
133
  ```bash
136
134
  rbenv shell 2.4.2 # or rvm use 2.4.2
@@ -384,7 +382,7 @@ $ rails generate devise:views users
384
382
  ```
385
383
 
386
384
  If you would like to generate only a few sets of views, like the ones for the `registerable` and `confirmable` module,
387
- you can pass a list of modules to the generator with the `-v` flag.
385
+ you can pass a list of views to the generator with the `-v` flag.
388
386
 
389
387
  ```console
390
388
  $ rails generate devise:views -v registrations confirmations
@@ -412,7 +410,7 @@ If the customization at the views level is not enough, you can customize each co
412
410
  ...
413
411
  end
414
412
  ```
415
- (Use the -c flag to specify a controller, for example: `rails generate devise:controllers users -c=sessions`)
413
+ Use the `-c` flag to specify one or more controllers, for example: `rails generate devise:controllers users -c sessions`)
416
414
 
417
415
  2. Tell the router to use this controller:
418
416
 
@@ -420,7 +418,7 @@ If the customization at the views level is not enough, you can customize each co
420
418
  devise_for :users, controllers: { sessions: 'users/sessions' }
421
419
  ```
422
420
 
423
- 3. Copy the views from `devise/sessions` to `users/sessions`. Since the controller was changed, it won't use the default views located in `devise/sessions`.
421
+ 3. Recommended but not required: copy (or move) the views from `devise/sessions` to `users/sessions`. Rails will continue using the views from `devise/sessions` due to inheritance if you skip this step, but having the views matching the controller(s) keeps things consistent.
424
422
 
425
423
  4. Finally, change or extend the desired controller actions.
426
424
 
@@ -458,7 +456,7 @@ Devise also ships with default routes. If you need to customize them, you should
458
456
  devise_for :users, path: 'auth', path_names: { sign_in: 'login', sign_out: 'logout', password: 'secret', confirmation: 'verification', unlock: 'unblock', registration: 'register', sign_up: 'cmon_let_me_in' }
459
457
  ```
460
458
 
461
- Be sure to check `devise_for` [documentation](http://www.rubydoc.info/github/heartcombo/devise/master/ActionDispatch/Routing/Mapper%3Adevise_for) for details.
459
+ Be sure to check `devise_for` [documentation](http://www.rubydoc.info/github/heartcombo/devise/main/ActionDispatch/Routing/Mapper%3Adevise_for) for details.
462
460
 
463
461
  If you have the need for more deep customization, for instance to also allow "/sign_in" besides "/users/sign_in", all you need to do is create your routes normally and wrap them in a `devise_scope` block in the router:
464
462
 
@@ -476,6 +474,36 @@ Please note: You will still need to add `devise_for` in your routes in order to
476
474
  devise_for :users, skip: :all
477
475
  ```
478
476
 
477
+ ### Hotwire/Turbo
478
+
479
+ Devise integrates with Hotwire/Turbo by treating such requests as navigational, and configuring certain responses for errors and redirects to match the expected behavior. New apps are generated with the following response configuration by default, and existing apps may opt-in by adding the config to their Devise initializers:
480
+
481
+ ```ruby
482
+ Devise.setup do |config|
483
+ # ...
484
+ # When using Devise with Hotwire/Turbo, the http status for error responses
485
+ # and some redirects must match the following. The default in Devise for existing
486
+ # apps is `200 OK` and `302 Found` respectively, but new apps are generated with
487
+ # these new defaults that match Hotwire/Turbo behavior.
488
+ # Note: These might become the new default in future versions of Devise.
489
+ config.responder.error_status = :unprocessable_entity
490
+ config.responder.redirect_status = :see_other
491
+ end
492
+ ```
493
+
494
+ **Important**: these custom responses require the `responders` gem version to be `3.1.0` or higher, please make sure you update it if you're going to use this configuration. Check [this upgrade guide](https://github.com/heartcombo/devise/wiki/How-To:-Upgrade-to-Devise-4.9.0-[Hotwire-Turbo-integration]) for more info.
495
+
496
+ _Note_: the above statuses configuration may become the default for Devise in a future release.
497
+
498
+ There are a couple other changes you might need to make in your app to work with Hotwire/Turbo, if you're migrating from rails-ujs:
499
+
500
+ * The `data-confirm` option that adds a confirmation modal to buttons/forms before submission needs to change to `data-turbo-confirm`, so that Turbo handles those appropriately.
501
+ * The `data-method` option that sets the request method for link submissions needs to change to `data-turbo-method`. This is not necessary for `button_to` or `form`s since Turbo can handle those.
502
+
503
+ If you're setting up Devise to sign out via `:delete`, and you're using links (instead of buttons wrapped in a form) to sign out with the `method: :delete` option, they will need to be updated as described above. (Devise does not provide sign out links/buttons in its shared views.)
504
+
505
+ Make sure to inspect your views looking for those, and change appropriately.
506
+
479
507
  ### I18n
480
508
 
481
509
  Devise uses flash messages with I18n, in conjunction with the flash keys :notice and :alert. To customize your app, you can set up your locale file:
@@ -679,7 +707,7 @@ end
679
707
 
680
708
  ### Password reset tokens and Rails logs
681
709
 
682
- If you enable the [Recoverable](http://rubydoc.info/github/heartcombo/devise/master/Devise/Models/Recoverable) module, note that a stolen password reset token could give an attacker access to your application. Devise takes effort to generate random, secure tokens, and stores only token digests in the database, never plaintext. However the default logging behavior in Rails can cause plaintext tokens to leak into log files:
710
+ If you enable the [Recoverable](http://rubydoc.info/github/heartcombo/devise/main/Devise/Models/Recoverable) module, note that a stolen password reset token could give an attacker access to your application. Devise takes effort to generate random, secure tokens, and stores only token digests in the database, never plaintext. However the default logging behavior in Rails can cause plaintext tokens to leak into log files:
683
711
 
684
712
  1. Action Mailer logs the entire contents of all outgoing emails to the DEBUG level. Password reset tokens delivered to users in email will be leaked.
685
713
  2. Active Job logs all arguments to every enqueued job at the INFO level. If you configure Devise to use `deliver_later` to send password reset emails, password reset tokens will be leaked.
@@ -739,6 +767,6 @@ https://github.com/heartcombo/devise/graphs/contributors
739
767
 
740
768
  ## License
741
769
 
742
- MIT License. Copyright 2020 Rafael França, Leonardo Tegon, Carlos Antônio da Silva. Copyright 2009-2019 Plataformatec.
770
+ MIT License. Copyright 2020-2024 Rafael França, Leonardo Tegon, Carlos Antônio da Silva. Copyright 2009-2019 Plataformatec.
743
771
 
744
772
  The Devise logo is licensed under [Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License](https://creativecommons.org/licenses/by-nc-nd/4.0/).
@@ -27,6 +27,7 @@ class Devise::ConfirmationsController < DeviseController
27
27
  set_flash_message!(:notice, :confirmed)
28
28
  respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
29
29
  else
30
+ # TODO: use `error_status` when the default changes to `:unprocessable_entity`.
30
31
  respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
31
32
  end
32
33
  end
@@ -36,7 +36,7 @@ class Devise::PasswordsController < DeviseController
36
36
 
37
37
  if resource.errors.empty?
38
38
  resource.unlock_access! if unlockable?(resource)
39
- if Devise.sign_in_after_reset_password
39
+ if resource_class.sign_in_after_reset_password
40
40
  flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
41
41
  set_flash_message!(:notice, flash_message)
42
42
  resource.after_database_authentication
@@ -53,7 +53,7 @@ class Devise::PasswordsController < DeviseController
53
53
 
54
54
  protected
55
55
  def after_resetting_password_path_for(resource)
56
- Devise.sign_in_after_reset_password ? after_sign_in_path_for(resource) : new_session_path(resource_name)
56
+ resource_class.sign_in_after_reset_password ? after_sign_in_path_for(resource) : new_session_path(resource_name)
57
57
  end
58
58
 
59
59
  # The path used after sending reset password instructions
@@ -67,7 +67,7 @@ class Devise::RegistrationsController < DeviseController
67
67
  Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
68
68
  set_flash_message! :notice, :destroyed
69
69
  yield resource if block_given?
70
- respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
70
+ respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name), status: Devise.responder.redirect_status }
71
71
  end
72
72
 
73
73
  # GET /resource/cancel
@@ -45,7 +45,7 @@ class Devise::SessionsController < DeviseController
45
45
  end
46
46
 
47
47
  def auth_options
48
- { scope: resource_name, recall: "#{controller_path}#new" }
48
+ { scope: resource_name, recall: "#{controller_path}#new", locale: I18n.locale }
49
49
  end
50
50
 
51
51
  def translation_scope
@@ -77,7 +77,7 @@ class Devise::SessionsController < DeviseController
77
77
  # support returning empty response on GET request
78
78
  respond_to do |format|
79
79
  format.all { head :no_content }
80
- format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name) }
80
+ format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name), status: Devise.responder.redirect_status }
81
81
  end
82
82
  end
83
83
  end
@@ -29,6 +29,7 @@ class Devise::UnlocksController < DeviseController
29
29
  set_flash_message! :notice, :unlocked
30
30
  respond_with_navigational(resource){ redirect_to after_unlock_path_for(resource) }
31
31
  else
32
+ # TODO: use `error_status` when the default changes to `:unprocessable_entity`.
32
33
  respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
33
34
  end
34
35
  end
@@ -15,6 +15,7 @@ class DeviseController < Devise.parent_controller.constantize
15
15
  end
16
16
 
17
17
  prepend_before_action :assert_is_devise_resource!
18
+ self.responder = Devise.responder
18
19
  respond_to :html if mimes_for_respond_to.empty?
19
20
 
20
21
  # Override prefixes to consider the scoped view.
@@ -32,6 +33,19 @@ class DeviseController < Devise.parent_controller.constantize
32
33
  end
33
34
  end
34
35
 
36
+ # Override internal methods to exclude `_prefixes` from action methods since
37
+ # we override it above.
38
+ #
39
+ # There was an intentional change in Rails 7.1 that will allow it to become
40
+ # an action method because it's a public method of a non-abstract controller,
41
+ # but we also can't make this abstract because it can affect potential actions
42
+ # defined in the parent controller, so instead we ensure `_prefixes` is going
43
+ # to be considered internal. (and thus, won't become an action method.)
44
+ # Ref: https://github.com/rails/rails/pull/48699
45
+ def self.internal_methods #:nodoc:
46
+ super << :_prefixes
47
+ end
48
+
35
49
  protected
36
50
 
37
51
  # Gets the actual resource stored in the instance variable
@@ -4,7 +4,7 @@ module DeviseHelper
4
4
  # Retain this method for backwards compatibility, deprecated in favor of modifying the
5
5
  # devise/shared/error_messages partial.
6
6
  def devise_error_messages!
7
- ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
7
+ Devise.deprecator.warn <<-DEPRECATION.strip_heredoc
8
8
  [Devise] `DeviseHelper#devise_error_messages!` is deprecated and will be
9
9
  removed in the next major version.
10
10
 
@@ -38,6 +38,6 @@
38
38
 
39
39
  <h3>Cancel my account</h3>
40
40
 
41
- <p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
41
+ <div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>
42
42
 
43
43
  <%= link_to "Back", :back %>
@@ -1,5 +1,5 @@
1
1
  <% if resource.errors.any? %>
2
- <div id="error_explanation">
2
+ <div id="error_explanation" data-turbo-cache="false">
3
3
  <h2>
4
4
  <%= I18n.t("errors.messages.not_saved",
5
5
  count: resource.errors.count,
@@ -20,6 +20,6 @@
20
20
 
21
21
  <%- if devise_mapping.omniauthable? %>
22
22
  <%- resource_class.omniauth_providers.each do |provider| %>
23
- <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), method: :post %><br />
23
+ <%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %><br />
24
24
  <% end %>
25
25
  <% end %>
@@ -46,6 +46,7 @@ module Devise
46
46
  mappings.unshift mappings.delete(favorite.to_sym) if favorite
47
47
  mappings.each do |mapping|
48
48
  opts[:scope] = mapping
49
+ opts[:locale] = I18n.locale
49
50
  warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
50
51
  end
51
52
  end
@@ -115,6 +116,7 @@ module Devise
115
116
  class_eval <<-METHODS, __FILE__, __LINE__ + 1
116
117
  def authenticate_#{mapping}!(opts = {})
117
118
  opts[:scope] = :#{mapping}
119
+ opts[:locale] = I18n.locale
118
120
  warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
119
121
  end
120
122
 
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Devise
4
+ module Controllers
5
+ # Custom Responder to configure default statuses that only apply to Devise,
6
+ # and allow to integrate more easily with Hotwire/Turbo.
7
+ class Responder < ActionController::Responder
8
+ if respond_to?(:error_status=) && respond_to?(:redirect_status=)
9
+ self.error_status = :ok
10
+ self.redirect_status = :found
11
+ else
12
+ # TODO: remove this support for older Rails versions, which aren't supported by Turbo
13
+ # and/or responders. It won't allow configuring a custom response, but it allows Devise
14
+ # to use these methods and defaults across the implementation more easily.
15
+ def self.error_status
16
+ :ok
17
+ end
18
+
19
+ def self.redirect_status
20
+ :found
21
+ end
22
+
23
+ def self.error_status=(*)
24
+ warn "[DEVISE] Setting the error status on the Devise responder has no effect with this " \
25
+ "version of `responders`, please make sure you're using a newer version. Check the changelog for more info."
26
+ end
27
+
28
+ def self.redirect_status=(*)
29
+ warn "[DEVISE] Setting the redirect status on the Devise responder has no effect with this " \
30
+ "version of `responders`, please make sure you're using a newer version. Check the changelog for more info."
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -21,7 +21,7 @@ module Devise
21
21
  # to the set_user method in warden.
22
22
  # If you are using a custom warden strategy and the timeoutable module, you have to
23
23
  # set `env["devise.skip_timeout"] = true` in the request to use this method, like we do
24
- # in the sessions controller: https://github.com/heartcombo/devise/blob/master/app/controllers/devise/sessions_controller.rb#L7
24
+ # in the sessions controller: https://github.com/heartcombo/devise/blob/main/app/controllers/devise/sessions_controller.rb#L7
25
25
  #
26
26
  # Examples:
27
27
  #
@@ -38,7 +38,7 @@ module Devise
38
38
  expire_data_after_sign_in!
39
39
 
40
40
  if options[:bypass]
41
- ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc, caller)
41
+ Devise.deprecator.warn(<<-DEPRECATION.strip_heredoc, caller)
42
42
  [Devise] bypass option is deprecated and it will be removed in future version of Devise.
43
43
  Please use bypass_sign_in method instead.
44
44
  Example:
@@ -18,6 +18,11 @@ module Devise
18
18
 
19
19
  delegate :flash, to: :request
20
20
 
21
+ include AbstractController::Callbacks
22
+ around_action do |failure_app, action|
23
+ I18n.with_locale(failure_app.i18n_locale, &action)
24
+ end
25
+
21
26
  def self.call(env)
22
27
  @respond ||= action(:respond)
23
28
  @respond.call(env)
@@ -71,7 +76,11 @@ module Devise
71
76
  end
72
77
 
73
78
  flash.now[:alert] = i18n_message(:invalid) if is_flashing_format?
74
- self.response = recall_app(warden_options[:recall]).call(request.env)
79
+ self.response = recall_app(warden_options[:recall]).call(request.env).tap { |response|
80
+ response[0] = Rack::Utils.status_code(
81
+ response[0].in?(300..399) ? Devise.responder.redirect_status : Devise.responder.error_status
82
+ )
83
+ }
75
84
  end
76
85
 
77
86
  def redirect
@@ -103,7 +112,7 @@ module Devise
103
112
  options[:default] = [message]
104
113
  auth_keys = scope_class.authentication_keys
105
114
  keys = (auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys).map { |key| scope_class.human_attribute_name(key) }
106
- options[:authentication_keys] = keys.join(I18n.translate(:"support.array.words_connector"))
115
+ options[:authentication_keys] = keys.join(I18n.t(:"support.array.words_connector"))
107
116
  options = i18n_options(options)
108
117
 
109
118
  I18n.t(:"#{scope}.#{message}", **options)
@@ -112,6 +121,10 @@ module Devise
112
121
  end
113
122
  end
114
123
 
124
+ def i18n_locale
125
+ warden_options[:locale]
126
+ end
127
+
115
128
  def redirect_url
116
129
  if warden_message == :timeout
117
130
  flash[:timedout] = true if is_flashing_format?
@@ -167,7 +180,7 @@ module Devise
167
180
  end
168
181
 
169
182
  def skip_format?
170
- %w(html */*).include? request_format.to_s
183
+ %w(html */* turbo_stream).include? request_format.to_s
171
184
  end
172
185
 
173
186
  # Choose whether we should respond in an HTTP authentication fashion,
@@ -4,6 +4,11 @@ Warden::Manager.after_authentication do |record, warden, options|
4
4
  clean_up_for_winning_strategy = !warden.winning_strategy.respond_to?(:clean_up_csrf?) ||
5
5
  warden.winning_strategy.clean_up_csrf?
6
6
  if Devise.clean_up_csrf_token_on_authentication && clean_up_for_winning_strategy
7
- warden.request.session.try(:delete, :_csrf_token)
7
+ if warden.request.respond_to?(:reset_csrf_token)
8
+ # Rails 7.1+
9
+ warden.request.reset_csrf_token
10
+ else
11
+ warden.request.session.try(:delete, :_csrf_token)
12
+ end
8
13
  end
9
14
  end
@@ -10,7 +10,7 @@ module Devise
10
10
  #
11
11
  # == Options
12
12
  #
13
- # Authenticatable adds the following options to devise_for:
13
+ # Authenticatable adds the following options to +devise+:
14
14
  #
15
15
  # * +authentication_keys+: parameters used for authentication. By default [:email].
16
16
  #
@@ -62,7 +62,7 @@ module Devise
62
62
  :remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at]
63
63
 
64
64
  include Devise::DeprecatedConstantAccessor
65
- deprecate_constant "BLACKLIST_FOR_SERIALIZATION", "Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION"
65
+ deprecate_constant "BLACKLIST_FOR_SERIALIZATION", "Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION", deprecator: Devise.deprecator
66
66
 
67
67
  included do
68
68
  class_attribute :devise_modules, instance_writer: false
@@ -48,7 +48,7 @@ module Devise
48
48
  included do
49
49
  before_create :generate_confirmation_token, if: :confirmation_required?
50
50
  after_create :skip_reconfirmation_in_callback!, if: :send_confirmation_notification?
51
- if defined?(ActiveRecord) && self < ActiveRecord::Base # ActiveRecord
51
+ if Devise::Orm.active_record?(self) # ActiveRecord
52
52
  after_commit :send_on_create_confirmation_instructions, on: :create, if: :send_confirmation_notification?
53
53
  after_commit :send_reconfirmation_instructions, on: :update, if: :reconfirmation_required?
54
54
  else # Mongoid
@@ -258,44 +258,23 @@ module Devise
258
258
  generate_confirmation_token && save(validate: false)
259
259
  end
260
260
 
261
- if Devise.activerecord51?
262
- def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
263
- @reconfirmation_required = true
264
- self.unconfirmed_email = self.email
265
- self.email = self.email_in_database
266
- self.confirmation_token = nil
267
- generate_confirmation_token
268
- end
269
- else
270
- def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
271
- @reconfirmation_required = true
272
- self.unconfirmed_email = self.email
273
- self.email = self.email_was
274
- self.confirmation_token = nil
275
- generate_confirmation_token
276
- end
261
+
262
+ def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
263
+ @reconfirmation_required = true
264
+ self.unconfirmed_email = self.email
265
+ self.email = self.devise_email_in_database
266
+ self.confirmation_token = nil
267
+ generate_confirmation_token
277
268
  end
278
269
 
279
- if Devise.activerecord51?
280
- def postpone_email_change?
281
- postpone = self.class.reconfirmable &&
282
- will_save_change_to_email? &&
283
- !@bypass_confirmation_postpone &&
284
- self.email.present? &&
285
- (!@skip_reconfirmation_in_callback || !self.email_in_database.nil?)
286
- @bypass_confirmation_postpone = false
287
- postpone
288
- end
289
- else
290
- def postpone_email_change?
291
- postpone = self.class.reconfirmable &&
292
- email_changed? &&
293
- !@bypass_confirmation_postpone &&
294
- self.email.present? &&
295
- (!@skip_reconfirmation_in_callback || !self.email_was.nil?)
296
- @bypass_confirmation_postpone = false
297
- postpone
298
- end
270
+ def postpone_email_change?
271
+ postpone = self.class.reconfirmable &&
272
+ devise_will_save_change_to_email? &&
273
+ !@bypass_confirmation_postpone &&
274
+ self.email.present? &&
275
+ (!@skip_reconfirmation_in_callback || !self.devise_email_in_database.nil?)
276
+ @bypass_confirmation_postpone = false
277
+ postpone
299
278
  end
300
279
 
301
280
  def reconfirmation_required?
@@ -13,7 +13,7 @@ module Devise
13
13
  #
14
14
  # == Options
15
15
  #
16
- # DatabaseAuthenticatable adds the following options to devise_for:
16
+ # DatabaseAuthenticatable adds the following options to +devise+:
17
17
  #
18
18
  # * +pepper+: a random string used to provide a more secure hash. Use
19
19
  # `rails secret` to generate new keys.
@@ -42,7 +42,7 @@ module Devise
42
42
  def initialize(*args, &block)
43
43
  @skip_email_changed_notification = false
44
44
  @skip_password_change_notification = false
45
- super
45
+ super
46
46
  end
47
47
 
48
48
  # Skips sending the email changed notification after_update
@@ -86,7 +86,7 @@ module Devise
86
86
  # is also rejected as long as it is also blank.
87
87
  def update_with_password(params, *options)
88
88
  if options.present?
89
- ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
89
+ Devise.deprecator.warn <<-DEPRECATION.strip_heredoc
90
90
  [Devise] The second argument of `DatabaseAuthenticatable#update_with_password`
91
91
  (`options`) is deprecated and it will be removed in the next major version.
92
92
  It was added to support a feature deprecated in Rails 4, so you can safely remove it
@@ -128,7 +128,7 @@ module Devise
128
128
  #
129
129
  def update_without_password(params, *options)
130
130
  if options.present?
131
- ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
131
+ Devise.deprecator.warn <<-DEPRECATION.strip_heredoc
132
132
  [Devise] The second argument of `DatabaseAuthenticatable#update_without_password`
133
133
  (`options`) is deprecated and it will be removed in the next major version.
134
134
  It was added to support a feature deprecated in Rails 4, so you can safely remove it
@@ -177,16 +177,9 @@ module Devise
177
177
  encrypted_password[0,29] if encrypted_password
178
178
  end
179
179
 
180
- if Devise.activerecord51?
181
- # Send notification to user when email changes.
182
- def send_email_changed_notification
183
- send_devise_notification(:email_changed, to: email_before_last_save)
184
- end
185
- else
186
- # Send notification to user when email changes.
187
- def send_email_changed_notification
188
- send_devise_notification(:email_changed, to: email_was)
189
- end
180
+ # Send notification to user when email changes.
181
+ def send_email_changed_notification
182
+ send_devise_notification(:email_changed, to: devise_email_before_last_save)
190
183
  end
191
184
 
192
185
  # Send notification to user when password changes.
@@ -205,24 +198,12 @@ module Devise
205
198
  Devise::Encryptor.digest(self.class, password)
206
199
  end
207
200
 
208
- if Devise.activerecord51?
209
- def send_email_changed_notification?
210
- self.class.send_email_changed_notification && saved_change_to_email? && !@skip_email_changed_notification
211
- end
212
- else
213
- def send_email_changed_notification?
214
- self.class.send_email_changed_notification && email_changed? && !@skip_email_changed_notification
215
- end
201
+ def send_email_changed_notification?
202
+ self.class.send_email_changed_notification && devise_saved_change_to_email? && !@skip_email_changed_notification
216
203
  end
217
204
 
218
- if Devise.activerecord51?
219
- def send_password_change_notification?
220
- self.class.send_password_change_notification && saved_change_to_encrypted_password? && !@skip_password_change_notification
221
- end
222
- else
223
- def send_password_change_notification?
224
- self.class.send_password_change_notification && encrypted_password_changed? && !@skip_password_change_notification
225
- end
205
+ def send_password_change_notification?
206
+ self.class.send_password_change_notification && devise_saved_change_to_encrypted_password? && !@skip_password_change_notification
226
207
  end
227
208
 
228
209
  module ClassMethods
@@ -18,7 +18,7 @@ module Devise
18
18
  # * +maximum_attempts+: how many attempts should be accepted before blocking the user.
19
19
  # * +lock_strategy+: lock the user account by :failed_attempts or :none.
20
20
  # * +unlock_strategy+: unlock the user account by :time, :email, :both or :none.
21
- # * +unlock_in+: the time you want to lock the user after to lock happens. Only available when unlock_strategy is :time or :both.
21
+ # * +unlock_in+: the time you want to unlock the user after lock happens. Only available when unlock_strategy is :time or :both.
22
22
  # * +unlock_keys+: the keys you want to use when locking and unlocking an account
23
23
  #
24
24
  module Lockable
@@ -8,11 +8,11 @@ module Devise
8
8
  #
9
9
  # == Options
10
10
  #
11
- # Oauthable adds the following options to devise_for:
11
+ # Oauthable adds the following options to +devise+:
12
12
  #
13
13
  # * +omniauth_providers+: Which providers are available to this model. It expects an array:
14
14
  #
15
- # devise_for :database_authenticatable, :omniauthable, omniauth_providers: [:twitter]
15
+ # devise :database_authenticatable, :omniauthable, omniauth_providers: [:twitter]
16
16
  #
17
17
  module Omniauthable
18
18
  extend ActiveSupport::Concern
@@ -7,7 +7,7 @@ module Devise
7
7
  #
8
8
  # ==Options
9
9
  #
10
- # Recoverable adds the following options to devise_for:
10
+ # Recoverable adds the following options to +devise+:
11
11
  #
12
12
  # * +reset_password_keys+: the keys you want to use when recovering the password for an account
13
13
  # * +reset_password_within+: the time period within which the password must be reset or the token expires.
@@ -99,24 +99,13 @@ module Devise
99
99
  send_devise_notification(:reset_password_instructions, token, {})
100
100
  end
101
101
 
102
- if Devise.activerecord51?
103
- def clear_reset_password_token?
104
- encrypted_password_changed = respond_to?(:will_save_change_to_encrypted_password?) && will_save_change_to_encrypted_password?
105
- authentication_keys_changed = self.class.authentication_keys.any? do |attribute|
106
- respond_to?("will_save_change_to_#{attribute}?") && send("will_save_change_to_#{attribute}?")
107
- end
108
-
109
- authentication_keys_changed || encrypted_password_changed
102
+ def clear_reset_password_token?
103
+ encrypted_password_changed = devise_respond_to_and_will_save_change_to_attribute?(:encrypted_password)
104
+ authentication_keys_changed = self.class.authentication_keys.any? do |attribute|
105
+ devise_respond_to_and_will_save_change_to_attribute?(attribute)
110
106
  end
111
- else
112
- def clear_reset_password_token?
113
- encrypted_password_changed = respond_to?(:encrypted_password_changed?) && encrypted_password_changed?
114
- authentication_keys_changed = self.class.authentication_keys.any? do |attribute|
115
- respond_to?("#{attribute}_changed?") && send("#{attribute}_changed?")
116
- end
117
107
 
118
- authentication_keys_changed || encrypted_password_changed
119
- end
108
+ authentication_keys_changed || encrypted_password_changed
120
109
  end
121
110
 
122
111
  module ClassMethods
@@ -15,7 +15,7 @@ module Devise
15
15
  #
16
16
  # == Options
17
17
  #
18
- # Rememberable adds the following options in devise_for:
18
+ # Rememberable adds the following options to +devise+:
19
19
  #
20
20
  # * +remember_for+: the time you want the user will be remembered without
21
21
  # asking for credentials. After this time the user will be blocked and
@@ -11,7 +11,7 @@ module Devise
11
11
  #
12
12
  # == Options
13
13
  #
14
- # Timeoutable adds the following options to devise_for:
14
+ # Timeoutable adds the following options to +devise+:
15
15
  #
16
16
  # * +timeout_in+: the interval to timeout the user session without activity.
17
17
  #
@@ -9,7 +9,7 @@ module Devise
9
9
  #
10
10
  # == Options
11
11
  #
12
- # Validatable adds the following options to devise_for:
12
+ # Validatable adds the following options to +devise+:
13
13
  #
14
14
  # * +email_regexp+: the regular expression used to validate e-mails;
15
15
  # * +password_length+: a range expressing password length. Defaults to 6..128.
@@ -29,13 +29,8 @@ module Devise
29
29
 
30
30
  base.class_eval do
31
31
  validates_presence_of :email, if: :email_required?
32
- if Devise.activerecord51?
33
- validates_uniqueness_of :email, allow_blank: true, case_sensitive: true, if: :will_save_change_to_email?
34
- validates_format_of :email, with: email_regexp, allow_blank: true, if: :will_save_change_to_email?
35
- else
36
- validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
37
- validates_format_of :email, with: email_regexp, allow_blank: true, if: :email_changed?
38
- end
32
+ validates_uniqueness_of :email, allow_blank: true, case_sensitive: true, if: :devise_will_save_change_to_email?
33
+ validates_format_of :email, with: email_regexp, allow_blank: true, if: :devise_will_save_change_to_email?
39
34
 
40
35
  validates_presence_of :password, if: :password_required?
41
36
  validates_confirmation_of :password, if: :password_required?
@@ -47,7 +42,7 @@ module Devise
47
42
  unavailable_validations = VALIDATIONS.select { |v| !base.respond_to?(v) }
48
43
 
49
44
  unless unavailable_validations.empty?
50
- raise "Could not use :validatable module since #{base} does not respond " <<
45
+ raise "Could not use :validatable module since #{base} does not respond " \
51
46
  "to the following methods: #{unavailable_validations.to_sentence}."
52
47
  end
53
48
  end
data/lib/devise/models.rb CHANGED
@@ -84,6 +84,7 @@ module Devise
84
84
  end
85
85
 
86
86
  devise_modules_hook! do
87
+ include Devise::Orm
87
88
  include Devise::Models::Authenticatable
88
89
 
89
90
  selected_modules.each do |m|
data/lib/devise/orm.rb ADDED
@@ -0,0 +1,71 @@
1
+ module Devise
2
+ module Orm # :nodoc:
3
+ def self.active_record?(model)
4
+ defined?(ActiveRecord) && model < ActiveRecord::Base
5
+ end
6
+
7
+ def self.active_record_51?(model)
8
+ active_record?(model) && ActiveRecord.gem_version >= Gem::Version.new("5.1.x")
9
+ end
10
+
11
+ def self.included(model)
12
+ if Devise::Orm.active_record_51?(model)
13
+ model.include DirtyTrackingNewMethods
14
+ else
15
+ model.include DirtyTrackingOldMethods
16
+ end
17
+ end
18
+
19
+ module DirtyTrackingNewMethods
20
+ def devise_email_before_last_save
21
+ email_before_last_save
22
+ end
23
+
24
+ def devise_email_in_database
25
+ email_in_database
26
+ end
27
+
28
+ def devise_saved_change_to_email?
29
+ saved_change_to_email?
30
+ end
31
+
32
+ def devise_saved_change_to_encrypted_password?
33
+ saved_change_to_encrypted_password?
34
+ end
35
+
36
+ def devise_will_save_change_to_email?
37
+ will_save_change_to_email?
38
+ end
39
+
40
+ def devise_respond_to_and_will_save_change_to_attribute?(attribute)
41
+ respond_to?("will_save_change_to_#{attribute}?") && send("will_save_change_to_#{attribute}?")
42
+ end
43
+ end
44
+
45
+ module DirtyTrackingOldMethods
46
+ def devise_email_before_last_save
47
+ email_was
48
+ end
49
+
50
+ def devise_email_in_database
51
+ email_was
52
+ end
53
+
54
+ def devise_saved_change_to_email?
55
+ email_changed?
56
+ end
57
+
58
+ def devise_saved_change_to_encrypted_password?
59
+ encrypted_password_changed?
60
+ end
61
+
62
+ def devise_will_save_change_to_email?
63
+ email_changed?
64
+ end
65
+
66
+ def devise_respond_to_and_will_save_change_to_attribute?(attribute)
67
+ respond_to?("#{attribute}_changed?") && send("#{attribute}_changed?")
68
+ end
69
+ end
70
+ end
71
+ end
@@ -26,7 +26,7 @@ rescue LoadError
26
26
  super
27
27
  end
28
28
 
29
- def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance)
29
+ def deprecate_constant(const_name, new_constant, message: nil, deprecator: Devise.deprecator)
30
30
  class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
31
31
  class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator }
32
32
  end
data/lib/devise/rails.rb CHANGED
@@ -17,6 +17,10 @@ module Devise
17
17
  app.reload_routes! if Devise.reload_routes
18
18
  end
19
19
 
20
+ initializer "devise.deprecator" do |app|
21
+ app.deprecators[:devise] = Devise.deprecator if app.respond_to?(:deprecators)
22
+ end
23
+
20
24
  initializer "devise.url_helpers" do
21
25
  Devise.include_helpers(Devise::Controllers)
22
26
  end
@@ -69,7 +69,7 @@ module Devise
69
69
  scope = resource
70
70
  resource = deprecated
71
71
 
72
- ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
72
+ Devise.deprecator.warn <<-DEPRECATION.strip_heredoc
73
73
  [Devise] sign_in(:#{scope}, resource) on controller tests is deprecated and will be removed from Devise.
74
74
  Please use sign_in(resource, scope: :#{scope}) instead.
75
75
  DEPRECATION
@@ -4,7 +4,7 @@ module Devise
4
4
  module TestHelpers
5
5
  def self.included(base)
6
6
  base.class_eval do
7
- ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
7
+ Devise.deprecator.warn <<-DEPRECATION.strip_heredoc
8
8
  [Devise] including `Devise::TestHelpers` is deprecated and will be removed from Devise.
9
9
  For controller tests, please include `Devise::Test::ControllerHelpers` instead.
10
10
  DEPRECATION
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Devise
4
- VERSION = "4.8.0".freeze
4
+ VERSION = "4.9.4".freeze
5
5
  end
data/lib/devise.rb CHANGED
@@ -13,6 +13,7 @@ module Devise
13
13
  autoload :Encryptor, 'devise/encryptor'
14
14
  autoload :FailureApp, 'devise/failure_app'
15
15
  autoload :OmniAuth, 'devise/omniauth'
16
+ autoload :Orm, 'devise/orm'
16
17
  autoload :ParameterFilter, 'devise/parameter_filter'
17
18
  autoload :ParameterSanitizer, 'devise/parameter_sanitizer'
18
19
  autoload :TestHelpers, 'devise/test_helpers'
@@ -23,6 +24,7 @@ module Devise
23
24
  module Controllers
24
25
  autoload :Helpers, 'devise/controllers/helpers'
25
26
  autoload :Rememberable, 'devise/controllers/rememberable'
27
+ autoload :Responder, 'devise/controllers/responder'
26
28
  autoload :ScopedViews, 'devise/controllers/scoped_views'
27
29
  autoload :SignInOut, 'devise/controllers/sign_in_out'
28
30
  autoload :StoreLocation, 'devise/controllers/store_location'
@@ -217,7 +219,16 @@ module Devise
217
219
 
218
220
  # Which formats should be treated as navigational.
219
221
  mattr_accessor :navigational_formats
220
- @@navigational_formats = ["*/*", :html]
222
+ @@navigational_formats = ["*/*", :html, :turbo_stream]
223
+
224
+ # The default responder used by Devise, used to customize status codes with:
225
+ #
226
+ # `config.responder.error_status`
227
+ # `config.responder.redirect_status`
228
+ #
229
+ # Can be replaced by a custom application responder.
230
+ mattr_accessor :responder
231
+ @@responder = Devise::Controllers::Responder
221
232
 
222
233
  # When set to true, signing out a user signs out all other scopes.
223
234
  mattr_accessor :sign_out_all_scopes
@@ -297,10 +308,6 @@ module Devise
297
308
  mattr_accessor :sign_in_after_change_password
298
309
  @@sign_in_after_change_password = true
299
310
 
300
- def self.activerecord51? # :nodoc:
301
- defined?(ActiveRecord) && ActiveRecord.gem_version >= Gem::Version.new("5.1.x")
302
- end
303
-
304
311
  # Default way to set up Devise. Run rails generate devise_install to create
305
312
  # a fresh initializer with all configuration values.
306
313
  def self.setup
@@ -313,12 +320,20 @@ module Devise
313
320
  end
314
321
 
315
322
  def get
316
- ActiveSupport::Dependencies.constantize(@name)
323
+ # TODO: Remove AS::Dependencies usage when dropping support to Rails < 7.
324
+ if ActiveSupport::Dependencies.respond_to?(:constantize)
325
+ ActiveSupport::Dependencies.constantize(@name)
326
+ else
327
+ @name.constantize
328
+ end
317
329
  end
318
330
  end
319
331
 
320
332
  def self.ref(arg)
321
- ActiveSupport::Dependencies.reference(arg)
333
+ # TODO: Remove AS::Dependencies usage when dropping support to Rails < 7.
334
+ if ActiveSupport::Dependencies.respond_to?(:reference)
335
+ ActiveSupport::Dependencies.reference(arg)
336
+ end
322
337
  Getter.new(arg)
323
338
  end
324
339
 
@@ -505,6 +520,18 @@ module Devise
505
520
  b.each_byte { |byte| res |= byte ^ l.shift }
506
521
  res == 0
507
522
  end
523
+
524
+ def self.deprecator
525
+ @deprecator ||= ActiveSupport::Deprecation.new("5.0", "Devise")
526
+ end
527
+
528
+ def self.activerecord51? # :nodoc:
529
+ deprecator.warn <<-DEPRECATION.strip_heredoc
530
+ [Devise] `Devise.activerecord51?` is deprecated and will be removed in the next major version.
531
+ It is a non-public method that's no longer used internally, but that other libraries have been relying on.
532
+ DEPRECATION
533
+ defined?(ActiveRecord) && ActiveRecord.gem_version >= Gem::Version.new("5.1.x")
534
+ end
508
535
  end
509
536
 
510
537
  require 'warden'
@@ -256,14 +256,14 @@ Devise.setup do |config|
256
256
 
257
257
  # ==> Navigation configuration
258
258
  # Lists the formats that should be treated as navigational. Formats like
259
- # :html, should redirect to the sign in page when the user does not have
259
+ # :html should redirect to the sign in page when the user does not have
260
260
  # access, but formats like :xml or :json, should return 401.
261
261
  #
262
262
  # If you have any extra navigational formats, like :iphone or :mobile, you
263
263
  # should add them to the navigational formats lists.
264
264
  #
265
265
  # The "*/*" below is required to match Internet Explorer requests.
266
- # config.navigational_formats = ['*/*', :html]
266
+ # config.navigational_formats = ['*/*', :html, :turbo_stream]
267
267
 
268
268
  # The default HTTP method used to sign out a resource. Default is :delete.
269
269
  config.sign_out_via = :delete
@@ -296,12 +296,14 @@ Devise.setup do |config|
296
296
  # so you need to do it manually. For the users scope, it would be:
297
297
  # config.omniauth_path_prefix = '/my_engine/users/auth'
298
298
 
299
- # ==> Turbolinks configuration
300
- # If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly:
301
- #
302
- # ActiveSupport.on_load(:devise_failure_app) do
303
- # include Turbolinks::Controller
304
- # end
299
+ # ==> Hotwire/Turbo configuration
300
+ # When using Devise with Hotwire/Turbo, the http status for error responses
301
+ # and some redirects must match the following. The default in Devise for existing
302
+ # apps is `200 OK` and `302 Found` respectively, but new apps are generated with
303
+ # these new defaults that match Hotwire/Turbo behavior.
304
+ # Note: These might become the new default in future versions of Devise.
305
+ config.responder.error_status = :unprocessable_entity
306
+ config.responder.redirect_status = :see_other
305
307
 
306
308
  # ==> Configuration for :registerable
307
309
 
@@ -30,6 +30,6 @@
30
30
 
31
31
  <h3>Cancel my account</h3>
32
32
 
33
- <p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
33
+ <div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>
34
34
 
35
35
  <%= link_to "Back", :back %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.0
4
+ version: 4.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - José Valim
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-04-29 00:00:00.000000000 Z
12
+ date: 2024-04-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: warden
@@ -117,6 +117,7 @@ files:
117
117
  - lib/devise.rb
118
118
  - lib/devise/controllers/helpers.rb
119
119
  - lib/devise/controllers/rememberable.rb
120
+ - lib/devise/controllers/responder.rb
120
121
  - lib/devise/controllers/scoped_views.rb
121
122
  - lib/devise/controllers/sign_in_out.rb
122
123
  - lib/devise/controllers/store_location.rb
@@ -150,6 +151,7 @@ files:
150
151
  - lib/devise/omniauth.rb
151
152
  - lib/devise/omniauth/config.rb
152
153
  - lib/devise/omniauth/url_helpers.rb
154
+ - lib/devise/orm.rb
153
155
  - lib/devise/orm/active_record.rb
154
156
  - lib/devise/orm/mongoid.rb
155
157
  - lib/devise/parameter_filter.rb
@@ -202,8 +204,17 @@ files:
202
204
  homepage: https://github.com/heartcombo/devise
203
205
  licenses:
204
206
  - MIT
205
- metadata: {}
206
- post_install_message:
207
+ metadata:
208
+ homepage_uri: https://github.com/heartcombo/devise
209
+ documentation_uri: https://rubydoc.info/github/heartcombo/devise
210
+ changelog_uri: https://github.com/heartcombo/devise/blob/main/CHANGELOG.md
211
+ source_code_uri: https://github.com/heartcombo/devise
212
+ bug_tracker_uri: https://github.com/heartcombo/devise/issues
213
+ wiki_uri: https://github.com/heartcombo/devise/wiki
214
+ post_install_message: "\n[DEVISE] Please review the [changelog] and [upgrade guide]
215
+ for more info on Hotwire / Turbo integration.\n\n [changelog] https://github.com/heartcombo/devise/blob/main/CHANGELOG.md\n
216
+ \ [upgrade guide] https://github.com/heartcombo/devise/wiki/How-To:-Upgrade-to-Devise-4.9.0-%5BHotwire-Turbo-integration%5D\n
217
+ \ "
207
218
  rdoc_options: []
208
219
  require_paths:
209
220
  - lib
@@ -218,7 +229,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
218
229
  - !ruby/object:Gem::Version
219
230
  version: '0'
220
231
  requirements: []
221
- rubygems_version: 3.2.6
232
+ rubygems_version: 3.5.3
222
233
  signing_key:
223
234
  specification_version: 4
224
235
  summary: Flexible authentication solution for Rails with Warden