diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 000000000..75ad21eca
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,25 @@
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the
+// README at: https://github.com/devcontainers/templates/tree/main/src/ruby
+{
+ "name": "Ruby",
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
+ "image": "mcr.microsoft.com/devcontainers/ruby:0-3-bullseye",
+ "features": {
+ "ghcr.io/devcontainers/features/github-cli:1": {}
+ },
+
+ // Features to add to the dev container. More info: https://containers.dev/features.
+ // "features": {},
+
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
+ // "forwardPorts": [],
+
+ // Use 'postCreateCommand' to run commands after the container is created.
+ "postCreateCommand": "bundle install",
+
+ // Configure tool-specific properties.
+ // "customizations": {},
+
+ // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
+ // "remoteUser": "root"
+}
diff --git a/.github/code-scanning.yml b/.github/code-scanning.yml
new file mode 100644
index 000000000..0245ae21d
--- /dev/null
+++ b/.github/code-scanning.yml
@@ -0,0 +1,2 @@
+paths-ignore:
+ - test/**
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000..5ace4600a
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 000000000..d3a7488b9
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,71 @@
+name: Test
+
+permissions:
+ contents: read
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ workflow_dispatch:
+jobs:
+ test:
+ strategy:
+ fail-fast: false
+ matrix:
+ gemfile:
+ - Gemfile
+ - gemfiles/Gemfile-rails-main
+ - gemfiles/Gemfile-rails-7-0
+ - gemfiles/Gemfile-rails-7-1
+ - gemfiles/Gemfile-rails-7-2
+ - gemfiles/Gemfile-rails-8-0
+ ruby:
+ - '4.0'
+ - '3.4'
+ - '3.3'
+ - '3.2'
+ - '3.1'
+ - '3.0'
+ - '2.7'
+ orm:
+ - active_record
+ - mongoid
+ exclude:
+ - gemfile: Gemfile
+ ruby: '3.1'
+ - gemfile: Gemfile
+ ruby: '3.0'
+ - gemfile: Gemfile
+ ruby: '2.7'
+ - gemfile: gemfiles/Gemfile-rails-main
+ ruby: '3.2'
+ - gemfile: gemfiles/Gemfile-rails-main
+ ruby: '3.1'
+ - gemfile: gemfiles/Gemfile-rails-main
+ ruby: '3.0'
+ - gemfile: gemfiles/Gemfile-rails-main
+ ruby: '2.7'
+ - gemfile: gemfiles/Gemfile-rails-8-0
+ ruby: '3.1'
+ - gemfile: gemfiles/Gemfile-rails-8-0
+ ruby: '3.0'
+ - gemfile: gemfiles/Gemfile-rails-8-0
+ ruby: '2.7'
+ - gemfile: gemfiles/Gemfile-rails-7-2
+ ruby: '3.0'
+ - gemfile: gemfiles/Gemfile-rails-7-2
+ ruby: '2.7'
+ runs-on: ubuntu-latest
+ env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
+ BUNDLE_GEMFILE: ${{ matrix.gemfile }}
+ DEVISE_ORM: ${{ matrix.orm }}
+ steps:
+ - uses: actions/checkout@v6
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler-cache: true # runs bundle install and caches installed gems automatically
+ - uses: supercharge/mongodb-github-action@1.12.1
+ if: ${{ matrix.orm == 'mongoid' }}
+ - run: bundle exec rake
diff --git a/.gitignore b/.gitignore
index 0ff774271..ac2a95781 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ rdoc/*
pkg
log
test/tmp/*
+gemfiles/*.lock
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index feeb80b18..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,58 +0,0 @@
-language: ruby
-
-rvm:
- - 2.1.10
- - 2.2.7
- - 2.3.4
- - 2.4.1
- - ruby-head
-
-gemfile:
- - Gemfile
- - gemfiles/Gemfile.rails-5.0-stable
- - gemfiles/Gemfile.rails-4.2-stable
- - gemfiles/Gemfile.rails-4.1-stable
-
-matrix:
- exclude:
- - rvm: 2.1.10
- gemfile: Gemfile
- - rvm: 2.4.1
- gemfile: gemfiles/Gemfile.rails-4.1-stable
- - rvm: ruby-head
- gemfile: gemfiles/Gemfile.rails-4.1-stable
- - rvm: 2.1.10
- gemfile: gemfiles/Gemfile.rails-5.0-stable
- - rvm: 2.1.10
- gemfile: Gemfile
- - env: DEVISE_ORM=mongoid
- gemfile: Gemfile
- - env: DEVISE_ORM=mongoid
- gemfile: gemfiles/Gemfile.rails-5.0-stable
- allow_failures:
- - rvm: ruby-head
-services:
- - mongodb
-
-sudo: false
-
-cache: bundler
-
-env:
- matrix:
- - DEVISE_ORM=active_record
- - DEVISE_ORM=mongoid
-
-before_install: "rm ${BUNDLE_GEMFILE}.lock"
-
-before_script: "bundle update"
-
-script: "bin/test"
-
-notifications:
- email: false
- slack:
- on_pull_requests: false
- on_success: change
- on_failure: always
- secure: Q3M+kmude3FjisibEeeGe0wSMXgvwLH+vL7Zrx9//q4QtkfnrQ/BBMvY9KXxPEsNF+eys4YopYjTkJ8uRmeboUATW/oQ4Jrv3+u3zkIHK2sFn/Q2cQWpK5w+CbgEnHPjKYnUu34b09njXTgDlr/mqtbPqrKeZ1dLlpKXCB/q4GY=
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f0ead4c46..7ccb0882a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,193 +1,88 @@
-### 4.3.0 - 2017-05-14
+### 5.0.4 - 2026-05-08
-* Enhancements
- * Dependency support added for Rails 5.1.x.
+* security fixes
+ * Fix open redirect in `FailureApp` via unvalidated `Referer` header on non-GET session timeout. CVE-2026-40295 [GHSA-jp94-3292-c3xv](https://github.com/heartcombo/devise/security/advisories/GHSA-jp94-3292-c3xv)
-### 4.2.1 - 2017-03-15
+### 5.0.3 - 2026-03-16
+
+* security fixes
+ * Fix race condition vulnerability on confirmable "change email" which would allow confirming an email they don't own CVE-2026-32700 [GHSA-57hq-95w6-v4fc](https://github.com/heartcombo/devise/security/advisories/GHSA-57hq-95w6-v4fc) [#5783](https://github.com/heartcombo/devise/pull/5783) [#5784](https://github.com/heartcombo/devise/pull/5784)
+
+### 5.0.2 - 2026-02-18
-* removals
- * `Devise::Mailer#scope_name` and `Devise::Mailer#resource` are now protected
- methods instead of public.
-* bug fixes
- * Attempt to reset password without the password field in the request now results in a `:blank` validation error.
- Before this change, Devise would accept the reset password request and log the user in, without validating/changing
- the password. (by @victor-am)
- * Confirmation links now expire based on UTC time, working properly when using different timezones. (by @jjuliano)
-* enhancements
- * Notify the original email when it is changed with a new `Devise.send_email_changed_notification` setting.
- When using `reconfirmable`, the notification will be sent right away instead of when the unconfirmed email is confirmed.
- (original change by @ethirajsrinivasan)
-
-### 4.2.0 - 2016-07-01
-
-* removals
- * Remove the deprecated `Devise::ParameterSanitizer` API from Devise 3.
- Please use the `#permit` and `#sanitize` methods over `#for`.
- * Remove the deprecated OmniAuth URL helpers. Use the fully qualified helpers
- (`user_facebook_omniauth_authorize_path`) over the scope based helpers
- ( `user_omniauth_authorize_path(:facebook)`).
- * Remove the `Devise.bcrypt` method, use `Devise::Encryptor.digest` instead.
- * Remove the `Devise::Models::Confirmable#confirm!` method, use `confirm` instead.
- * Remove the `Devise::Models::Recoverable#reset_password!` method, use `reset_password` instead.
- * Remove the `Devise::Models::Recoverable#after_password_reset` method.
-* bug fixes
- * Fix an `ActionDispatch::IllegalStateError` when testing controllers with Rails 5 rc 2(by @hamadata).
- * Use `ActiveSupport.on_load` hooks to include Devise on `ActiveRecord` and `Mongoid`,
- avoiding autoloading these constants too soon (by @lucasmazza, @rafaelfranca).
* enhancements
- * Display the minimum password length on `registrations/edit` view (by @Yanchek99).
- * You can disable Devise's routes reloading on boot by through the `reload_routes = false` config.
- This can reduce the time taken to boot the application but it might trigger
- some errors if you application (mostly your controllers) requires that
- Devise mappings be loaded during boot time (by @sidonath).
- * Added `Devise::Test::IntegrationHelpers` to bypass the sign in process using
- Warden test API (by @lucasmazza).
- * Define `inspect` in `Devise::Models::Authenticatable` to help ensure password hashes
- aren't included in exceptions or otherwise accidentally serialized (by @tkrajcar).
- * Add missing support of `Rails.application.config.action_controller.relative_url_root` (by @kosdiamantis).
-* deprecations
- * `Devise::TestHelpers` is deprecated in favor of `Devise::Test::ControllerHelpers`
- (by @lucasmazza).
- * The `sign_in` test helper has changed to use keyword arguments when passing
- a scope. `sign_in :admin, users(:alice)` should be rewritten as
- `sign_in users(:alice), scope: :admin` (by @lucasmazza).
- * The option `bypass` of `Devise::Controllers::SignInOut#sign_in` method is
- deprecated in favor of `Devise::Controllers::SignInOut#bypass_sign_in`
- method (by @ulissesalmeida).
-
-### 4.1.1 - 2016-05-15
+ * Allow resource class scopes to override the global configuration for `sign_in_after_change_password` behaviour. [#5825](https://github.com/heartcombo/devise/pull/5825)
+ * _Note_: some users ran into an issue with this change because `RegistrationsController` now relies on a setting from the `:registerable` module. These users were configuring their own routes pointing to the `RegistrationsController` for resource edit/update actions mostly, without relying on the other registration actions (e.g. user sign up.), so they omitted `:registerable` from the model declaration. While using just a portion of the controller functionality is a valid use for `:registerable` (or any module really), the module must still be declared in the model, much like the other modules must be declared if you plan on using just a portion of their behavior. Please check [this issue](https://github.com/heartcombo/devise/pull/5828#issuecomment-3926822788) for more info.
+ * Add `sign_in_after_reset_password?` check hook to passwords controller, to allow it to be customized by users. [#5826](https://github.com/heartcombo/devise/pull/5826)
+
+### 5.0.1 - 2026-02-13
* bug fixes
- * Fix overwriting the remember_token when a valid one already exists (by @ralinchimev).
+ * Fix translation issue with German `E-Mail` on invalid authentication messages caused by previous fix for incorrect grammar [#5822](https://github.com/heartcombo/devise/pull/5822)
-### 4.1.0
+### 5.0.0 - 2026-01-23
-* bug fixes
- * Fix race condition of sending the confirmation instructions e-mail using background jobs.
- Using the previous `after_create` callback, the e-mail can be sent before
- the record be committed on database, generating a `ActiveRecord::NotFound` error.
- Now the confirmation e-mail will be only sent after the database commit,
- using the `after_commit` callback.
- It may break your test suite on Rails 4 if you are testing the sent e-mails
- or enqueued jobs using transactional fixtures enabled or `DatabaseCleaner` with `transaction` strategy.
- You can easily fix your test suite using the gem
- [test_after_commit](https://github.com/grosser/test_after_commit). For example, put in your Gemfile:
-
- ```ruby
- gem 'test_after_commit', :group => :test
- ```
+no changes
- On Rails 5 `after_commit` callbacks are triggered even using transactional
- fixtures, then this fix will not break your test suite. If you are using `DatabaseCleaner` with the `deletion` or `truncation` strategies it may not break your tests. (by @allenwq)
- * Fix strategy checking in `Lockable#unlock_strategy_enabled?` for `:none` and
- `:undefined` strategies. (by @f3ndot)
-* features
- * Humanize authentication keys in failure flash message (by @byzg)
- When you are configuring the translations of `devise.failure.invalid`, the
- `authentication_keys` is translated now.
-* deprecations
- * Remove code supporting old session serialization format (by @fphilipe).
- * Now the `email_regexp` default uses a more permissive regex:
- `/\A[^@\s]+@[^@\s]+\z/` (by @kimgb)
- * Now the `strip_whitespace_keys` default is `[:email]` (by @ulissesalmeida)
- * Now the `reconfirmable` default is `true` (by @ulissesalmeida)
- * Now the `skip_session_storage` default is `[:http_auth]` (by @ulissesalmeida)
- * Now the `sign_out_via` default is `:delete` (by @ulissesalmeida)
-* improvements
- * Avoids extra computation of friendly token for confirmation token (by @sbc100)
-
-### 4.0.3 - 2016-05-15
-
- * bug fixes
- * Fix overwriting the remember_token when a valid one already exists (by @ralinchimev).
-
-### 4.0.2 - 2016-05-02
+### 5.0.0.rc - 2025-12-31
-* bug fixes
- * Fix strategy checking in `Lockable#unlock_strategy_enabled?` for `:none`
- and `:undefined` strategies. (by @f3ndot)
+* breaking changes
+ * Drop support to Ruby < 2.7
+ * Drop support to Rails < 7.0
+ * Remove deprecated `:bypass` option from `sign_in` helper, use `bypass_sign_in` instead. [#5803](https://github.com/heartcombo/devise/pull/5803)
+ * Remove deprecated `devise_error_messages!` helper, use `render "devise/shared/error_messages", resource: resource` instead. [#5803](https://github.com/heartcombo/devise/pull/5803)
+ * Remove deprecated `scope` second argument from `sign_in(resource, :admin)` controller test helper, use `sign_in(resource, scope: :admin)` instead. [#5803](https://github.com/heartcombo/devise/pull/5803)
+ * Remove deprecated `Devise::TestHelpers`, use `Devise::Test::ControllerHelpers` instead. [#5803](https://github.com/heartcombo/devise/pull/5803)
+ * Remove deprecated `Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION` [#5598](https://github.com/heartcombo/devise/pull/5598)
+ * Remove deprecated `Devise.activerecord51?` method.
+ * Remove `SecretKeyFinder` and use `app.secret_key_base` as the default secret key for `Devise.secret_key` if a custom `Devise.secret_key` is not provided.
-### 4.0.1 - 2016-04-25
+ This is potentially a breaking change because Devise previously used the following order to find a secret key:
-* bug fixes
- * Fix the e-mail confirmation instructions send when a user updates the email
- address from nil. (by @lmduc)
- * Remove unnecessary `attribute_will_change!` call. (by @cadejscroggins)
- * Consistent `permit!` check. (by @ulissesalmeida)
+ ```
+ app.credentials.secret_key_base > app.secrets.secret_key_base > application.config.secret_key_base > application.secret_key_base
+ ```
-### 4.0.0 - 2016-04-18
+ Now, it always uses `application.secret_key_base`. Make sure you're using the same secret key after the upgrade; otherwise, previously generated tokens for `recoverable`, `lockable`, and `confirmable` will be invalid.
+ [#5645](https://github.com/heartcombo/devise/pull/5645)
+ * Change password instructions button label on devise view from `Send me reset password instructions` to `Send me password reset instructions` [#5515](https://github.com/heartcombo/devise/pull/5515)
+ * Change `
` tags separating form elements to wrapping them in `
` tags [#5494](https://github.com/heartcombo/devise/pull/5494) + * Replace `[data-turbo-cache=false]` with `[data-turbo-temporary]` on `devise/shared/error_messages` partial. This has been [deprecated by Turbo since v7.3.0 (released on Mar 1, 2023)](https://github.com/hotwired/turbo/releases/tag/v7.3.0). -* bug fixes - * Fix the `extend_remember_period` configuration. When set to `false` it does - not update the cookie expiration anymore.(by @ulissesalmeida) - -* deprecations - * Added a warning of default value change in Devise 4.1 for users that uses - the the default configuration of the following configurations: (by @ulissesalmeida) - * `strip_whitespace_keys` - The default will be `[:email]`. - * `skip_session_storage` - The default will be `[:http_auth]`. - * `sign_out_via` - The default will be `:delete`. - * `reconfirmable` - The default will be `true`. - * `email_regexp` - The default will be `/\A[^@\s]+@[^@\s]+\z/`. - * Removed deprecated argument of `Devise::Models::Rememberable#remember_me!` (by @ulissesalmeida) - * Removed deprecated private method Devise::Controllers::Helpers#expire_session_data_after_sign_in! - (by @bogdanvlviv) - -### 4.0.0.rc2 - 2016-03-09 + If you are using an older version of Turbo and the default devise template, you'll need to copy it over to your app and change that back to `[data-turbo-cache=false]`. * enhancements - * Introduced `DeviseController#set_flash_message!` for conditional flash - messages setting to reduce complexity. - * `rails g devise:install` will fail if the app does not have a ORM configured - (by @arjunsharma) - * Support to Rails 5 versioned migrations added. - -* deprecations - * omniauth routes are no longer defined with a wildcard `:provider` parameter, - and provider specific routes are defined instead, so route helpers like `user_omniauth_authorize_path(:github)` are deprecated in favor of `user_github_omniauth_authorize_path`. - You can still use `omniauth_authorize_path(:user, :github)` if you need to - call the helpers dynamically. - -### 4.0.0.rc1 - 2016-02-01 - -* Support added to Rails 5 (by @twalpole). -* Devise no longer supports Rails 3.2 and 4.0. -* Devise no longer supports Ruby 1.9 and 2.0. - -* deprecations - * The `devise_parameter_sanitize` API has changed: - The `for` method was deprecated in favor of `permit`: - - ```ruby - def configure_permitted_parameters - devise_parameter_sanitizer.for(:sign_up) << :subscribe_newsletter - # Should become the following. - devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter]) - end - ``` + * Add Rails 8 support. + - Routes are lazy-loaded by default in test and development environments now so Devise loads them before `Devise.mappings` call. [#5728](https://github.com/heartcombo/devise/pull/5728) + * New apps using Rack 3.1+ will be generated using `config.responder.error_status = :unprocessable_content`, since [`:unprocessable_entity` has been deprecated by Rack](https://github.com/rack/rack/pull/2137). - The customization through instance methods on the sanitizer implementation - should be done through it's `initialize` method: + Latest versions of [Rails transparently convert `:unprocessable_entity` -> `:unprocessable_content`](https://github.com/rails/rails/pull/53383), and Devise will use that in the failure app to avoid Rack deprecation warnings for apps that are configured with `:unprocessable_entity`. They can also simply change their `error_status` to `:unprocessable_content` in latest Rack versions to avoid the warning. + * Add Ruby 3.4 and 4.0 support. + * Reenable Mongoid test suite across all Rails 7+ versions, to ensure we continue supporting it. Changes to dirty tracking to support Mongoid 8.0+. [#5568](https://github.com/heartcombo/devise/pull/5568) + * Password length validator is changed from - ```ruby - class User::ParameterSanitizer < Devise::ParameterSanitizer - def sign_up - default_params.permit(:username, :email) - end - end + ``` + validates_length_of :password, within: password_length, allow_blank: true` + ``` - # The `sign_up` method can be a `permit` call on the sanitizer `initialize`. + to - class User::ParameterSanitizer < Devise::ParameterSanitizer - def initialize(*) - super - permit(:sign_up, keys: [:username, :email]) - end - end ``` + validates_length_of :password, minimum: proc { password_length.min }, maximum: proc { password_length.max }, allow_blank: true + ``` + + so it's possible to override `password_length` at runtime. [#5734](https://github.com/heartcombo/devise/pull/5734) + +* bug fixes + * Make `Devise` work without `ActionMailer` when `Zeitwerk` autoloader is used. [#5731](https://github.com/heartcombo/devise/pull/5731) + * Handle defaults `:from` and `:reply_to` as procs correctly by delegating to Rails [#5595](https://github.com/heartcombo/devise/pull/5595) + * Use `OmniAuth.config.allowed_request_methods` as routing verbs for the auth path [#5508](https://github.com/heartcombo/devise/pull/5508) + * Handle `on` and `ON` as true values to check params [#5514](https://github.com/heartcombo/devise/pull/5514) + * Fix passing `format` option to `devise_for` [#5732](https://github.com/heartcombo/devise/pull/5732) + * Use `ActiveRecord::SecurityUtils.secure_compare` in `Devise.secure_compare` to match two empty strings correctly. [#4829](https://github.com/heartcombo/devise/pull/4829) + * Respond with `401 Unauthorized` for non-navigational requests to destroy the session when there is no authenticated resource. [#4878](https://github.com/heartcombo/devise/pull/4878) + * Fix incorrect grammar of invalid authentication message with capitalized attributes, e.g.: "Invalid Email or password" => "Invalid email or password". (originally introduced by [#4014](https://github.com/heartcombo/devise/pull/4014), released on v4.1.0) [#4834](https://github.com/heartcombo/devise/pull/4834) - You can check more examples and explanations on the [README section](/plataformatec/devise#strong-parameters) - and on the [ParameterSanitizer docs](lib/devise/parameter_sanitizer.rb). -Please check [3-stable](https://github.com/plataformatec/devise/blob/3-stable/CHANGELOG.md) +Please check [4-stable](https://github.com/heartcombo/devise/blob/4-stable/CHANGELOG.md) for previous changes. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index cae2742e1..3fc1d0982 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -17,6 +17,6 @@ Project maintainers have the right and responsibility to remove, edit, or reject This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by sending an email to [conduct@plataformatec.com.br](conduct@plataformatec.com.br) or contacting one or more of the project maintainers. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by sending an email to [heartcombo.oss@gmail.com](heartcombo.oss@gmail.com) or contacting one or more of the project maintainers. -This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) +This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org), version 1.2.0, available at [https://contributor-covenant.org/version/1/2/0/](https://contributor-covenant.org/version/1/2/0/) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fb9dd7ad4..6327e4ddb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ expected to follow our [Code of Conduct](CODE_OF_CONDUCT.md). ## Reporting Issues Before reporting a new issue, please be sure that the issue wasn't already -reported or fixed by searching on GitHub through our [issues](https://github.com/plataformatec/devise/issues). +reported or fixed by searching on GitHub through our [issues](https://github.com/heartcombo/devise/issues). When creating a new issue, be sure to include a **title and clear description**, as much relevant information as possible, and either a test case example or @@ -22,15 +22,15 @@ Please do not attempt to translate Devise built in views. The views are meant to be a starting point for fresh apps and not production material - eventually all applications will require custom views where you can write your own copy and translate it if the application requires it . For historical references, please look into closed -[Issues/Pull Requests](https://github.com/plataformatec/devise/issues?q=i18n) regarding +[Issues/Pull Requests](https://github.com/heartcombo/devise/issues?q=i18n) regarding internationalization. Avoid opening new issues to ask questions in our issues tracker. Please go through the project wiki, documentation and source code first, or try to ask your question -on [Stack Overflow](http://stackoverflow.com/questions/tagged/devise). +on [Stack Overflow](https://stackoverflow.com/questions/tagged/devise). **If you find a security bug, do not report it through GitHub. Please send an -e-mail to [opensource@plataformatec.com.br](mailto:opensource@plataformatec.com.br) +e-mail to [heartcombo.oss@gmail.com](mailto:heartcombo.oss@gmail.com) instead.** ## Sending Pull Requests @@ -50,7 +50,7 @@ are beneficial to a wide range of use cases or it's an application specific chan that might not be so valuable to other applications. Some changes can be introduced as a new `devise-something` gem instead of belonging to the main codebase. -When adding new settings, you can take advantage of the [`Devise::Models.config`](https://github.com/plataformatec/devise/blob/245b1f9de0b3386b7913e14b60ea24f43b77feb0/lib/devise/models.rb#L13-L50) method to add class and instance level fallbacks +When adding new settings, you can take advantage of the [`Devise::Models.config`](https://github.com/heartcombo/devise/blob/245b1f9de0b3386b7913e14b60ea24f43b77feb0/lib/devise/models.rb#L13-L50) method to add class and instance level fallbacks to the new setting. We also welcome Pull Requests that improve our existing documentation (both our @@ -64,9 +64,9 @@ open issues to help troubleshoot and fix existing bugs on Devise. Here is what you can do: * Help ensure that existing issues follows the recommendations from the -_[Reporting Issues](#reporting-issues)_ section, providing feeback to the issue's +_[Reporting Issues](#reporting-issues)_ section, providing feedback to the issue's author on what might be missing. -* Review and update the existing content of our [Wiki](https://github.com/plataformatec/devise/wiki) +* Review and update the existing content of our [Wiki](https://github.com/heartcombo/devise/wiki) with up to date instructions and code samples - the wiki was grown with several different tutorials and references that we can't keep track of everything, so if there is a page that showcases an integration or customization that you are diff --git a/Gemfile b/Gemfile index dc7b6b4ae..3fc8499f9 100644 --- a/Gemfile +++ b/Gemfile @@ -1,40 +1,33 @@ +# frozen_string_literal: true + source "https://rubygems.org" gemspec -gem "rails", "~> 5.1" -gem "omniauth", "~> 1.3" -gem "oauth2" +gem "omniauth" gem "omniauth-oauth2" +gem "rails", "~> 8.1.0" gem "rdoc" -gem "activemodel-serializers-xml", github: "rails/activemodel-serializers-xml" - gem "rails-controller-testing" -gem "responders", "~> 2.1" - -# TODO: Remove this line when Rails 5.1.1 is released -gem "minitest", "< 5.10.2" +gem "responders", "~> 3.1" group :test do + gem "minitest", "< 6" + gem "mocha", "~> 2.1", require: false gem "omniauth-facebook" gem "omniauth-openid" - gem "webrat", "0.7.3", require: false - gem "mocha", "~> 1.1", require: false -end - -platforms :jruby do - gem "activerecord-jdbc-adapter" - gem "activerecord-jdbcsqlite3-adapter" - gem "jruby-openssl" + gem "rexml" + gem "timecop" + gem "webrat" + gem "ostruct" end platforms :ruby do gem "sqlite3" end -# TODO: -# group :mongoid do -# gem "mongoid", "~> 4.0.0" -# end +group :mongoid do + gem "mongoid", "~> 9.0", github: "mongodb/mongoid", branch: "9.0-stable" +end diff --git a/Gemfile.lock b/Gemfile.lock index 9b012392a..a6fdb5a71 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,194 +1,314 @@ GIT - remote: git://github.com/rails/activemodel-serializers-xml.git - revision: dd9c0acf26aab111ebc647cd8deb99ebc6946531 + remote: https://github.com/mongodb/mongoid.git + revision: 0623af687a234392ed4b8872f474a9208b908500 + branch: 9.0-stable specs: - activemodel-serializers-xml (1.0.1) - activemodel (> 5.x) - activesupport (> 5.x) - builder (~> 3.1) + mongoid (9.0.10) + activemodel (>= 5.1, < 8.2, != 7.0.0) + concurrent-ruby (>= 1.0.5, < 2.0) + mongo (>= 2.18.0, < 3.0.0) PATH remote: . specs: - devise (4.3.0) + devise (5.0.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 4.1.0, < 5.2) + railties (>= 7.0) responders warden (~> 1.2.3) GEM remote: https://rubygems.org/ specs: - actioncable (5.1.0) - actionpack (= 5.1.0) + action_text-trix (2.1.18) + railties + actioncable (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) nio4r (~> 2.0) - websocket-driver (~> 0.6.1) - actionmailer (5.1.0) - actionpack (= 5.1.0) - actionview (= 5.1.0) - activejob (= 5.1.0) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 2.0) - actionpack (5.1.0) - actionview (= 5.1.0) - activesupport (= 5.1.0) - rack (~> 2.0) - rack-test (~> 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.1.0) - activesupport (= 5.1.0) + websocket-driver (>= 0.6.1) + zeitwerk (~> 2.6) + actionmailbox (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) + mail (>= 2.8.0) + actionmailer (8.1.3) + actionpack (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activesupport (= 8.1.3) + mail (>= 2.8.0) + rails-dom-testing (~> 2.2) + actionpack (8.1.3) + actionview (= 8.1.3) + activesupport (= 8.1.3) + nokogiri (>= 1.8.5) + rack (>= 2.2.4) + rack-session (>= 1.0.1) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + useragent (~> 0.16) + actiontext (8.1.3) + action_text-trix (~> 2.1.15) + actionpack (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (8.1.3) + activesupport (= 8.1.3) builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.1.0) - activesupport (= 5.1.0) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (8.1.3) + activesupport (= 8.1.3) globalid (>= 0.3.6) - activemodel (5.1.0) - activesupport (= 5.1.0) - activerecord (5.1.0) - activemodel (= 5.1.0) - activesupport (= 5.1.0) - arel (~> 8.0) - activesupport (5.1.0) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (~> 0.7) - minitest (~> 5.1) - tzinfo (~> 1.1) - arel (8.0.0) - bcrypt (3.1.11) - builder (3.2.3) - concurrent-ruby (1.0.5) - erubi (1.6.0) - faraday (0.11.0) - multipart-post (>= 1.2, < 3) - globalid (0.4.0) - activesupport (>= 4.2.0) - hashie (3.5.5) - i18n (0.8.1) - jwt (1.5.6) - loofah (2.0.3) - nokogiri (>= 1.5.9) - mail (2.6.5) - mime-types (>= 1.16, < 4) - metaclass (0.0.4) - method_source (0.8.2) - mime-types (3.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2016.0521) - mini_portile2 (2.1.0) - minitest (5.10.1) - mocha (1.2.1) - metaclass (~> 0.0.1) - multi_json (1.12.1) - multi_xml (0.6.0) - multipart-post (2.0.0) - nio4r (2.0.0) - nokogiri (1.7.1) - mini_portile2 (~> 2.1.0) - oauth2 (1.3.1) - faraday (>= 0.8, < 0.12) - jwt (~> 1.0) - multi_json (~> 1.3) + activemodel (8.1.3) + activesupport (= 8.1.3) + activerecord (8.1.3) + activemodel (= 8.1.3) + activesupport (= 8.1.3) + timeout (>= 0.4.0) + activestorage (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activesupport (= 8.1.3) + marcel (~> 1.0) + activesupport (8.1.3) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + json + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + base64 (0.3.0) + bcrypt (3.1.22) + bigdecimal (4.0.1) + bson (5.2.0) + builder (3.3.0) + concurrent-ruby (1.3.6) + connection_pool (3.0.2) + crass (1.0.6) + date (3.5.1) + drb (2.2.3) + erb (6.0.2) + erubi (1.13.1) + faraday (2.14.1) + faraday-net_http (>= 2.0, < 3.5) + json + logger + faraday-net_http (3.4.2) + net-http (~> 0.5) + globalid (1.3.0) + activesupport (>= 6.1) + hashie (5.1.0) + logger + i18n (1.14.8) + concurrent-ruby (~> 1.0) + io-console (0.8.2) + irb (1.17.0) + pp (>= 0.6.0) + prism (>= 1.3.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + json (2.19.3) + jwt (3.1.2) + base64 + logger (1.7.0) + loofah (2.25.1) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.9.0) + logger + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.1.0) + mini_mime (1.1.5) + mini_portile2 (2.8.9) + minitest (5.27.0) + mocha (2.8.2) + ruby2_keywords (>= 0.0.5) + mongo (2.23.0) + base64 + bson (>= 4.14.1, < 6.0.0) + multi_xml (0.8.1) + bigdecimal (>= 3.1, < 5) + net-http (0.9.1) + uri (>= 0.11.1) + net-imap (0.6.3) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.5.1) + net-protocol + nio4r (2.7.5) + nokogiri (1.19.2) + mini_portile2 (~> 2.8.2) + racc (~> 1.4) + oauth2 (2.0.18) + faraday (>= 0.17.3, < 4.0) + jwt (>= 1.0, < 4.0) + logger (~> 1.2) multi_xml (~> 0.5) - rack (>= 1.2, < 3) - omniauth (1.6.1) - hashie (>= 3.4.6, < 3.6.0) - rack (>= 1.6.2, < 3) - omniauth-facebook (4.0.0) - omniauth-oauth2 (~> 1.2) - omniauth-oauth2 (1.4.0) - oauth2 (~> 1.0) - omniauth (~> 1.2) - omniauth-openid (1.0.1) - omniauth (~> 1.0) - rack-openid (~> 1.3.1) + rack (>= 1.2, < 4) + snaky_hash (~> 2.0, >= 2.0.3) + version_gem (~> 1.1, >= 1.1.9) + omniauth (2.1.4) + hashie (>= 3.4.6) + logger + rack (>= 2.2.3) + rack-protection + omniauth-facebook (10.0.0) + bigdecimal + omniauth-oauth2 (>= 1.2, < 3) + omniauth-oauth2 (1.9.0) + oauth2 (>= 2.0.2, < 3) + omniauth (~> 2.0) + omniauth-openid (2.0.2) + omniauth (>= 1.1) + rack-openid (~> 1.4) + ruby-openid (~> 2.1, >= 2.1.8) + version_gem (~> 1.1, >= 1.1.8) orm_adapter (0.5.0) - rack (2.0.1) - rack-openid (1.3.1) + ostruct (0.6.3) + pp (0.6.3) + prettyprint + prettyprint (0.2.0) + prism (1.9.0) + psych (5.3.1) + date + stringio + racc (1.8.1) + rack (3.2.5) + rack-openid (1.4.2) rack (>= 1.1.0) ruby-openid (>= 2.1.8) - rack-test (0.6.3) - rack (>= 1.0) - rails (5.1.0) - actioncable (= 5.1.0) - actionmailer (= 5.1.0) - actionpack (= 5.1.0) - actionview (= 5.1.0) - activejob (= 5.1.0) - activemodel (= 5.1.0) - activerecord (= 5.1.0) - activesupport (= 5.1.0) - bundler (>= 1.3.0, < 2.0) - railties (= 5.1.0) - sprockets-rails (>= 2.0.0) - rails-controller-testing (1.0.1) - actionpack (~> 5.x) - actionview (~> 5.x) - activesupport (~> 5.x) - rails-dom-testing (2.0.2) - activesupport (>= 4.2.0, < 6.0) - nokogiri (~> 1.6) - rails-html-sanitizer (1.0.3) - loofah (~> 2.0) - railties (5.1.0) - actionpack (= 5.1.0) - activesupport (= 5.1.0) - method_source - rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) - rake (12.0.0) - rdoc (5.1.0) - responders (2.4.0) - actionpack (>= 4.2.0, < 5.3) - railties (>= 4.2.0, < 5.3) - ruby-openid (2.7.0) - sprockets (3.7.1) + rack-protection (4.2.1) + base64 (>= 0.1.0) + logger (>= 1.6.0) + rack (>= 3.0.0, < 4) + rack-session (2.1.1) + base64 (>= 0.1.0) + rack (>= 3.0.0) + rack-test (2.2.0) + rack (>= 1.3) + rackup (2.3.1) + rack (>= 3) + rails (8.1.3) + actioncable (= 8.1.3) + actionmailbox (= 8.1.3) + actionmailer (= 8.1.3) + actionpack (= 8.1.3) + actiontext (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activemodel (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) + bundler (>= 1.15.0) + railties (= 8.1.3) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) + rails-dom-testing (2.3.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.7.0) + loofah (~> 2.25) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) + railties (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) + irb (~> 1.13) + rackup (>= 1.0.0) + rake (>= 12.2) + thor (~> 1.0, >= 1.2.2) + tsort (>= 0.2) + zeitwerk (~> 2.6) + rake (13.3.1) + rdoc (7.2.0) + erb + psych (>= 4.0.0) + tsort + reline (0.6.3) + io-console (~> 0.5) + responders (3.2.0) + actionpack (>= 7.0) + railties (>= 7.0) + rexml (3.4.4) + ruby-openid (2.9.2) + ruby2_keywords (0.0.5) + securerandom (0.4.1) + snaky_hash (2.0.3) + hashie (>= 0.1.0, < 6) + version_gem (>= 1.1.8, < 3) + sqlite3 (2.9.2) + mini_portile2 (~> 2.8.0) + stringio (3.2.0) + thor (1.5.0) + timecop (0.9.10) + timeout (0.6.1) + tsort (0.2.0) + tzinfo (2.0.6) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.0) - actionpack (>= 4.0) - activesupport (>= 4.0) - sprockets (>= 3.0.0) - sqlite3 (1.3.13) - thor (0.19.4) - thread_safe (0.3.6) - tzinfo (1.2.3) - thread_safe (~> 0.1) - warden (1.2.7) - rack (>= 1.0) + uri (1.1.1) + useragent (0.16.11) + version_gem (1.1.9) + warden (1.2.9) + rack (>= 2.0.9) webrat (0.7.3) nokogiri (>= 1.2.0) rack (>= 1.0) rack-test (>= 0.5.3) - websocket-driver (0.6.5) + websocket-driver (0.8.0) + base64 websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.2) + websocket-extensions (0.1.5) + zeitwerk (2.7.5) PLATFORMS ruby DEPENDENCIES - activemodel-serializers-xml! - activerecord-jdbc-adapter - activerecord-jdbcsqlite3-adapter devise! - jruby-openssl - minitest (< 5.10.2) - mocha (~> 1.1) - oauth2 - omniauth (~> 1.3) + minitest (< 6) + mocha (~> 2.1) + mongoid (~> 9.0)! + omniauth omniauth-facebook omniauth-oauth2 omniauth-openid - rails (~> 5.1) + ostruct + rails (~> 8.1.0) rails-controller-testing rdoc - responders (~> 2.1) + responders (~> 3.1) + rexml sqlite3 - webrat (= 0.7.3) + timecop + webrat BUNDLED WITH - 1.14.6 + 4.0.3 diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..445eedba5 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,20 @@ +## Pre-check + +- Do not use the issues tracker for help or support, try Stack Overflow. +- For bugs, do a quick search and make sure the bug has not yet been reported +- If you found a security bug, do not report it through GitHub. Please send an e-mail to heartcombo.oss@gmail.com instead. +- Finally, be nice and have fun! + +## Environment + +- Ruby **[version]** +- Rails **[version]** +- Devise **[version]** + +## Current behavior + +Include code samples, errors, steps to reproduce the error and stack traces if appropriate. + +Will be even more helpful if you provide a sample application or a test case that reproduces the error. + +## Expected behavior diff --git a/MIT-LICENSE b/MIT-LICENSE index 73b88e91c..ad599708f 100644 --- a/MIT-LICENSE +++ b/MIT-LICENSE @@ -1,4 +1,5 @@ -Copyright 2009-2017 Plataformatec. http://plataformatec.com.br +Copyright (c) 2020-CURRENT Rafael França, Carlos Antonio da Silva +Copyright (c) 2009-2019 Plataformatec Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 19c9d6a30..37e2d3160 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,4 @@ - - -By [Plataformatec](http://plataformatec.com.br/). - -[](http://travis-ci.org/plataformatec/devise) -[](https://codeclimate.com/github/plataformatec/devise) - -This README is [also available in a friendly navigable format](http://devise.plataformatec.com.br/). + Devise is a flexible authentication solution for Rails based on Warden. It: @@ -16,16 +9,55 @@ Devise is a flexible authentication solution for Rails based on Warden. It: It's composed of 10 modules: -* [Database Authenticatable](http://rubydoc.info/github/plataformatec/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. -* [Omniauthable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds OmniAuth (https://github.com/omniauth/omniauth) support. -* [Confirmable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in. -* [Recoverable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Recoverable): resets the user password and sends reset instructions. -* [Registerable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Registerable): handles signing up users through a registration process, also allowing them to edit and destroy their account. -* [Rememberable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Rememberable): manages generating and clearing a token for remembering the user from a saved cookie. -* [Trackable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Trackable): tracks sign in count, timestamps and IP address. -* [Timeoutable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Timeoutable): expires sessions that have not been active in a specified period of time. -* [Validatable](http://rubydoc.info/github/plataformatec/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. -* [Lockable](http://rubydoc.info/github/plataformatec/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. +* [Database Authenticatable](https://www.rubydoc.info/gems/devise/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. +* [Omniauthable](https://www.rubydoc.info/gems/devise/Devise/Models/Omniauthable): adds OmniAuth (https://github.com/omniauth/omniauth) support. +* [Confirmable](https://www.rubydoc.info/gems/devise/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in. +* [Recoverable](https://www.rubydoc.info/gems/devise/Devise/Models/Recoverable): resets the user password and sends reset instructions. +* [Registerable](https://www.rubydoc.info/gems/devise/Devise/Models/Registerable): handles signing up users through a registration process, also allowing them to edit and destroy their account. +* [Rememberable](https://www.rubydoc.info/gems/devise/Devise/Models/Rememberable): manages generating and clearing a token for remembering the user from a saved cookie. +* [Trackable](https://www.rubydoc.info/gems/devise/Devise/Models/Trackable): tracks sign in count, timestamps and IP address. +* [Timeoutable](https://www.rubydoc.info/gems/devise/Devise/Models/Timeoutable): expires sessions that have not been active in a specified period of time. +* [Validatable](https://www.rubydoc.info/gems/devise/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. +* [Lockable](https://www.rubydoc.info/gems/devise/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. + +## Table of Contents + + + +- [Information](#information) + - [The Devise wiki](#the-devise-wiki) + - [Bug reports](#bug-reports) + - [StackOverflow and Mailing List](#stackoverflow-and-mailing-list) + - [RDocs](#rdocs) + - [Example applications](#example-applications) + - [Extensions](#extensions) + - [Supported Ruby / Rails versions](#supported-ruby--rails-versions) + - [Contributing](#contributing) +- [Starting with Rails?](#starting-with-rails) +- [Getting started](#getting-started) + - [Controller filters and helpers](#controller-filters-and-helpers) + - [Configuring Models](#configuring-models) + - [Strong Parameters](#strong-parameters) + - [Configuring views](#configuring-views) + - [Configuring controllers](#configuring-controllers) + - [Configuring routes](#configuring-routes) + - [I18n](#i18n) + - [Test helpers](#test-helpers) + - [Controller tests](#controller-tests) + - [Integration tests](#integration-tests) + - [OmniAuth](#omniauth) + - [Configuring multiple models](#configuring-multiple-models) + - [Active Job Integration](#active-job-integration) + - [Password reset tokens and Rails logs](#password-reset-tokens-and-rails-logs) + - [Other ORMs](#other-orms) + - [Rails API mode](#rails-api-mode) +- [Additional information](#additional-information) + - [Warden](#warden) +- [License](#license) + + + + ## Information @@ -33,31 +65,32 @@ It's composed of 10 modules: The Devise Wiki has lots of additional information about Devise including many "how-to" articles and answers to the most frequently asked questions. Please browse the Wiki after finishing this README: -https://github.com/plataformatec/devise/wiki +https://github.com/heartcombo/devise/wiki ### Bug reports If you discover a problem with Devise, we would like to know about it. However, we ask that you please review these guidelines before submitting a bug report: -https://github.com/plataformatec/devise/wiki/Bug-reports +https://github.com/heartcombo/devise/wiki/Bug-reports -If you have discovered a security related bug, please do *NOT* use the GitHub issue tracker. Send an email to opensource@plataformatec.com.br. +If you have discovered a security related bug, please do *NOT* use the GitHub issue tracker. Send an email to heartcombo.oss@gmail.com. ### StackOverflow and Mailing List If you have any questions, comments, or concerns, please use StackOverflow instead of the GitHub issue tracker: -http://stackoverflow.com/questions/tagged/devise +https://stackoverflow.com/questions/tagged/devise -The deprecated mailing list can still be read on +The deprecated mailing lists can still be read on: https://groups.google.com/group/plataformatec-devise +https://groups.google.com/group/heartcombo ### RDocs You can view the Devise documentation in RDoc format here: -http://rubydoc.info/github/plataformatec/devise/master/frames +https://rubydoc.info/github/heartcombo/devise/main/frames 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. @@ -65,46 +98,99 @@ If you need to use Devise with previous versions of Rails, you can always run "g There are a few example applications available on GitHub that demonstrate various features of Devise with different versions of Rails. You can view them here: -https://github.com/plataformatec/devise/wiki/Example-Applications +https://github.com/heartcombo/devise/wiki/Example-Applications ### Extensions Our community has created a number of extensions that add functionality above and beyond what is included with Devise. You can view a list of available extensions and add your own here: -https://github.com/plataformatec/devise/wiki/Extensions +https://github.com/heartcombo/devise/wiki/Extensions + +### Supported Ruby / Rails versions + +We intend to maintain support for all Ruby / Rails versions that haven't reached end-of-life. + +For more information about specific versions please check [Ruby](https://www.ruby-lang.org/en/downloads/branches/) +and [Rails](https://guides.rubyonrails.org/maintenance_policy.html) maintenance policies, and our test matrix. ### Contributing We hope that you will consider contributing to Devise. Please read this short overview for some information about how to get started: -https://github.com/plataformatec/devise/wiki/Contributing +https://github.com/heartcombo/devise/wiki/Contributing + +You will usually want to write tests for your changes. To run the test suite, go into Devise's top-level directory and run `bundle install` and `bin/test`. +Devise works with multiple Ruby and Rails versions, and ActiveRecord and Mongoid ORMs, which means you can run the test suite with some modifiers: `DEVISE_ORM` and `BUNDLE_GEMFILE`. + +#### DEVISE_ORM +Since Devise supports both Mongoid and ActiveRecord, we rely on this variable to run specific code for each ORM. +The default value of `DEVISE_ORM` is `active_record`. To run the tests for Mongoid, you can pass `mongoid`: +``` +DEVISE_ORM=mongoid bin/test + +==> Devise.orm = :mongoid +``` +When running the tests for Mongoid, you will need to have a MongoDB server (version 2.0 or newer) running on your system. + +Please note that the command output will show the variable value being used. + +#### BUNDLE_GEMFILE +We can use this variable to tell bundler what Gemfile it should use (instead of the one in the current directory). +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. +For example, if the tests broke using Ruby 3.4 and Rails 8.0, you can do the following: +```bash +chruby 3.4.0 # or rbenv shell 3.4.0, or rvm use 3.4.0, etc. +BUNDLE_GEMFILE=gemfiles/Gemfile-rails-8-0 bundle install +BUNDLE_GEMFILE=gemfiles/Gemfile-rails-8-0 bin/test +``` + +You can also combine both of them if the tests broke for Mongoid: +```bash +BUNDLE_GEMFILE=gemfiles/Gemfile-rails-8-0 bundle install +BUNDLE_GEMFILE=gemfiles/Gemfile-rails-8-0 DEVISE_ORM=mongoid bin/test +``` -You will usually want to write tests for your changes. To run the test suite, go into Devise's top-level directory and run "bundle install" and "rake". For the tests to pass, you will need to have a MongoDB server (version 2.0 or newer) running on your system. +### Running tests +Devise uses [minitest](https://github.com/seattlerb/minitest) as test framework. + +* Running all tests: +```bash +bin/test +``` + +* Running tests for an specific file: +```bash +bin/test test/models/trackable_test.rb +``` + +* Running a specific test given a line number or a regex: +```bash +bin/test test/models/trackable_test.rb:16 +bin/test test/models/trackable_test.rb -n '/update.*record/' +``` ## Starting with Rails? -If you are building your first Rails application, we recommend you *do not* use Devise. Devise requires a good understanding of the Rails Framework. In such cases, we advise you to start a simple authentication system from scratch. Today, we have three resources that should help you get started: +If you are building your first Rails application, we recommend you *do not* use Devise. Devise requires a good understanding of the Rails Framework. In such cases, we advise you to start a simple authentication system from scratch. Here's a few resources that should help you get started: * Michael Hartl's online book: https://www.railstutorial.org/book/modeling_users -* Ryan Bates' Railscast: http://railscasts.com/episodes/250-authentication-from-scratch -* Codecademy's Ruby on Rails: Authentication and Authorization: http://www.codecademy.com/en/learn/rails-auth +* Ryan Bates' Railscasts: http://railscasts.com/episodes/250-authentication-from-scratch and http://railscasts.com/episodes/250-authentication-from-scratch-revised +* Codecademy's Ruby on Rails: Authentication and Authorization: https://www.codecademy.com/learn/rails-auth Once you have solidified your understanding of Rails and authentication mechanisms, we assure you Devise will be very pleasant to work with. :smiley: ## Getting started -Devise 4.0 works with Rails 4.1 onwards. You can add it to your Gemfile with: +Devise 5 works with Rails 7 onwards. Run: -```ruby -gem 'devise' +```sh +bundle add devise ``` -Then run `bundle install` - Next, you need to run the generator: ```console -$ rails generate devise:install +rails generate devise:install ``` At this point, a number of instructions will appear in the console. Among these instructions, you'll need to set up the default URL options for the Devise mailer in each environment. Here is a possible configuration for `config/environments/development.rb`: @@ -119,14 +205,14 @@ The generator will install an initializer which describes ALL of Devise's config In the following command you will replace `MODEL` with the class name used for the application’s users (it’s frequently `User` but could also be `Admin`). This will create a model (if one does not exist) and configure it with the default Devise modules. The generator also configures your `config/routes.rb` file to point to the Devise controller. ```console -$ rails generate devise MODEL +rails generate devise MODEL ``` -Next, check the MODEL for any additional configuration options you might want to add, such as confirmable or lockable. If you add an option, be sure to inspect the migration file (created by the generator if your ORM supports them) and uncomment the appropriate section. For example, if you add the confirmable option in the model, you'll need to uncomment the Confirmable section in the migration. +Next, check the MODEL for any additional configuration options you might want to add, such as confirmable or lockable. If you add an option, be sure to inspect the migration file (created by the generator if your ORM supports them) and uncomment the appropriate section. For example, if you add the confirmable option in the model, you'll need to uncomment the Confirmable section in the migration. Then run `rails db:migrate` -You should restart your application after changing Devise's configuration options. Otherwise, you will run into strange errors, for example, users being unable to login and route helpers being undefined. +You should restart your application after changing Devise's configuration options (this includes stopping spring). Otherwise, you will run into strange errors, for example, users being unable to login and route helpers being undefined. ### Controller filters and helpers @@ -183,16 +269,16 @@ member_session The Devise method in your models also accepts some options to configure its modules. For example, you can choose the cost of the hashing algorithm with: ```ruby -devise :database_authenticatable, :registerable, :confirmable, :recoverable, stretches: 12 +devise :database_authenticatable, :registerable, :confirmable, :recoverable, stretches: 13 ``` Besides `:stretches`, you can define `:pepper`, `:encryptor`, `:confirm_within`, `:remember_for`, `:timeout_in`, `:unlock_in` among other options. For more details, see the initializer file that was created when you invoked the "devise:install" generator described above. This file is usually located at `/config/initializers/devise.rb`. ### Strong Parameters - +The Parameter Sanitizer API has changed for Devise 4 :warning: -*For previous Devise versions see https://github.com/plataformatec/devise/tree/3-stable#strong-parameters* +*For previous Devise versions see https://github.com/heartcombo/devise/tree/3-stable#strong-parameters* When you customize your own views, you may end up adding new attributes to forms. Rails 4 moved the parameter sanitization from the model to the controller, causing Devise to handle this concern at the controller as well. @@ -202,7 +288,7 @@ There are just three actions in Devise that allow any set of parameters to be pa * `sign_up` (`Devise::RegistrationsController#create`) - Permits authentication keys plus `password` and `password_confirmation` * `account_update` (`Devise::RegistrationsController#update`) - Permits authentication keys plus `password`, `password_confirmation` and `current_password` -In case you want to permit additional parameters (the lazy way™), you can do so using a simple before filter in your `ApplicationController`: +In case you want to permit additional parameters (the lazy way™), you can do so using a simple before action in your `ApplicationController`: ```ruby class ApplicationController < ActionController::Base @@ -216,7 +302,21 @@ class ApplicationController < ActionController::Base end ``` -The above works for any additional fields where the parameters are simple scalar types. If you have nested attributes (say you're using `accepts_nested_attributes_for`), then you will need to tell devise about those nestings and types. Devise allows you to completely change Devise defaults or invoke custom behaviour by passing a block: +The above works for any additional fields where the parameters are simple scalar types. If you have nested attributes (say you're using `accepts_nested_attributes_for`), then you will need to tell devise about those nestings and types: + +```ruby +class ApplicationController < ActionController::Base + before_action :configure_permitted_parameters, if: :devise_controller? + + protected + + def configure_permitted_parameters + devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, address_attributes: [:country, :state, :city, :area, :postal_code]]) + end +end +``` + +Devise allows you to completely change Devise defaults or invoke custom behavior by passing a block: To permit simple scalar values for username and email, use this @@ -277,7 +377,7 @@ We built Devise to help you quickly develop an application that uses authenticat Since Devise is an engine, all its views are packaged inside the gem. These views will help you get started, but after some time you may want to change them. If this is the case, you just need to invoke the following generator, and it will copy all views to your application: ```console -$ rails generate devise:views +rails generate devise:views ``` If you have more than one Devise model in your application (such as `User` and `Admin`), you will notice that Devise uses the same views for all models. Fortunately, Devise offers an easy way to customize views. All you need to do is set `config.scoped_views = true` inside the `config/initializers/devise.rb` file. @@ -285,14 +385,14 @@ If you have more than one Devise model in your application (such as `User` and ` After doing so, you will be able to have views based on the role like `users/sessions/new` and `admins/sessions/new`. If no view is found within the scope, Devise will use the default view at `devise/sessions/new`. You can also use the generator to generate scoped views: ```console -$ rails generate devise:views users +rails generate devise:views users ``` If you would like to generate only a few sets of views, like the ones for the `registerable` and `confirmable` module, -you can pass a list of modules to the generator with the `-v` flag. +you can pass a list of views to the generator with the `-v` flag. ```console -$ rails generate devise:views -v registrations confirmations +rails generate devise:views -v registrations confirmations ``` ### Configuring controllers @@ -302,7 +402,7 @@ If the customization at the views level is not enough, you can customize each co 1. Create your custom controllers using the generator which requires a scope: ```console - $ rails generate devise:controllers [scope] + rails generate devise:controllers [scope] ``` If you specify `users` as the scope, controllers will be created in `app/controllers/users/`. @@ -317,6 +417,7 @@ If the customization at the views level is not enough, you can customize each co ... end ``` + Use the `-c` flag to specify one or more controllers, for example: `rails generate devise:controllers users -c sessions` 2. Tell the router to use this controller: @@ -324,7 +425,7 @@ If the customization at the views level is not enough, you can customize each co devise_for :users, controllers: { sessions: 'users/sessions' } ``` -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`. +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. 4. Finally, change or extend the desired controller actions. @@ -338,7 +439,7 @@ If the customization at the views level is not enough, you can customize each co end ``` - Or you can simply add new behaviour to it: + Or you can simply add new behavior to it: ```ruby class Users::SessionsController < Devise::SessionsController @@ -362,7 +463,7 @@ Devise also ships with default routes. If you need to customize them, you should 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' } ``` -Be sure to check `devise_for` [documentation](http://www.rubydoc.info/github/plataformatec/devise/master/ActionDispatch/Routing/Mapper%3Adevise_for) for details. +Be sure to check `devise_for` [documentation](https://www.rubydoc.info/gems/devise/ActionDispatch/Routing/Mapper#devise_for-instance_method) for details. 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: @@ -374,6 +475,43 @@ end This way, you tell Devise to use the scope `:user` when "/sign_in" is accessed. Notice `devise_scope` is also aliased as `as` in your router. +Please note: You will still need to add `devise_for` in your routes in order to use helper methods such as `current_user`. + +```ruby +devise_for :users, skip: :all +``` + +### Hotwire/Turbo + +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: + +```ruby +Devise.setup do |config| + # ... + # When using Devise with Hotwire/Turbo, the http status for error responses + # and some redirects must match the following. The default in Devise for existing + # apps is `200 OK` and `302 Found` respectively, but new apps are generated with + # these new defaults that match Hotwire/Turbo behavior. + # Note: These might become the new default in future versions of Devise. + config.responder.error_status = :unprocessable_content # for Rack 3.1 or higher + # config.responder.error_status = :unprocessable_entity # for Rack 3.0 or lower + config.responder.redirect_status = :see_other +end +``` + +**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. + +_Note_: the above statuses configuration may become the default for Devise in a future release. + +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: + +* 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. +* 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. + +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.) + +Make sure to inspect your views looking for those, and change appropriately. + ### I18n 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: @@ -412,7 +550,7 @@ en: Take a look at our locale file to check all available messages. You may also be interested in one of the many translations that are available on our wiki: -https://github.com/plataformatec/devise/wiki/I18n +https://github.com/heartcombo/devise/wiki/I18n Caution: Devise Controllers inherit from ApplicationController. If your app uses multiple locales, you should be sure to set I18n.locale in ApplicationController. @@ -424,12 +562,21 @@ cases/specs. ### Controller tests -Controller tests require that you include `Devise::Test::ControllerHelpers` on +Controller tests require that you include `Devise::Test::IntegrationHelpers` on your test case or its parent `ActionController::TestCase` superclass. +For Rails versions prior to 5, include `Devise::Test::ControllerHelpers` instead, since the superclass +for controller tests was changed to ActionDispatch::IntegrationTest +(for more details, see the [Integration tests](#integration-tests) section). ```ruby class PostsControllerTest < ActionController::TestCase - include Devise::Test::ControllerHelpers + include Devise::Test::IntegrationHelpers # Rails >= 5 +end +``` + +```ruby +class PostsControllerTest < ActionController::TestCase + include Devise::Test::ControllerHelpers # Rails < 5 end ``` @@ -507,9 +654,9 @@ Unlike controller tests, integration tests do not need to supply the `devise.mapping` `env` value, as the mapping can be inferred by the routes that are executed in your tests. -You can read more about testing your Rails 3 - Rails 4 controllers with RSpec in the wiki: +You can read more about testing your Rails controllers with RSpec in the wiki: -* https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-%28and-RSpec%29 +* https://github.com/heartcombo/devise/wiki/How-To:-Test-controllers-with-Rails-(and-RSpec) ### OmniAuth @@ -521,7 +668,7 @@ config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' You can read more about OmniAuth support in the wiki: -* https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview +* https://github.com/heartcombo/devise/wiki/OmniAuth:-Overview ### Configuring multiple models @@ -554,9 +701,9 @@ Alternatively, you can simply run the Devise generator. Keep in mind that those models will have completely different routes. They **do not** and **cannot** share the same controller for sign in, sign out and so on. In case you want to have different roles sharing the same actions, we recommend that you use a role-based approach, by either providing a role column or using a dedicated gem for authorization. -### ActiveJob Integration +### Active Job Integration -If you are using Rails 4.2 and ActiveJob to deliver ActionMailer messages in the +If you are using Active Job to deliver Action Mailer messages in the background through a queuing back-end, you can send Devise emails through your existing queue by overriding the `send_devise_notification` method in your model. @@ -568,12 +715,12 @@ end ### Password reset tokens and Rails logs -If you enable the [Recoverable](http://rubydoc.info/github/plataformatec/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: +If you enable the [Recoverable](https://www.rubydoc.info/gems/devise/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: 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. 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. -Rails sets the production logger level to DEBUG by default. Consider changing your production logger level to WARN if you wish to prevent tokens from being leaked into your logs. In `config/environments/production.rb`: +Rails sets the production logger level to INFO by default. Consider changing your production logger level to WARN if you wish to prevent tokens from being leaked into your logs. In `config/environments/production.rb`: ```ruby config.log_level = :warn @@ -584,32 +731,46 @@ config.log_level = :warn Devise supports ActiveRecord (default) and Mongoid. To select another ORM, simply require it in the initializer file. -## Additional information +### Rails API Mode -### Heroku +Rails 5+ has a built-in [API Mode](https://edgeguides.rubyonrails.org/api_app.html) which optimizes Rails for use as an API (only). Devise is _somewhat_ able to handle applications that are built in this mode without additional modifications in the sense that it should not raise exceptions and the like. But some issues may still arise during `development`/`testing`, as we still don't know the full extent of this compatibility. (For more information, see [issue #4947](https://github.com/heartcombo/devise/issues/4947/)) -Using Devise on Heroku with Ruby on Rails 3.2 requires setting: +#### Supported Authentication Strategies +API-only applications don't support browser-based authentication via cookies, which is devise's default. Yet, devise can still provide authentication out of the box in those cases with the `http_authenticatable` strategy, which uses HTTP Basic Auth and authenticates the user on each request. (For more info, see this wiki article for [How To: Use HTTP Basic Authentication](https://github.com/heartcombo/devise/wiki/How-To:-Use-HTTP-Basic-Authentication)) + +The devise default for HTTP Auth is disabled, so it will need to be enabled in the devise initializer for the database strategy: ```ruby -config.assets.initialize_on_precompile = false +config.http_authenticatable = [:database] ``` -Read more about the potential issues at http://guides.rubyonrails.org/asset_pipeline.html +This restriction does not limit you from implementing custom warden strategies, either in your application or via gem-based extensions for devise. +A common authentication strategy for APIs is token-based authentication. For more information on extending devise to support this type of authentication and others, see the wiki article for [Simple Token Authentication Examples and alternatives](https://github.com/heartcombo/devise/wiki/How-To:-Simple-Token-Authentication-Example#alternatives) or this blog post on [Custom authentication methods with Devise](https://blog.plataformatec.com.br/2019/01/custom-authentication-methods-with-devise/). -### Warden +#### Testing +API Mode changes the order of the middleware stack, and this can cause problems for `Devise::Test::IntegrationHelpers`. This problem usually surfaces as an ```undefined method `[]=' for nil:NilClass``` error when using integration test helpers, such as `#sign_in`. The solution is simply to reorder the middlewares by adding the following to test.rb: -Devise is based on Warden, which is a general Rack authentication framework created by Daniel Neighman. We encourage you to read more about Warden here: +```ruby +Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Cookies +Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Session::CookieStore +``` + +For a deeper understanding of this, review [this issue](https://github.com/heartcombo/devise/issues/4696). -https://github.com/hassox/warden +Additionally be mindful that without views supported, some email-based flows from Confirmable, Recoverable and Lockable are not supported directly at this time. -### Contributors +## Additional information + +### Warden -We have a long list of valued contributors. Check them all at: +Devise is based on Warden, which is a general Rack authentication framework created by Daniel Neighman. We encourage you to read more about Warden here: -https://github.com/plataformatec/devise/graphs/contributors +https://github.com/wardencommunity/warden ## License -MIT License. Copyright 2009-2017 Plataformatec. http://plataformatec.com.br +MIT License. +Copyright 2020-CURRENT Rafael França, Carlos Antonio da Silva. +Copyright 2009-2019 Plataformatec. -You are not granted rights or licenses to the trademarks of Plataformatec, including without limitation the Devise name or logo. +The Devise logo is licensed under [Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License](https://creativecommons.org/licenses/by-nc-nd/4.0/). diff --git a/Rakefile b/Rakefile index bbf716633..6e2ab1802 100644 --- a/Rakefile +++ b/Rakefile @@ -1,4 +1,5 @@ # encoding: UTF-8 +# frozen_string_literal: true require 'bundler/gem_tasks' require 'rake/testtask' diff --git a/app/controllers/devise/confirmations_controller.rb b/app/controllers/devise/confirmations_controller.rb index 4981545a3..39ff669be 100644 --- a/app/controllers/devise/confirmations_controller.rb +++ b/app/controllers/devise/confirmations_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class Devise::ConfirmationsController < DeviseController # GET /resource/confirmation/new def new @@ -25,6 +27,7 @@ def show set_flash_message!(:notice, :confirmed) respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) } else + # TODO: use `error_status` when the default changes to `:unprocessable_entity` / `:unprocessable_content`. respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new } end end diff --git a/app/controllers/devise/omniauth_callbacks_controller.rb b/app/controllers/devise/omniauth_callbacks_controller.rb index d5b2c094e..a9a2c30ea 100644 --- a/app/controllers/devise/omniauth_callbacks_controller.rb +++ b/app/controllers/devise/omniauth_callbacks_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class Devise::OmniauthCallbacksController < DeviseController prepend_before_action { request.env["devise.skip_timeout"] = true } @@ -6,7 +8,7 @@ def passthru end def failure - set_flash_message :alert, :failure, kind: OmniAuth::Utils.camelize(failed_strategy.name), reason: failure_message + set_flash_message! :alert, :failure, kind: OmniAuth::Utils.camelize(failed_strategy.name), reason: failure_message redirect_to after_omniauth_failure_path_for(resource_name) end diff --git a/app/controllers/devise/passwords_controller.rb b/app/controllers/devise/passwords_controller.rb index f4291c76a..68b8dc877 100644 --- a/app/controllers/devise/passwords_controller.rb +++ b/app/controllers/devise/passwords_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class Devise::PasswordsController < DeviseController prepend_before_action :require_no_authentication # Render the #edit only if coming from a reset password email link @@ -34,9 +36,10 @@ def update if resource.errors.empty? resource.unlock_access! if unlockable?(resource) - if Devise.sign_in_after_reset_password + if sign_in_after_reset_password? flash_message = resource.active_for_authentication? ? :updated : :updated_not_active set_flash_message!(:notice, flash_message) + resource.after_database_authentication sign_in(resource_name, resource) else set_flash_message!(:notice, :updated_not_active) @@ -50,7 +53,7 @@ def update protected def after_resetting_password_path_for(resource) - Devise.sign_in_after_reset_password ? after_sign_in_path_for(resource) : new_session_path(resource_name) + sign_in_after_reset_password? ? after_sign_in_path_for(resource) : new_session_path(resource_name) end # The path used after sending reset password instructions @@ -66,6 +69,11 @@ def assert_reset_token_passed end end + # Check if the user should be signed in automatically after resetting the password. + def sign_in_after_reset_password? + resource_class.sign_in_after_reset_password + end + # Check if proper Lockable module methods are present & unlock strategy # allows to unlock resource on password reset def unlockable?(resource) diff --git a/app/controllers/devise/registrations_controller.rb b/app/controllers/devise/registrations_controller.rb index 31ba0887b..79e2b0e81 100644 --- a/app/controllers/devise/registrations_controller.rb +++ b/app/controllers/devise/registrations_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class Devise::RegistrationsController < DeviseController prepend_before_action :require_no_authentication, only: [:new, :create, :cancel] prepend_before_action :authenticate_scope!, only: [:edit, :update, :destroy] @@ -5,7 +7,7 @@ class Devise::RegistrationsController < DeviseController # GET /resource/sign_up def new - build_resource({}) + build_resource yield resource if block_given? respond_with resource end @@ -48,12 +50,9 @@ def update resource_updated = update_resource(resource, account_update_params) yield resource if block_given? if resource_updated - if is_flashing_format? - flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ? - :update_needs_confirmation : :updated - set_flash_message :notice, flash_key - end - bypass_sign_in resource, scope: resource_name + set_flash_message_for_update(resource, prev_unconfirmed_email) + bypass_sign_in resource, scope: resource_name if sign_in_after_change_password? + respond_with resource, location: after_update_path_for(resource) else clean_up_passwords resource @@ -68,7 +67,7 @@ def destroy Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name) set_flash_message! :notice, :destroyed yield resource if block_given? - respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) } + respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name), status: Devise.responder.redirect_status } end # GET /resource/cancel @@ -83,12 +82,6 @@ def cancel protected - def update_needs_confirmation?(resource, previous) - resource.respond_to?(:pending_reconfirmation?) && - resource.pending_reconfirmation? && - previous != resource.unconfirmed_email - end - # By default we want to require a password checks on update. # You can overwrite this method in your own RegistrationsController. def update_resource(resource, params) @@ -97,8 +90,8 @@ def update_resource(resource, params) # Build a devise resource passing in the session. Useful to move # temporary session data to the newly created user. - def build_resource(hash=nil) - self.resource = resource_class.new_with_session(hash || {}, session) + def build_resource(hash = {}) + self.resource = resource_class.new_with_session(hash, session) end # Signs in a user on sign up. You can overwrite this method in your own @@ -110,7 +103,7 @@ def sign_up(resource_name, resource) # The path used after sign up. You need to overwrite this method # in your own RegistrationsController. def after_sign_up_path_for(resource) - after_sign_in_path_for(resource) + after_sign_in_path_for(resource) if is_navigational_format? end # The path used after sign up for inactive accounts. You need to overwrite @@ -125,7 +118,7 @@ def after_inactive_sign_up_path_for(resource) # The default url to be used after updating a resource. You need to overwrite # this method in your own RegistrationsController. def after_update_path_for(resource) - signed_in_root_path(resource) + sign_in_after_change_password? ? signed_in_root_path(resource) : new_session_path(resource_name) end # Authenticates the current scope and gets the current resource from the session. @@ -134,6 +127,13 @@ def authenticate_scope! self.resource = send(:"current_#{resource_name}") end + # Check if the user should be signed in automatically after updating the password. + def sign_in_after_change_password? + return true if account_update_params[:password].blank? + + resource_class.sign_in_after_change_password + end + def sign_up_params devise_parameter_sanitizer.sanitize(:sign_up) end @@ -145,4 +145,25 @@ def account_update_params def translation_scope 'devise.registrations' end + + private + + def set_flash_message_for_update(resource, prev_unconfirmed_email) + return unless is_flashing_format? + + flash_key = if update_needs_confirmation?(resource, prev_unconfirmed_email) + :update_needs_confirmation + elsif sign_in_after_change_password? + :updated + else + :updated_but_not_signed_in + end + set_flash_message :notice, flash_key + end + + def update_needs_confirmation?(resource, previous) + resource.respond_to?(:pending_reconfirmation?) && + resource.pending_reconfirmation? && + previous != resource.unconfirmed_email + end end diff --git a/app/controllers/devise/sessions_controller.rb b/app/controllers/devise/sessions_controller.rb index d0ddf7506..41b74f39c 100644 --- a/app/controllers/devise/sessions_controller.rb +++ b/app/controllers/devise/sessions_controller.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + class Devise::SessionsController < DeviseController prepend_before_action :require_no_authentication, only: [:new, :create] prepend_before_action :allow_params_authentication!, only: :create prepend_before_action :verify_signed_out_user, only: :destroy - prepend_before_action only: [:create, :destroy] { request.env["devise.skip_timeout"] = true } + prepend_before_action(only: [:create, :destroy]) { request.env["devise.skip_timeout"] = true } # GET /resource/sign_in def new @@ -26,7 +28,7 @@ def destroy signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)) set_flash_message! :notice, :signed_out if signed_out yield if block_given? - respond_to_on_destroy + respond_to_on_destroy(non_navigational_status: :no_content) end protected @@ -43,7 +45,7 @@ def serialize_options(resource) end def auth_options - { scope: resource_name, recall: "#{controller_path}#new" } + { scope: resource_name, recall: "#{controller_path}#new", locale: I18n.locale } end def translation_scope @@ -60,7 +62,7 @@ def verify_signed_out_user if all_signed_out? set_flash_message! :notice, :already_signed_out - respond_to_on_destroy + respond_to_on_destroy(non_navigational_status: :unauthorized) end end @@ -70,12 +72,12 @@ def all_signed_out? users.all?(&:blank?) end - def respond_to_on_destroy + def respond_to_on_destroy(non_navigational_status: :no_content) # We actually need to hardcode this as Rails default responder doesn't # support returning empty response on GET request respond_to do |format| - format.all { head :no_content } - format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name) } + format.all { head non_navigational_status } + format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name), status: Devise.responder.redirect_status } end end end diff --git a/app/controllers/devise/unlocks_controller.rb b/app/controllers/devise/unlocks_controller.rb index 179c9525f..8cff126c9 100644 --- a/app/controllers/devise/unlocks_controller.rb +++ b/app/controllers/devise/unlocks_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class Devise::UnlocksController < DeviseController prepend_before_action :require_no_authentication @@ -27,6 +29,7 @@ def show set_flash_message! :notice, :unlocked respond_with_navigational(resource){ redirect_to after_unlock_path_for(resource) } else + # TODO: use `error_status` when the default changes to `:unprocessable_entity` / `:unprocessable_content`. respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new } end end diff --git a/app/controllers/devise_controller.rb b/app/controllers/devise_controller.rb index 0679a62e6..1c3b41626 100644 --- a/app/controllers/devise_controller.rb +++ b/app/controllers/devise_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # All Devise controllers are inherited from here. class DeviseController < Devise.parent_controller.constantize include Devise::Controllers::ScopedViews @@ -13,6 +15,7 @@ class DeviseController < Devise.parent_controller.constantize end prepend_before_action :assert_is_devise_resource! + self.responder = Devise.responder respond_to :html if mimes_for_respond_to.empty? # Override prefixes to consider the scoped view. @@ -20,7 +23,7 @@ class DeviseController < Devise.parent_controller.constantize # Action Controller tests that forces _prefixes to be # loaded before even having a request object. # - # This method should be public as it is is in ActionPack + # This method should be public as it is in ActionPack # itself. Changing its visibility may break other gems. def _prefixes #:nodoc: @_prefixes ||= if self.class.scoped_views? && request && devise_mapping @@ -30,6 +33,19 @@ def _prefixes #:nodoc: end end + # Override internal methods to exclude `_prefixes` from action methods since + # we override it above. + # + # There was an intentional change in Rails 7.1 that will allow it to become + # an action method because it's a public method of a non-abstract controller, + # but we also can't make this abstract because it can affect potential actions + # defined in the parent controller, so instead we ensure `_prefixes` is going + # to be considered internal. (and thus, won't become an action method.) + # Ref: https://github.com/rails/rails/pull/48699 + def self.internal_methods #:nodoc: + super << :_prefixes + end + protected # Gets the actual resource stored in the instance variable @@ -110,7 +126,7 @@ def require_no_authentication end if authenticated && resource = warden.user(resource_name) - flash[:alert] = I18n.t("devise.failure.already_authenticated") + set_flash_message(:alert, 'already_authenticated', scope: 'devise.failure') redirect_to after_sign_in_path_for(resource) end end @@ -182,7 +198,7 @@ def find_message(kind, options = {}) options[:default] = Array(options[:default]).unshift(kind.to_sym) options[:resource_name] = resource_name options = devise_i18n_options(options) - I18n.t("#{options[:resource_name]}.#{kind}", options) + I18n.t("#{options[:resource_name]}.#{kind}", **options) end # Controllers inheriting DeviseController are advised to override this diff --git a/app/helpers/devise_helper.rb b/app/helpers/devise_helper.rb index f2d072615..0bfcb0630 100644 --- a/app/helpers/devise_helper.rb +++ b/app/helpers/devise_helper.rb @@ -1,25 +1,5 @@ -module DeviseHelper - # A simple way to show error messages for the current devise resource. If you need - # to customize this method, you can either overwrite it in your application helpers or - # copy the views to your application. - # - # This method is intended to stay simple and it is unlikely that we are going to change - # it to add more behavior or options. - def devise_error_messages! - return "" if resource.errors.empty? - - messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join - sentence = I18n.t("errors.messages.not_saved", - count: resource.errors.count, - resource: resource.class.model_name.human.downcase) +# frozen_string_literal: true - html = <<-HTML -
<%= f.label :email %>
+<%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
<%= f.label :password, "New password" %>
<% if @minimum_password_length %> - (<%= @minimum_password_length %> characters minimum)(<%= @minimum_password_length %> characters minimum)
<% end %> - <%= f.password_field :password, autofocus: true, autocomplete: "off" %> +<%= f.password_field :password, autofocus: true, autocomplete: "new-password" %>
<%= f.label :password_confirmation, "Confirm new password" %>
+<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
<%= f.label :email %>
+<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
<%= f.label :email %>
+<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
<%= f.label :password %> (leave blank if you don't want to change it)
+<%= f.password_field :password, autocomplete: "new-password" %>
<% if @minimum_password_length %> -<%= @minimum_password_length %> characters minimum
<% end %><%= f.label :password_confirmation %>
+<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
<%= f.label :current_password %> (we need your current password to confirm your changes)
+<%= f.password_field :current_password, autocomplete: "current-password" %>
Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>
+<%= f.label :email %>
+<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
<%= f.label :password %>
<% if @minimum_password_length %> - (<%= @minimum_password_length %> characters minimum) - <% end %>(<%= @minimum_password_length %> characters minimum)
+ <% end %> +<%= f.password_field :password, autocomplete: "new-password" %>
<%= f.label :password_confirmation %>
+<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
<%= f.label :email %>
+<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
<%= f.label :password %>
+<%= f.password_field :password, autocomplete: "current-password" %>
<%= f.check_box :remember_me %>
+<%= f.label :remember_me %>
<%= link_to "Log in", new_session_path(resource_name) %>
+<% end %> <%- if devise_mapping.registerable? && controller_name != 'registrations' %> - <%= link_to "Sign up", new_registration_path(resource_name) %><%= link_to "Sign up", new_registration_path(resource_name) %>
+<% end %> <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> - <%= link_to "Forgot your password?", new_password_path(resource_name) %><%= link_to "Forgot your password?", new_password_path(resource_name) %>
+<% end %> <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> - <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
+<% end %> <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> - <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
+<% end %> <%- if devise_mapping.omniauthable? %> <%- resource_class.omniauth_providers.each do |provider| %> - <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %>
+ <% end %> +<% end %> diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb index 16586bc7a..6b68d724c 100644 --- a/app/views/devise/unlocks/new.html.erb +++ b/app/views/devise/unlocks/new.html.erb @@ -1,11 +1,11 @@<%= f.label :email %>
+<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
<%= notice %>
<%= alert %>
+ * Not required for API-only Applications * + 4. You can copy Devise views (for customization) to your app by running: rails g devise:views + + * Not required * =============================================================================== diff --git a/lib/generators/templates/controllers/confirmations_controller.rb b/lib/generators/templates/controllers/confirmations_controller.rb index 480ee9a07..e0466111c 100644 --- a/lib/generators/templates/controllers/confirmations_controller.rb +++ b/lib/generators/templates/controllers/confirmations_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class <%= @scope_prefix %>ConfirmationsController < Devise::ConfirmationsController # GET /resource/confirmation/new # def new diff --git a/lib/generators/templates/controllers/omniauth_callbacks_controller.rb b/lib/generators/templates/controllers/omniauth_callbacks_controller.rb index cc122dc4f..29556cf6e 100644 --- a/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +++ b/lib/generators/templates/controllers/omniauth_callbacks_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class <%= @scope_prefix %>OmniauthCallbacksController < Devise::OmniauthCallbacksController # You should configure your model like this: # devise :omniauthable, omniauth_providers: [:twitter] @@ -7,7 +9,7 @@ class <%= @scope_prefix %>OmniauthCallbacksController < Devise::OmniauthCallback # end # More info at: - # https://github.com/plataformatec/devise#omniauth + # https://github.com/heartcombo/devise#omniauth # GET|POST /resource/auth/twitter # def passthru diff --git a/lib/generators/templates/controllers/passwords_controller.rb b/lib/generators/templates/controllers/passwords_controller.rb index 3409d4359..afd468cc1 100644 --- a/lib/generators/templates/controllers/passwords_controller.rb +++ b/lib/generators/templates/controllers/passwords_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class <%= @scope_prefix %>PasswordsController < Devise::PasswordsController # GET /resource/password/new # def new diff --git a/lib/generators/templates/controllers/registrations_controller.rb b/lib/generators/templates/controllers/registrations_controller.rb index 3ffd29e91..cdd91acc1 100644 --- a/lib/generators/templates/controllers/registrations_controller.rb +++ b/lib/generators/templates/controllers/registrations_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class <%= @scope_prefix %>RegistrationsController < Devise::RegistrationsController # before_action :configure_sign_up_params, only: [:create] # before_action :configure_account_update_params, only: [:update] diff --git a/lib/generators/templates/controllers/sessions_controller.rb b/lib/generators/templates/controllers/sessions_controller.rb index 69afe4b4b..f229c9b4a 100644 --- a/lib/generators/templates/controllers/sessions_controller.rb +++ b/lib/generators/templates/controllers/sessions_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class <%= @scope_prefix %>SessionsController < Devise::SessionsController # before_action :configure_sign_in_params, only: [:create] diff --git a/lib/generators/templates/controllers/unlocks_controller.rb b/lib/generators/templates/controllers/unlocks_controller.rb index 0e2cced59..0eadbbf65 100644 --- a/lib/generators/templates/controllers/unlocks_controller.rb +++ b/lib/generators/templates/controllers/unlocks_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class <%= @scope_prefix %>UnlocksController < Devise::UnlocksController # GET /resource/unlock/new # def new diff --git a/lib/generators/templates/devise.rb b/lib/generators/templates/devise.rb old mode 100755 new mode 100644 index e3d9ede77..b36f281f2 --- a/lib/generators/templates/devise.rb +++ b/lib/generators/templates/devise.rb @@ -1,3 +1,11 @@ +# frozen_string_literal: true + +# Assuming you have not yet modified this file, each configuration option below +# is set to its default value. Note that some are commented out while others +# are not: uncommented lines are intended to protect your configuration from +# breaking changes in upgrades (i.e., in the event that future versions of +# Devise change the default values for those options). +# # Use this hook to configure devise mailer, warden hooks and so forth. # Many of these configuration options can be set straight in your model. Devise.setup do |config| @@ -8,6 +16,10 @@ # by default. You can change it below and use your own secret key. # config.secret_key = '<%= SecureRandom.hex(64) %>' + # ==> Controller configuration + # Configure the parent class to the devise controllers. + # config.parent_controller = 'DeviseController' + # ==> Mailer Configuration # Configure the e-mail address which will be shown in Devise::Mailer, # note that it will be overwritten if you use your own mailer class @@ -62,7 +74,10 @@ # Tell if authentication through HTTP Auth is enabled. False by default. # It can be set to an array that will enable http authentication only for the # given strategies, for example, `config.http_authenticatable = [:database]` will - # enable it only for database authentication. The supported strategies are: + # enable it only for database authentication. + # For API-only applications to support authentication "out-of-the-box", you will likely want to + # enable this with :database unless you are using a custom strategy. + # The supported strategies are: # :database = Support basic authentication with authentication key + password # config.http_authenticatable = false @@ -97,15 +112,18 @@ # config.reload_routes = true # ==> Configuration for :database_authenticatable - # For bcrypt, this is the cost for hashing the password and defaults to 11. If + # For bcrypt, this is the cost for hashing the password and defaults to 12. If # using other algorithms, it sets how many times you want the password to be hashed. + # The number of stretches used for generating the hashed password are stored + # with the hashed password. This allows you to change the stretches without + # invalidating existing passwords. # # Limiting the stretches to just one in testing will increase the performance of # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use # a value less than 10 in other environments. Note that, for bcrypt (the default # algorithm), the cost increases exponentially with the number of stretches (e.g. # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). - config.stretches = Rails.env.test? ? 1 : 11 + config.stretches = Rails.env.test? ? 1 : 12 # Set up a pepper to generate the hashed password. # config.pepper = '<%= SecureRandom.hex(64) %>' @@ -120,8 +138,11 @@ # A period that the user is allowed to access the website even without # confirming their account. For instance, if set to 2.days, the user will be # able to access the website for two days without confirming their account, - # access will be blocked just in the third day. Default is 0.days, meaning - # the user cannot access the website without confirming their account. + # access will be blocked just in the third day. + # You can also set it to nil, which will allow the user to access the website + # without confirming their account. + # Default is 0.days, meaning the user cannot access the website without + # confirming their account. # config.allow_unconfirmed_access_for = 2.days # A period that the user is allowed to confirm their account before their @@ -136,6 +157,9 @@ # initial account confirmation) to be applied. Requires additional unconfirmed_email # db field (see migrations). Until confirmed, new email is stored in # unconfirmed_email column, and copied to email column on successful confirmation. + # Also, when used in conjunction with `send_email_changed_notification`, + # the notification is sent to the original email when the change is requested, + # not when the unconfirmed email is confirmed. config.reconfirmable = true # Defines which key will be used when confirming an account @@ -235,14 +259,14 @@ # ==> Navigation configuration # Lists the formats that should be treated as navigational. Formats like - # :html, should redirect to the sign in page when the user does not have + # :html should redirect to the sign in page when the user does not have # access, but formats like :xml or :json, should return 401. # # If you have any extra navigational formats, like :iphone or :mobile, you # should add them to the navigational formats lists. # # The "*/*" below is required to match Internet Explorer requests. - # config.navigational_formats = ['*/*', :html] + # config.navigational_formats = ['*/*', :html, :turbo_stream] # The default HTTP method used to sign out a resource. Default is :delete. config.sign_out_via = :delete @@ -256,9 +280,9 @@ # If you want to use other strategies, that are not supported by Devise, or # change the failure app, you can configure them inside the config.warden block. # - # config.warden do |manager| - # manager.intercept_401 = false - # manager.default_strategies(scope: :user).unshift :some_external_strategy + # config.warden do |warden_config| + # warden_config.intercept_401 = false + # warden_config.default_strategies(scope: :user).unshift :some_external_strategy # end # ==> Mountable engine configurations @@ -274,4 +298,19 @@ # When using OmniAuth, Devise cannot automatically set OmniAuth path, # so you need to do it manually. For the users scope, it would be: # config.omniauth_path_prefix = '/my_engine/users/auth' + + # ==> Hotwire/Turbo configuration + # When using Devise with Hotwire/Turbo, the http status for error responses + # and some redirects must match the following. The default in Devise for existing + # apps is `200 OK` and `302 Found` respectively, but new apps are generated with + # these new defaults that match Hotwire/Turbo behavior. + # Note: These might become the new default in future versions of Devise. + config.responder.error_status = <%= Rack::Utils::SYMBOL_TO_STATUS_CODE.key(422).inspect %> + config.responder.redirect_status = :see_other + + # ==> Configuration for :registerable + + # When set to false, does not sign a user in automatically after their password is + # changed. Defaults to true, so a user is signed in automatically after changing a password. + # config.sign_in_after_change_password = true end diff --git a/lib/generators/templates/simple_form_for/confirmations/new.html.erb b/lib/generators/templates/simple_form_for/confirmations/new.html.erb index 949b17277..f7b4a65c5 100644 --- a/lib/generators/templates/simple_form_for/confirmations/new.html.erb +++ b/lib/generators/templates/simple_form_for/confirmations/new.html.erb @@ -5,7 +5,11 @@ <%= f.full_error :confirmation_token %>Currently waiting confirmation for: <%= resource.unconfirmed_email %>
<% end %> - <%= f.input :password, autocomplete: "off", hint: "leave it blank if you don't want to change it", required: false %> - <%= f.input :password_confirmation, required: false %> - <%= f.input :current_password, hint: "we need your current password to confirm your changes", required: true %> + <%= f.input :password, + hint: "leave it blank if you don't want to change it", + required: false, + input_html: { autocomplete: "new-password" } %> + <%= f.input :password_confirmation, + required: false, + input_html: { autocomplete: "new-password" } %> + <%= f.input :current_password, + hint: "we need your current password to confirm your changes", + required: true, + input_html: { autocomplete: "current-password" } %>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>
+