Full Code of heartcombo/devise for AI

main 5d202775d75c cached
272 files
656.7 KB
168.8k tokens
1041 symbols
1 requests
Download .txt
Showing preview only (723K chars total). Download the full file or copy to clipboard to get everything.
Repository: heartcombo/devise
Branch: main
Commit: 5d202775d75c
Files: 272
Total size: 656.7 KB

Directory structure:
gitextract_4bqfrk55/

├── .devcontainer/
│   └── devcontainer.json
├── .github/
│   ├── code-scanning.yml
│   ├── dependabot.yml
│   └── workflows/
│       └── test.yml
├── .gitignore
├── .yardopts
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Gemfile
├── ISSUE_TEMPLATE.md
├── MIT-LICENSE
├── README.md
├── Rakefile
├── app/
│   ├── controllers/
│   │   ├── devise/
│   │   │   ├── confirmations_controller.rb
│   │   │   ├── omniauth_callbacks_controller.rb
│   │   │   ├── passwords_controller.rb
│   │   │   ├── registrations_controller.rb
│   │   │   ├── sessions_controller.rb
│   │   │   └── unlocks_controller.rb
│   │   └── devise_controller.rb
│   ├── helpers/
│   │   └── devise_helper.rb
│   ├── mailers/
│   │   └── devise/
│   │       └── mailer.rb
│   └── views/
│       └── devise/
│           ├── confirmations/
│           │   └── new.html.erb
│           ├── mailer/
│           │   ├── confirmation_instructions.html.erb
│           │   ├── email_changed.html.erb
│           │   ├── password_change.html.erb
│           │   ├── reset_password_instructions.html.erb
│           │   └── unlock_instructions.html.erb
│           ├── passwords/
│           │   ├── edit.html.erb
│           │   └── new.html.erb
│           ├── registrations/
│           │   ├── edit.html.erb
│           │   └── new.html.erb
│           ├── sessions/
│           │   └── new.html.erb
│           ├── shared/
│           │   ├── _error_messages.html.erb
│           │   └── _links.html.erb
│           └── unlocks/
│               └── new.html.erb
├── bin/
│   └── test
├── config/
│   └── locales/
│       └── en.yml
├── devise.gemspec
├── gemfiles/
│   ├── Gemfile-rails-7-0
│   ├── Gemfile-rails-7-1
│   ├── Gemfile-rails-7-2
│   ├── Gemfile-rails-8-0
│   └── Gemfile-rails-main
├── guides/
│   └── bug_report_templates/
│       └── integration_test.rb
├── lib/
│   ├── devise/
│   │   ├── controllers/
│   │   │   ├── helpers.rb
│   │   │   ├── rememberable.rb
│   │   │   ├── responder.rb
│   │   │   ├── scoped_views.rb
│   │   │   ├── sign_in_out.rb
│   │   │   ├── store_location.rb
│   │   │   └── url_helpers.rb
│   │   ├── delegator.rb
│   │   ├── encryptor.rb
│   │   ├── failure_app.rb
│   │   ├── hooks/
│   │   │   ├── activatable.rb
│   │   │   ├── csrf_cleaner.rb
│   │   │   ├── forgetable.rb
│   │   │   ├── lockable.rb
│   │   │   ├── proxy.rb
│   │   │   ├── rememberable.rb
│   │   │   ├── timeoutable.rb
│   │   │   └── trackable.rb
│   │   ├── mailers/
│   │   │   └── helpers.rb
│   │   ├── mapping.rb
│   │   ├── models/
│   │   │   ├── authenticatable.rb
│   │   │   ├── confirmable.rb
│   │   │   ├── database_authenticatable.rb
│   │   │   ├── lockable.rb
│   │   │   ├── omniauthable.rb
│   │   │   ├── recoverable.rb
│   │   │   ├── registerable.rb
│   │   │   ├── rememberable.rb
│   │   │   ├── timeoutable.rb
│   │   │   ├── trackable.rb
│   │   │   └── validatable.rb
│   │   ├── models.rb
│   │   ├── modules.rb
│   │   ├── omniauth/
│   │   │   ├── config.rb
│   │   │   └── url_helpers.rb
│   │   ├── omniauth.rb
│   │   ├── orm/
│   │   │   ├── active_record.rb
│   │   │   └── mongoid.rb
│   │   ├── orm.rb
│   │   ├── parameter_filter.rb
│   │   ├── parameter_sanitizer.rb
│   │   ├── rails/
│   │   │   ├── routes.rb
│   │   │   └── warden_compat.rb
│   │   ├── rails.rb
│   │   ├── strategies/
│   │   │   ├── authenticatable.rb
│   │   │   ├── base.rb
│   │   │   ├── database_authenticatable.rb
│   │   │   └── rememberable.rb
│   │   ├── test/
│   │   │   ├── controller_helpers.rb
│   │   │   └── integration_helpers.rb
│   │   ├── time_inflector.rb
│   │   ├── token_generator.rb
│   │   └── version.rb
│   ├── devise.rb
│   └── generators/
│       ├── active_record/
│       │   ├── devise_generator.rb
│       │   └── templates/
│       │       ├── migration.rb
│       │       └── migration_existing.rb
│       ├── devise/
│       │   ├── controllers_generator.rb
│       │   ├── devise_generator.rb
│       │   ├── install_generator.rb
│       │   ├── orm_helpers.rb
│       │   └── views_generator.rb
│       ├── mongoid/
│       │   └── devise_generator.rb
│       └── templates/
│           ├── README
│           ├── controllers/
│           │   ├── README
│           │   ├── confirmations_controller.rb
│           │   ├── omniauth_callbacks_controller.rb
│           │   ├── passwords_controller.rb
│           │   ├── registrations_controller.rb
│           │   ├── sessions_controller.rb
│           │   └── unlocks_controller.rb
│           ├── devise.rb
│           ├── markerb/
│           │   ├── confirmation_instructions.markerb
│           │   ├── email_changed.markerb
│           │   ├── password_change.markerb
│           │   ├── reset_password_instructions.markerb
│           │   └── unlock_instructions.markerb
│           └── simple_form_for/
│               ├── confirmations/
│               │   └── new.html.erb
│               ├── passwords/
│               │   ├── edit.html.erb
│               │   └── new.html.erb
│               ├── registrations/
│               │   ├── edit.html.erb
│               │   └── new.html.erb
│               ├── sessions/
│               │   └── new.html.erb
│               └── unlocks/
│                   └── new.html.erb
└── test/
    ├── controllers/
    │   ├── custom_registrations_controller_test.rb
    │   ├── custom_strategy_test.rb
    │   ├── helper_methods_test.rb
    │   ├── helpers_test.rb
    │   ├── inherited_controller_i18n_messages_test.rb
    │   ├── internal_helpers_test.rb
    │   ├── load_hooks_controller_test.rb
    │   ├── passwords_controller_test.rb
    │   ├── sessions_controller_test.rb
    │   └── url_helpers_test.rb
    ├── delegator_test.rb
    ├── devise_test.rb
    ├── failure_app_test.rb
    ├── generators/
    │   ├── active_record_generator_test.rb
    │   ├── controllers_generator_test.rb
    │   ├── devise_generator_test.rb
    │   ├── install_generator_test.rb
    │   ├── mongoid_generator_test.rb
    │   └── views_generator_test.rb
    ├── helpers/
    │   └── devise_helper_test.rb
    ├── integration/
    │   ├── authenticatable_test.rb
    │   ├── confirmable_test.rb
    │   ├── database_authenticatable_test.rb
    │   ├── http_authenticatable_test.rb
    │   ├── lockable_test.rb
    │   ├── mounted_engine_test.rb
    │   ├── omniauthable_test.rb
    │   ├── recoverable_test.rb
    │   ├── registerable_test.rb
    │   ├── rememberable_test.rb
    │   ├── timeoutable_test.rb
    │   └── trackable_test.rb
    ├── mailers/
    │   ├── confirmation_instructions_test.rb
    │   ├── email_changed_test.rb
    │   ├── mailer_test.rb
    │   ├── reset_password_instructions_test.rb
    │   └── unlock_instructions_test.rb
    ├── mapping_test.rb
    ├── models/
    │   ├── authenticatable_test.rb
    │   ├── confirmable_test.rb
    │   ├── database_authenticatable_test.rb
    │   ├── lockable_test.rb
    │   ├── omniauthable_test.rb
    │   ├── recoverable_test.rb
    │   ├── registerable_test.rb
    │   ├── rememberable_test.rb
    │   ├── serializable_test.rb
    │   ├── timeoutable_test.rb
    │   ├── trackable_test.rb
    │   └── validatable_test.rb
    ├── models_test.rb
    ├── omniauth/
    │   ├── config_test.rb
    │   └── url_helpers_test.rb
    ├── orm/
    │   ├── active_record.rb
    │   └── mongoid.rb
    ├── parameter_sanitizer_test.rb
    ├── rails_app/
    │   ├── Rakefile
    │   ├── app/
    │   │   ├── active_record/
    │   │   │   ├── admin.rb
    │   │   │   ├── shim.rb
    │   │   │   ├── user.rb
    │   │   │   ├── user_on_engine.rb
    │   │   │   ├── user_on_main_app.rb
    │   │   │   ├── user_with_validations.rb
    │   │   │   └── user_without_email.rb
    │   │   ├── controllers/
    │   │   │   ├── admins/
    │   │   │   │   └── sessions_controller.rb
    │   │   │   ├── admins_controller.rb
    │   │   │   ├── application_controller.rb
    │   │   │   ├── application_with_fake_engine.rb
    │   │   │   ├── custom/
    │   │   │   │   └── registrations_controller.rb
    │   │   │   ├── home_controller.rb
    │   │   │   ├── publisher/
    │   │   │   │   ├── registrations_controller.rb
    │   │   │   │   └── sessions_controller.rb
    │   │   │   ├── streaming_controller.rb
    │   │   │   ├── users/
    │   │   │   │   └── omniauth_callbacks_controller.rb
    │   │   │   └── users_controller.rb
    │   │   ├── helpers/
    │   │   │   └── application_helper.rb
    │   │   ├── mailers/
    │   │   │   └── users/
    │   │   │       ├── from_proc_mailer.rb
    │   │   │       ├── mailer.rb
    │   │   │       └── reply_to_mailer.rb
    │   │   ├── mongoid/
    │   │   │   ├── admin.rb
    │   │   │   ├── shim.rb
    │   │   │   ├── user.rb
    │   │   │   ├── user_on_engine.rb
    │   │   │   ├── user_on_main_app.rb
    │   │   │   ├── user_with_validations.rb
    │   │   │   └── user_without_email.rb
    │   │   └── views/
    │   │       ├── admins/
    │   │       │   ├── index.html.erb
    │   │       │   └── sessions/
    │   │       │       └── new.html.erb
    │   │       ├── home/
    │   │       │   ├── admin_dashboard.html.erb
    │   │       │   ├── index.html.erb
    │   │       │   ├── join.html.erb
    │   │       │   ├── private.html.erb
    │   │       │   └── user_dashboard.html.erb
    │   │       ├── layouts/
    │   │       │   └── application.html.erb
    │   │       └── users/
    │   │           ├── edit_form.html.erb
    │   │           ├── index.html.erb
    │   │           ├── mailer/
    │   │           │   └── confirmation_instructions.erb
    │   │           └── sessions/
    │   │               └── new.html.erb
    │   ├── bin/
    │   │   ├── bundle
    │   │   ├── rails
    │   │   └── rake
    │   ├── config/
    │   │   ├── application.rb
    │   │   ├── boot.rb
    │   │   ├── database.yml
    │   │   ├── environment.rb
    │   │   ├── environments/
    │   │   │   ├── development.rb
    │   │   │   ├── production.rb
    │   │   │   └── test.rb
    │   │   ├── initializers/
    │   │   │   ├── backtrace_silencers.rb
    │   │   │   ├── devise.rb
    │   │   │   ├── inflections.rb
    │   │   │   ├── secret_token.rb
    │   │   │   └── session_store.rb
    │   │   └── routes.rb
    │   ├── config.ru
    │   ├── db/
    │   │   ├── migrate/
    │   │   │   └── 20100401102949_create_tables.rb
    │   │   └── schema.rb
    │   ├── lib/
    │   │   ├── lazy_load_test_module.rb
    │   │   ├── shared_admin.rb
    │   │   ├── shared_user.rb
    │   │   ├── shared_user_without_email.rb
    │   │   └── shared_user_without_omniauth.rb
    │   └── public/
    │       ├── 404.html
    │       ├── 422.html
    │       └── 500.html
    ├── rails_test.rb
    ├── routes_test.rb
    ├── support/
    │   ├── action_controller/
    │   │   └── record_identifier.rb
    │   ├── assertions.rb
    │   ├── helpers.rb
    │   ├── http_method_compatibility.rb
    │   ├── integration.rb
    │   ├── locale/
    │   │   ├── de.yml
    │   │   ├── en.yml
    │   │   └── pt-BR.yml
    │   ├── mongoid.yml
    │   └── webrat/
    │       ├── integrations/
    │       │   └── rails.rb
    │       └── matchers.rb
    ├── test/
    │   ├── controller_helpers_test.rb
    │   └── integration_helpers_test.rb
    ├── test_helper.rb
    └── test_models.rb

================================================
FILE CONTENTS
================================================

================================================
FILE: .devcontainer/devcontainer.json
================================================
// 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"
}


================================================
FILE: .github/code-scanning.yml
================================================
paths-ignore:
  - test/**


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"


================================================
FILE: .github/workflows/test.yml
================================================
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


================================================
FILE: .gitignore
================================================
test/rails_app/log/*
test/rails_app/tmp/*
*~
coverage/*
*.sqlite3
.bundle
rdoc/*
pkg
log
test/tmp/*
gemfiles/*.lock


================================================
FILE: .yardopts
================================================
--protected
--no-private
--embed-mixin ClassMethods
-
README.md
CHANGELOG.rdoc
CONTRIBUTING.md
MIT-LICENSE



================================================
FILE: CHANGELOG.md
================================================
### 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 [#5783](https://github.com/heartcombo/devise/pull/5783) [#5784](https://github.com/heartcombo/devise/pull/5784)

### 5.0.2 - 2026-02-18

* enhancements
  * 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 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)

### 5.0.0 - 2026-01-23

no changes

### 5.0.0.rc - 2025-12-31

* 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.

    This is potentially a breaking change because Devise previously used the following order to find a secret key:

    ```
    app.credentials.secret_key_base > app.secrets.secret_key_base > application.config.secret_key_base > application.secret_key_base
    ```

    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 `<br>` tags separating form elements to wrapping them in `<p>` 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).

    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
  * 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).

    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

    ```
    validates_length_of :password, within: password_length, allow_blank: true`
    ```

    to

    ```
    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)


Please check [4-stable](https://github.com/heartcombo/devise/blob/4-stable/CHANGELOG.md)
for previous changes.


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Code of Conduct

As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.

We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
* Other unethical or unprofessional conduct.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.

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 [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/)


================================================
FILE: CONTRIBUTING.md
================================================
# How to contribute to Devise

Thanks for your interest on contributing to Devise! Here are a few general
guidelines on contributing and reporting bugs to Devise that we ask you to
take a look first. Notice that all of your interactions in the project are
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/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
even better a **sample Rails app that replicates the issue** - Devise has a lot
of moving parts and it's functionality can be affected by third party gems, so
we need as much context and details as possible to identify what might be broken
for you. We have a [test case template](guides/bug_report_templates/integration_test.rb)
that can be used to replicate issues with minimal setup.

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/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).

**If you find a security bug, do not report it through GitHub. Please send an
e-mail to [heartcombo.oss@gmail.com](mailto:heartcombo.oss@gmail.com)
instead.**

## Sending Pull Requests

Before sending a new Pull Request, take a look on existing Pull Requests and Issues
to see if the proposed change or fix has been discussed in the past, or if the
change was already implemented but not yet released.

We expect new Pull Requests to include enough tests for new or changed behavior,
and we aim to maintain everything as most backwards compatible as possible,
reserving breaking changes to be ship in major releases when necessary - you
can wrap the new code path with a setting toggle from the `Devise` module defined
as `false` by default to require developers to opt-in for the new behavior.

If your Pull Request includes new or changed behavior, be sure that the changes
are beneficial to a wide range of use cases or it's an application specific change
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/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
`README.md` and the RDoc sections in the source code) or improve existing rough
edges in our API that might be blocking existing integrations or 3rd party gems.

## Other ways to contribute

We welcome anyone that wants to contribute to Devise to triage and reply to
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 feedback to the issue's
author on what might be missing.
* 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
familiar with feel free to update it as necessary.
* Review existing Pull Requests, and testing patches against real existing
applications that use Devise.

Thanks again for your interest on contributing to the project!

:heart:


================================================
FILE: Gemfile
================================================
# frozen_string_literal: true

source "https://rubygems.org"

gemspec

gem "omniauth"
gem "omniauth-oauth2"
gem "rails", "~> 8.1.0"
gem "rdoc"

gem "rails-controller-testing"

gem "responders", "~> 3.1"

group :test do
  gem "minitest", "< 6"
  gem "mocha", "~> 2.1", require: false
  gem "omniauth-facebook"
  gem "omniauth-openid"
  gem "rexml"
  gem "timecop"
  gem "webrat"
  gem "ostruct"
end

platforms :ruby do
  gem "sqlite3"
end

group :mongoid do
  gem "mongoid", "~> 9.0", github: "mongodb/mongoid", branch: "9.0-stable"
end


================================================
FILE: ISSUE_TEMPLATE.md
================================================
## 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


================================================
FILE: MIT-LICENSE
================================================
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
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
![Devise Logo](https://raw.github.com/heartcombo/devise/main/devise.png)

Devise is a flexible authentication solution for Rails based on Warden. It:

* Is Rack based;
* Is a complete MVC solution based on Rails engines;
* Allows you to have multiple models signed in at the same time;
* Is based on a modularity concept: use only what you really need.

It's composed of 10 modules:

* [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

<!-- TOC depthFrom:1 depthTo:6 withLinks:1 orderedList:0 -->

- [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)

<!-- /TOC -->



## Information

### The Devise wiki

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

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/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.

### Example applications

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/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/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/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
```

### 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. 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' 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 5 works with Rails 7 onwards. Run:

```sh
bundle add devise
```

Next, you need to run the generator:

```console
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`:

```ruby
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
```

The generator will install an initializer which describes ALL of Devise's configuration options. It is *imperative* that you take a look at it. When you are done, you are ready to add Devise to any of your models using the generator.


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

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

Devise will create some helpers to use inside your controllers and views. To set up a controller with user authentication, just add this before_action (assuming your devise model is 'User'):

```ruby
before_action :authenticate_user!
```

For Rails 5, note that `protect_from_forgery` is no longer prepended to the `before_action` chain, so if you have set `authenticate_user` before `protect_from_forgery`, your request will result in "Can't verify CSRF token authenticity." To resolve this, either change the order in which you call them, or use `protect_from_forgery prepend: true`.

If your devise model is something other than User, replace "_user" with "_yourmodel". The same logic applies to the instructions below.

To verify if a user is signed in, use the following helper:

```ruby
user_signed_in?
```

For the current signed-in user, this helper is available:

```ruby
current_user
```

You can access the session for this scope:

```ruby
user_session
```

After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect to. For instance, when using a `:user` resource, the `user_root_path` will be used if it exists; otherwise, the default `root_path` will be used. This means that you need to set the root inside your routes:

```ruby
root to: 'home#index'
```

You can also override `after_sign_in_path_for` and `after_sign_out_path_for` to customize your redirect hooks.

Notice that if your Devise model is called `Member` instead of `User`, for example, then the helpers available are:

```ruby
before_action :authenticate_member!

member_signed_in?

current_member

member_session
```

### Configuring Models

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: 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/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.

There are just three actions in Devise that allow any set of parameters to be passed down to the model, therefore requiring sanitization. Their names and default permitted parameters are:

* `sign_in` (`Devise::SessionsController#create`) - Permits only the authentication keys (like `email`)
* `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 action in your `ApplicationController`:

```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: [:username])
  end
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:

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

```ruby
def configure_permitted_parameters
  devise_parameter_sanitizer.permit(:sign_in) do |user_params|
    user_params.permit(:username, :email)
  end
end
```

If you have some checkboxes that express the roles a user may take on registration, the browser will send those selected checkboxes as an array. An array is not one of Strong Parameters' permitted scalars, so we need to configure Devise in the following way:

```ruby
def configure_permitted_parameters
  devise_parameter_sanitizer.permit(:sign_up) do |user_params|
    user_params.permit({ roles: [] }, :email, :password, :password_confirmation)
  end
end
```
For the list of permitted scalars, and how to declare permitted keys in nested hashes and arrays, see

https://github.com/rails/strong_parameters#nested-parameters

If you have multiple Devise models, you may want to set up a different parameter sanitizer per model. In this case, we recommend inheriting from `Devise::ParameterSanitizer` and adding your own logic:

```ruby
class User::ParameterSanitizer < Devise::ParameterSanitizer
  def initialize(*)
    super
    permit(:sign_up, keys: [:username, :email])
  end
end
```

And then configure your controllers to use it:

```ruby
class ApplicationController < ActionController::Base
  protected

  def devise_parameter_sanitizer
    if resource_class == User
      User::ParameterSanitizer.new(User, :user, params)
    else
      super # Use the default one
    end
  end
end
```

The example above overrides the permitted parameters for the user to be both `:username` and `:email`. The non-lazy way to configure parameters would be by defining the before filter above in a custom controller. We detail how to configure and customize controllers in some sections below.

### Configuring views

We built Devise to help you quickly develop an application that uses authentication. However, we don't want to be in your way when you need to customize it.

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

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.

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

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 views to the generator with the `-v` flag.

```console
rails generate devise:views -v registrations confirmations
```

### Configuring controllers

If the customization at the views level is not enough, you can customize each controller by following these steps:

1. Create your custom controllers using the generator which requires a scope:

    ```console
    rails generate devise:controllers [scope]
    ```

    If you specify `users` as the scope, controllers will be created in `app/controllers/users/`.
    And the sessions controller will look like this:

    ```ruby
    class Users::SessionsController < Devise::SessionsController
      # GET /resource/sign_in
      # def new
      #   super
      # end
      ...
    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:

    ```ruby
    devise_for :users, controllers: { sessions: 'users/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.

    You can completely override a controller action:

    ```ruby
    class Users::SessionsController < Devise::SessionsController
      def create
        # custom sign-in code
      end
    end
    ```

    Or you can simply add new behavior to it:

    ```ruby
    class Users::SessionsController < Devise::SessionsController
      def create
        super do |resource|
          BackgroundWorker.trigger(resource)
        end
      end
    end
    ```

    This is useful for triggering background jobs or logging events during certain actions.

Remember that Devise uses flash messages to let users know if sign in was successful or unsuccessful. Devise expects your application to call `flash[:notice]` and `flash[:alert]` as appropriate. Do not print the entire flash hash, print only specific keys. In some circumstances, Devise adds a `:timedout` key to the flash hash, which is not meant for display. Remove this key from the hash if you intend to print the entire hash.

### Configuring routes

Devise also ships with default routes. If you need to customize them, you should probably be able to do it through the devise_for method. It accepts several options like :class_name, :path_prefix and so on, including the possibility to change path names for I18n:

```ruby
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](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:

```ruby
devise_scope :user do
  get 'sign_in', to: 'devise/sessions#new'
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:

```yaml
en:
  devise:
    sessions:
      signed_in: 'Signed in successfully.'
```

You can also create distinct messages based on the resource you've configured using the singular name given in routes:

```yaml
en:
  devise:
    sessions:
      user:
        signed_in: 'Welcome user, you are signed in.'
      admin:
        signed_in: 'Hello admin!'
```

The Devise mailer uses a similar pattern to create subject messages:

```yaml
en:
  devise:
    mailer:
      confirmation_instructions:
        subject: 'Hello everybody!'
        user_subject: 'Hello User! Please confirm your email'
      reset_password_instructions:
        subject: 'Reset instructions'
```

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/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.

### Test helpers

Devise includes some test helpers for controller and integration tests.
In order to use them, you need to include the respective module in your test
cases/specs.

### Controller tests

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::IntegrationHelpers # Rails >= 5
end
```

```ruby
class PostsControllerTest < ActionController::TestCase
  include Devise::Test::ControllerHelpers # Rails < 5
end
```

If you're using RSpec, you can put the following inside a file named
`spec/support/devise.rb` or in your `spec/spec_helper.rb` (or
`spec/rails_helper.rb` if you are using `rspec-rails`):

```ruby
RSpec.configure do |config|
  config.include Devise::Test::ControllerHelpers, type: :controller
  config.include Devise::Test::ControllerHelpers, type: :view
end
```

Just be sure that this inclusion is made *after* the `require 'rspec/rails'` directive.

Now you are ready to use the `sign_in` and `sign_out` methods on your controller
tests:

```ruby
sign_in @user
sign_in @user, scope: :admin
```

If you are testing Devise internal controllers or a controller that inherits
from Devise's, you need to tell Devise which mapping should be used before a
request. This is necessary because Devise gets this information from the router,
but since controller tests do not pass through the router, it needs to be stated
explicitly. For example, if you are testing the user scope, simply use:

```ruby
test 'GET new' do
  # Mimic the router behavior of setting the Devise scope through the env.
  @request.env['devise.mapping'] = Devise.mappings[:user]

  # Use the sign_in helper to sign in a fixture `User` record.
  sign_in users(:alice)

  get :new

  # assert something
end
```

### Integration tests

Integration test helpers are available by including the
`Devise::Test::IntegrationHelpers` module.

```ruby
class PostsTests < ActionDispatch::IntegrationTest
  include Devise::Test::IntegrationHelpers
end
```

Now you can use the following `sign_in` and `sign_out` methods in your integration
tests:

```ruby
sign_in users(:bob)
sign_in users(:bob), scope: :admin

sign_out :user
```

RSpec users can include the `IntegrationHelpers` module on their `:feature` specs.

```ruby
RSpec.configure do |config|
  config.include Devise::Test::IntegrationHelpers, type: :feature
end
```

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 controllers with RSpec in the wiki:

* https://github.com/heartcombo/devise/wiki/How-To:-Test-controllers-with-Rails-(and-RSpec)

### OmniAuth

Devise comes with OmniAuth support out of the box to authenticate with other providers. To use it, simply specify your OmniAuth configuration in `config/initializers/devise.rb`:

```ruby
config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
```

You can read more about OmniAuth support in the wiki:

* https://github.com/heartcombo/devise/wiki/OmniAuth:-Overview

### Configuring multiple models

Devise allows you to set up as many Devise models as you want. If you want to have an Admin model with just authentication and timeout features, in addition to the User model above, just run:

```ruby
# Create a migration with the required fields
create_table :admins do |t|
  t.string :email
  t.string :encrypted_password
  t.timestamps null: false
end

# Inside your Admin model
devise :database_authenticatable, :timeoutable

# Inside your routes
devise_for :admins

# Inside your protected controller
before_action :authenticate_admin!

# Inside your controllers and views
admin_signed_in?
current_admin
admin_session
```

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.

### Active Job Integration

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.

```ruby
def send_devise_notification(notification, *args)
  devise_mailer.send(notification, self, *args).deliver_later
end
```

### Password reset tokens and Rails logs

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


### Other ORMs

Devise supports ActiveRecord (default) and Mongoid. To select another ORM, simply require it in the initializer file.

### Rails API Mode

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/))

#### 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.http_authenticatable = [:database]
```

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](http://blog.plataformatec.com.br/2019/01/custom-authentication-methods-with-devise/).

#### 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:

```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).

Additionally be mindful that without views supported, some email-based flows from Confirmable, Recoverable and Lockable are not supported directly at this time.

## Additional information

### Warden

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/wardencommunity/warden

## License

MIT License.
Copyright 2020-CURRENT Rafael França, Carlos Antonio da Silva.
Copyright 2009-2019 Plataformatec.

The Devise logo is licensed under [Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License](https://creativecommons.org/licenses/by-nc-nd/4.0/).


================================================
FILE: Rakefile
================================================
# encoding: UTF-8
# frozen_string_literal: true

require 'bundler/gem_tasks'
require 'rake/testtask'
require 'rdoc/task'

desc 'Default: run tests for all ORMs.'
task default: :test

desc 'Run Devise tests for all ORMs.'
task :pre_commit do
  Dir[File.join(File.dirname(__FILE__), 'test', 'orm', '*.rb')].each do |file|
    orm = File.basename(file).split(".").first
    # "Some day, my son, rake's inner wisdom will reveal itself.  Until then,
    # take this `system` -- may its brute force protect you well."
    exit 1 unless system "rake test DEVISE_ORM=#{orm}"
  end
end

desc 'Run Devise unit tests.'
Rake::TestTask.new(:test) do |t|
  t.libs << 'lib'
  t.libs << 'test'
  t.pattern = 'test/**/*_test.rb'
  t.verbose = true
  t.warning = false
end

desc 'Generate documentation for Devise.'
Rake::RDocTask.new(:rdoc) do |rdoc|
  rdoc.rdoc_dir = 'rdoc'
  rdoc.title    = 'Devise'
  rdoc.options << '--line-numbers' << '--inline-source'
  rdoc.rdoc_files.include('README.md')
  rdoc.rdoc_files.include('lib/**/*.rb')
end


================================================
FILE: app/controllers/devise/confirmations_controller.rb
================================================
# frozen_string_literal: true

class Devise::ConfirmationsController < DeviseController
  # GET /resource/confirmation/new
  def new
    self.resource = resource_class.new
  end

  # POST /resource/confirmation
  def create
    self.resource = resource_class.send_confirmation_instructions(resource_params)
    yield resource if block_given?

    if successfully_sent?(resource)
      respond_with({}, location: after_resending_confirmation_instructions_path_for(resource_name))
    else
      respond_with(resource)
    end
  end

  # GET /resource/confirmation?confirmation_token=abcdef
  def show
    self.resource = resource_class.confirm_by_token(params[:confirmation_token])
    yield resource if block_given?

    if resource.errors.empty?
      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

  protected

    # The path used after resending confirmation instructions.
    def after_resending_confirmation_instructions_path_for(resource_name)
      is_navigational_format? ? new_session_path(resource_name) : '/'
    end

    # The path used after confirmation.
    def after_confirmation_path_for(resource_name, resource)
      if signed_in?(resource_name)
        signed_in_root_path(resource)
      else
        new_session_path(resource_name)
      end
    end

    def translation_scope
      'devise.confirmations'
    end
end


================================================
FILE: app/controllers/devise/omniauth_callbacks_controller.rb
================================================
# frozen_string_literal: true

class Devise::OmniauthCallbacksController < DeviseController
  prepend_before_action { request.env["devise.skip_timeout"] = true }

  def passthru
    render status: 404, plain: "Not found. Authentication passthru."
  end

  def failure
    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

  protected

  def failed_strategy
    request.respond_to?(:get_header) ? request.get_header("omniauth.error.strategy") : request.env["omniauth.error.strategy"]
  end

  def failure_message
    exception = request.respond_to?(:get_header) ? request.get_header("omniauth.error") : request.env["omniauth.error"]
    error   = exception.error_reason if exception.respond_to?(:error_reason)
    error ||= exception.error        if exception.respond_to?(:error)
    error ||= (request.respond_to?(:get_header) ? request.get_header("omniauth.error.type") : request.env["omniauth.error.type"]).to_s
    error.to_s.humanize if error
  end

  def after_omniauth_failure_path_for(scope)
    new_session_path(scope)
  end

  def translation_scope
    'devise.omniauth_callbacks'
  end
end


================================================
FILE: app/controllers/devise/passwords_controller.rb
================================================
# 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
  append_before_action :assert_reset_token_passed, only: :edit

  # GET /resource/password/new
  def new
    self.resource = resource_class.new
  end

  # POST /resource/password
  def create
    self.resource = resource_class.send_reset_password_instructions(resource_params)
    yield resource if block_given?

    if successfully_sent?(resource)
      respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name))
    else
      respond_with(resource)
    end
  end

  # GET /resource/password/edit?reset_password_token=abcdef
  def edit
    self.resource = resource_class.new
    set_minimum_password_length
    resource.reset_password_token = params[:reset_password_token]
  end

  # PUT /resource/password
  def update
    self.resource = resource_class.reset_password_by_token(resource_params)
    yield resource if block_given?

    if resource.errors.empty?
      resource.unlock_access! if unlockable?(resource)
      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)
      end
      respond_with resource, location: after_resetting_password_path_for(resource)
    else
      set_minimum_password_length
      respond_with resource
    end
  end

  protected
    def after_resetting_password_path_for(resource)
      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
    def after_sending_reset_password_instructions_path_for(resource_name)
      new_session_path(resource_name) if is_navigational_format?
    end

    # Check if a reset_password_token is provided in the request
    def assert_reset_token_passed
      if params[:reset_password_token].blank?
        set_flash_message(:alert, :no_token)
        redirect_to new_session_path(resource_name)
      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)
      resource.respond_to?(:unlock_access!) &&
        resource.respond_to?(:unlock_strategy_enabled?) &&
        resource.unlock_strategy_enabled?(:email)
    end

    def translation_scope
      'devise.passwords'
    end
end


================================================
FILE: app/controllers/devise/registrations_controller.rb
================================================
# 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]
  prepend_before_action :set_minimum_password_length, only: [:new, :edit]

  # GET /resource/sign_up
  def new
    build_resource
    yield resource if block_given?
    respond_with resource
  end

  # POST /resource
  def create
    build_resource(sign_up_params)

    resource.save
    yield resource if block_given?
    if resource.persisted?
      if resource.active_for_authentication?
        set_flash_message! :notice, :signed_up
        sign_up(resource_name, resource)
        respond_with resource, location: after_sign_up_path_for(resource)
      else
        set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
        expire_data_after_sign_in!
        respond_with resource, location: after_inactive_sign_up_path_for(resource)
      end
    else
      clean_up_passwords resource
      set_minimum_password_length
      respond_with resource
    end
  end

  # GET /resource/edit
  def edit
    render :edit
  end

  # PUT /resource
  # We need to use a copy of the resource because we don't want to change
  # the current user in place.
  def update
    self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
    prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)

    resource_updated = update_resource(resource, account_update_params)
    yield resource if block_given?
    if resource_updated
      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
      set_minimum_password_length
      respond_with resource
    end
  end

  # DELETE /resource
  def destroy
    resource.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), status: Devise.responder.redirect_status }
  end

  # GET /resource/cancel
  # Forces the session data which is usually expired after sign
  # in to be expired now. This is useful if the user wants to
  # cancel oauth signing in/up in the middle of the process,
  # removing all OAuth session data.
  def cancel
    expire_data_after_sign_in!
    redirect_to new_registration_path(resource_name)
  end

  protected

  # 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)
    resource.update_with_password(params)
  end

  # Build a devise resource passing in the session. Useful to move
  # temporary session data to the newly created user.
  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
  # RegistrationsController.
  def sign_up(resource_name, resource)
    sign_in(resource_name, resource)
  end

  # 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) if is_navigational_format?
  end

  # The path used after sign up for inactive accounts. You need to overwrite
  # this method in your own RegistrationsController.
  def after_inactive_sign_up_path_for(resource)
    scope = Devise::Mapping.find_scope!(resource)
    router_name = Devise.mappings[scope].router_name
    context = router_name ? send(router_name) : self
    context.respond_to?(:root_path) ? context.root_path : "/"
  end

  # 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)
    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.
  def authenticate_scope!
    send(:"authenticate_#{resource_name}!", force: true)
    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

  def account_update_params
    devise_parameter_sanitizer.sanitize(:account_update)
  end

  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


================================================
FILE: app/controllers/devise/sessions_controller.rb
================================================
# 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 }

  # GET /resource/sign_in
  def new
    self.resource = resource_class.new(sign_in_params)
    clean_up_passwords(resource)
    yield resource if block_given?
    respond_with(resource, serialize_options(resource))
  end

  # POST /resource/sign_in
  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message!(:notice, :signed_in)
    sign_in(resource_name, resource)
    yield resource if block_given?
    respond_with resource, location: after_sign_in_path_for(resource)
  end

  # DELETE /resource/sign_out
  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(non_navigational_status: :no_content)
  end

  protected

  def sign_in_params
    devise_parameter_sanitizer.sanitize(:sign_in)
  end

  def serialize_options(resource)
    methods = resource_class.authentication_keys.dup
    methods = methods.keys if methods.is_a?(Hash)
    methods << :password if resource.respond_to?(:password)
    { methods: methods, only: [:password] }
  end

  def auth_options
    { scope: resource_name, recall: "#{controller_path}#new", locale: I18n.locale }
  end

  def translation_scope
    'devise.sessions'
  end

  private

  # Check if there is no signed in user before doing the sign out.
  #
  # If there is no signed in user, it will set the flash message and redirect
  # to the after_sign_out path.
  def verify_signed_out_user
    if all_signed_out?
      set_flash_message! :notice, :already_signed_out

      respond_to_on_destroy(non_navigational_status: :unauthorized)
    end
  end

  def all_signed_out?
    users = Devise.mappings.keys.map { |s| warden.user(scope: s, run_callbacks: false) }

    users.all?(&:blank?)
  end

  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 non_navigational_status }
      format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name), status: Devise.responder.redirect_status }
    end
  end
end


================================================
FILE: app/controllers/devise/unlocks_controller.rb
================================================
# frozen_string_literal: true

class Devise::UnlocksController < DeviseController
  prepend_before_action :require_no_authentication

  # GET /resource/unlock/new
  def new
    self.resource = resource_class.new
  end

  # POST /resource/unlock
  def create
    self.resource = resource_class.send_unlock_instructions(resource_params)
    yield resource if block_given?

    if successfully_sent?(resource)
      respond_with({}, location: after_sending_unlock_instructions_path_for(resource))
    else
      respond_with(resource)
    end
  end

  # GET /resource/unlock?unlock_token=abcdef
  def show
    self.resource = resource_class.unlock_access_by_token(params[:unlock_token])
    yield resource if block_given?

    if resource.errors.empty?
      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

  protected

    # The path used after sending unlock password instructions
    def after_sending_unlock_instructions_path_for(resource)
      new_session_path(resource) if is_navigational_format?
    end

    # The path used after unlocking the resource
    def after_unlock_path_for(resource)
      new_session_path(resource)  if is_navigational_format?
    end

    def translation_scope
      'devise.unlocks'
    end
end


================================================
FILE: app/controllers/devise_controller.rb
================================================
# frozen_string_literal: true

# All Devise controllers are inherited from here.
class DeviseController < Devise.parent_controller.constantize
  include Devise::Controllers::ScopedViews

  if respond_to?(:helper)
    helper DeviseHelper
  end

  if respond_to?(:helper_method)
    helpers = %w(resource scope_name resource_name signed_in_resource
                 resource_class resource_params devise_mapping)
    helper_method(*helpers)
  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.
  # Notice we need to check for the request due to a bug in
  # Action Controller tests that forces _prefixes to be
  # loaded before even having a request object.
  #
  # 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
      ["#{devise_mapping.scoped_path}/#{controller_name}"] + super
    else
      super
    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
  def resource
    instance_variable_get(:"@#{resource_name}")
  end

  # Proxy to devise map name
  def resource_name
    devise_mapping.name
  end
  alias :scope_name :resource_name

  # Proxy to devise map class
  def resource_class
    devise_mapping.to
  end

  # Returns a signed in resource from session (if one exists)
  def signed_in_resource
    warden.authenticate(scope: resource_name)
  end

  # Attempt to find the mapped route for devise based on request path
  def devise_mapping
    @devise_mapping ||= request.env["devise.mapping"]
  end

  # Checks whether it's a devise mapped resource or not.
  def assert_is_devise_resource! #:nodoc:
    unknown_action! <<-MESSAGE unless devise_mapping
Could not find devise mapping for path #{request.fullpath.inspect}.
This may happen for two reasons:

1) You forgot to wrap your route inside the scope block. For example:

  devise_scope :user do
    get "/some/route" => "some_devise_controller"
  end

2) You are testing a Devise controller bypassing the router.
   If so, you can explicitly tell Devise which mapping to use:

   @request.env["devise.mapping"] = Devise.mappings[:user]

MESSAGE
  end

  # Returns real navigational formats which are supported by Rails
  def navigational_formats
    @navigational_formats ||= Devise.navigational_formats.select { |format| Mime::EXTENSION_LOOKUP[format.to_s] }
  end

  def unknown_action!(msg)
    logger.debug "[Devise] #{msg}" if logger
    raise AbstractController::ActionNotFound, msg
  end

  # Sets the resource creating an instance variable
  def resource=(new_resource)
    instance_variable_set(:"@#{resource_name}", new_resource)
  end

  # Helper for use in before_actions where no authentication is required.
  #
  # Example:
  #   before_action :require_no_authentication, only: :new
  def require_no_authentication
    assert_is_devise_resource!
    return unless is_navigational_format?
    no_input = devise_mapping.no_input_strategies

    authenticated = if no_input.present?
      args = no_input.dup.push scope: resource_name
      warden.authenticate?(*args)
    else
      warden.authenticated?(resource_name)
    end

    if authenticated && resource = warden.user(resource_name)
      set_flash_message(:alert, 'already_authenticated', scope: 'devise.failure')
      redirect_to after_sign_in_path_for(resource)
    end
  end

  # Helper for use after calling send_*_instructions methods on a resource.
  # If we are in paranoid mode, we always act as if the resource was valid
  # and instructions were sent.
  def successfully_sent?(resource)
    notice = if Devise.paranoid
      resource.errors.clear
      :send_paranoid_instructions
    elsif resource.errors.empty?
      :send_instructions
    end

    if notice
      set_flash_message! :notice, notice
      true
    end
  end

  # Sets the flash message with :key, using I18n. By default you are able
  # to set up your messages using specific resource scope, and if no message is
  # found we look to the default scope. Set the "now" options key to a true
  # value to populate the flash.now hash in lieu of the default flash hash (so
  # the flash message will be available to the current action instead of the
  # next action).
  # Example (i18n locale file):
  #
  #   en:
  #     devise:
  #       passwords:
  #         #default_scope_messages - only if resource_scope is not found
  #         user:
  #           #resource_scope_messages
  #
  # Please refer to README or en.yml locale file to check what messages are
  # available.
  def set_flash_message(key, kind, options = {})
    message = find_message(kind, options)
    if options[:now]
      flash.now[key] = message if message.present?
    else
      flash[key] = message if message.present?
    end
  end

  # Sets flash message if is_flashing_format? equals true
  def set_flash_message!(key, kind, options = {})
    if is_flashing_format?
      set_flash_message(key, kind, options)
    end
  end

  # Sets minimum password length to show to user
  def set_minimum_password_length
    if devise_mapping.validatable?
      @minimum_password_length = resource_class.password_length.min
    end
  end

  def devise_i18n_options(options)
    options
  end

  # Get message for given
  def find_message(kind, options = {})
    options[:scope] ||= translation_scope
    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)
  end

  # Controllers inheriting DeviseController are advised to override this
  # method so that other controllers inheriting from them would use
  # existing translations.
  def translation_scope
    "devise.#{controller_name}"
  end

  def clean_up_passwords(object)
    object.clean_up_passwords if object.respond_to?(:clean_up_passwords)
  end

  def respond_with_navigational(*args, &block)
    respond_with(*args) do |format|
      format.any(*navigational_formats, &block)
    end
  end

  def resource_params
    params.fetch(resource_name, {})
  end

  ActiveSupport.run_load_hooks(:devise_controller, self)
end


================================================
FILE: app/helpers/devise_helper.rb
================================================
# frozen_string_literal: true

# Keeping the helper around for backward compatibility.
module DeviseHelper
end


================================================
FILE: app/mailers/devise/mailer.rb
================================================
# frozen_string_literal: true

if defined?(ActionMailer)
  class Devise::Mailer < Devise.parent_mailer.constantize
    include Devise::Mailers::Helpers

    def confirmation_instructions(record, token, opts = {})
      @token = token
      devise_mail(record, :confirmation_instructions, opts)
    end

    def reset_password_instructions(record, token, opts = {})
      @token = token
      devise_mail(record, :reset_password_instructions, opts)
    end

    def unlock_instructions(record, token, opts = {})
      @token = token
      devise_mail(record, :unlock_instructions, opts)
    end

    def email_changed(record, opts = {})
      devise_mail(record, :email_changed, opts)
    end

    def password_change(record, opts = {})
      devise_mail(record, :password_change, opts)
    end
  end
end


================================================
FILE: app/views/devise/confirmations/new.html.erb
================================================
<h2>Resend confirmation instructions</h2>

<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <p><%= f.label :email %></p>
    <p><%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %></p>
  </div>

  <div class="actions">
    <%= f.submit "Resend confirmation instructions" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>


================================================
FILE: app/views/devise/mailer/confirmation_instructions.html.erb
================================================
<p>Welcome <%= @email %>!</p>

<p>You can confirm your account email through the link below:</p>

<p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>


================================================
FILE: app/views/devise/mailer/email_changed.html.erb
================================================
<p>Hello <%= @email %>!</p>

<% if @resource.try(:unconfirmed_email?) %>
  <p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p>
<% else %>
  <p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p>
<% end %>


================================================
FILE: app/views/devise/mailer/password_change.html.erb
================================================
<p>Hello <%= @resource.email %>!</p>

<p>We're contacting you to notify you that your password has been changed.</p>


================================================
FILE: app/views/devise/mailer/reset_password_instructions.html.erb
================================================
<p>Hello <%= @resource.email %>!</p>

<p>Someone has requested a link to change your password. You can do this through the link below.</p>

<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>

<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>


================================================
FILE: app/views/devise/mailer/unlock_instructions.html.erb
================================================
<p>Hello <%= @resource.email %>!</p>

<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>

<p>Click the link below to unlock your account:</p>

<p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>


================================================
FILE: app/views/devise/passwords/edit.html.erb
================================================
<h2>Change your password</h2>

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>
  <%= f.hidden_field :reset_password_token %>

  <div class="field">
    <p><%= f.label :password, "New password" %></p>
    <% if @minimum_password_length %>
      <p><em>(<%= @minimum_password_length %> characters minimum)</em></p>
    <% end %>
    <p><%= f.password_field :password, autofocus: true, autocomplete: "new-password" %></p>
  </div>

  <div class="field">
    <p><%= f.label :password_confirmation, "Confirm new password" %></p>
    <p><%= f.password_field :password_confirmation, autocomplete: "new-password" %></p>
  </div>

  <div class="actions">
    <%= f.submit "Change my password" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>


================================================
FILE: app/views/devise/passwords/new.html.erb
================================================
<h2>Forgot your password?</h2>

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <p><%= f.label :email %></p>
    <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
  </div>

  <div class="actions">
    <%= f.submit "Send me password reset instructions" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>


================================================
FILE: app/views/devise/registrations/edit.html.erb
================================================
<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <p><%= f.label :email %></p>
    <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
  </div>

  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
    <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
  <% end %>

  <div class="field">
    <p><%= f.label :password %> <i>(leave blank if you don't want to change it)</i></p>
    <p><%= f.password_field :password, autocomplete: "new-password" %></p>
    <% if @minimum_password_length %>
      <p><em><%= @minimum_password_length %> characters minimum</em></p>
    <% end %>
  </div>

  <div class="field">
    <p><%= f.label :password_confirmation %></p>
    <p><%= f.password_field :password_confirmation, autocomplete: "new-password" %></p>
  </div>

  <div class="field">
    <p><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i></p>
    <p><%= f.password_field :current_password, autocomplete: "current-password" %></p>
  </div>

  <div class="actions">
    <%= f.submit "Update" %>
  </div>
<% end %>

<h3>Cancel my account</h3>

<div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>

<%= link_to "Back", :back %>


================================================
FILE: app/views/devise/registrations/new.html.erb
================================================
<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <p><%= f.label :email %></p>
    <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
  </div>

  <div class="field">
    <p><%= f.label :password %></p>
    <% if @minimum_password_length %>
      <p><em>(<%= @minimum_password_length %> characters minimum)</em></p>
    <% end %>
    <p><%= f.password_field :password, autocomplete: "new-password" %></p>
  </div>

  <div class="field">
    <p><%= f.label :password_confirmation %></p>
    <p><%= f.password_field :password_confirmation, autocomplete: "new-password" %></p>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>


================================================
FILE: app/views/devise/sessions/new.html.erb
================================================
<h2>Log in</h2>

<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
  <div class="field">
    <p><%= f.label :email %></p>
    <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
  </div>

  <div class="field">
    <p><%= f.label :password %></p>
    <p><%= f.password_field :password, autocomplete: "current-password" %></p>
  </div>

  <% if devise_mapping.rememberable? %>
    <div class="field">
      <p><%= f.check_box :remember_me %></p>
      <p><%= f.label :remember_me %></p>
    </div>
  <% end %>

  <div class="actions">
    <%= f.submit "Log in" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>


================================================
FILE: app/views/devise/shared/_error_messages.html.erb
================================================
<% if resource.errors.any? %>
  <div id="error_explanation" data-turbo-temporary>
    <h2>
      <%= I18n.t("errors.messages.not_saved",
                 count: resource.errors.count,
                 resource: resource.class.model_name.human.downcase)
       %>
    </h2>
    <ul>
      <% resource.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>


================================================
FILE: app/views/devise/shared/_links.html.erb
================================================
<%- if controller_name != 'sessions' %>
  <p><%= link_to "Log in", new_session_path(resource_name) %></p>
<% end %>

<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
  <p><%= link_to "Sign up", new_registration_path(resource_name) %></p>
<% end %>

<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
  <p><%= link_to "Forgot your password?", new_password_path(resource_name) %></p>
<% end %>

<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
  <p><%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %></p>
<% end %>

<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
  <p><%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %></p>
<% end %>

<%- if devise_mapping.omniauthable? %>
  <%- resource_class.omniauth_providers.each do |provider| %>
    <p><%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %></p>
  <% end %>
<% end %>


================================================
FILE: app/views/devise/unlocks/new.html.erb
================================================
<h2>Resend unlock instructions</h2>

<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <p><%= f.label :email %></p>
    <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
  </div>

  <div class="actions">
    <%= f.submit "Resend unlock instructions" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>


================================================
FILE: bin/test
================================================
#!/usr/bin/env ruby
$: << File.expand_path(File.expand_path('../../test', __FILE__))

require 'bundler/setup'
require 'rails/test_unit/runner'
require 'rails/test_unit/reporter'
require 'rails/test_unit/line_filtering'

Rails::TestUnitReporter.executable = 'bin/test'

Rails::TestUnit::Runner.parse_options(ARGV)
Rails::TestUnit::Runner.run(ARGV)


================================================
FILE: config/locales/en.yml
================================================
# Additional translations at https://github.com/heartcombo/devise/wiki/I18n

en:
  devise:
    confirmations:
      confirmed: "Your email address has been successfully confirmed."
      send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
      send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
    failure:
      already_authenticated: "You are already signed in."
      inactive: "Your account is not activated yet."
      invalid: "Invalid %{authentication_keys} or password."
      locked: "Your account is locked."
      last_attempt: "You have one more attempt before your account is locked."
      not_found_in_database: "Invalid %{authentication_keys} or password."
      timeout: "Your session expired. Please sign in again to continue."
      unauthenticated: "You need to sign in or sign up before continuing."
      unconfirmed: "You have to confirm your email address before continuing."
    mailer:
      confirmation_instructions:
        subject: "Confirmation instructions"
      reset_password_instructions:
        subject: "Reset password instructions"
      unlock_instructions:
        subject: "Unlock instructions"
      email_changed:
        subject: "Email Changed"
      password_change:
        subject: "Password Changed"
    omniauth_callbacks:
      failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
      success: "Successfully authenticated from %{kind} account."
    passwords:
      no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
      send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
      send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
      updated: "Your password has been changed successfully. You are now signed in."
      updated_not_active: "Your password has been changed successfully."
    registrations:
      destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
      signed_up: "Welcome! You have signed up successfully."
      signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
      signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
      signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
      update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
      updated: "Your account has been updated successfully."
      updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again."
    sessions:
      signed_in: "Signed in successfully."
      signed_out: "Signed out successfully."
      already_signed_out: "Signed out successfully."
    unlocks:
      send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
      send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
      unlocked: "Your account has been unlocked successfully. Please sign in to continue."
  errors:
    messages:
      already_confirmed: "was already confirmed, please try signing in"
      confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
      expired: "has expired, please request a new one"
      not_found: "not found"
      not_locked: "was not locked"
      not_saved:
        one: "1 error prohibited this %{resource} from being saved:"
        other: "%{count} errors prohibited this %{resource} from being saved:"


================================================
FILE: devise.gemspec
================================================
# -*- encoding: utf-8 -*-
# frozen_string_literal: true

$:.push File.expand_path("../lib", __FILE__)
require "devise/version"

Gem::Specification.new do |s|
  s.name        = "devise"
  s.version     = Devise::VERSION.dup
  s.platform    = Gem::Platform::RUBY
  s.licenses    = ["MIT"]
  s.summary     = "Flexible authentication solution for Rails with Warden"
  s.email       = "heartcombo.oss@gmail.com"
  s.homepage    = "https://github.com/heartcombo/devise"
  s.description = "Flexible authentication solution for Rails with Warden"
  s.authors     = ['José Valim', 'Carlos Antônio']
  s.metadata    = {
    "homepage_uri"      => "https://github.com/heartcombo/devise",
    "documentation_uri" => "https://rubydoc.info/github/heartcombo/devise",
    "changelog_uri"     => "https://github.com/heartcombo/devise/blob/main/CHANGELOG.md",
    "source_code_uri"   => "https://github.com/heartcombo/devise",
    "bug_tracker_uri"   => "https://github.com/heartcombo/devise/issues",
    "wiki_uri"          => "https://github.com/heartcombo/devise/wiki"
  }

  s.files         = Dir["{app,config,lib}/**/*", "CHANGELOG.md", "MIT-LICENSE", "README.md"]
  s.require_paths = ["lib"]
  s.required_ruby_version = '>= 2.7.0'

  s.add_dependency("warden", "~> 1.2.3")
  s.add_dependency("orm_adapter", "~> 0.1")
  s.add_dependency("bcrypt", "~> 3.0")
  s.add_dependency("railties", ">= 7.0")
  s.add_dependency("responders")
end


================================================
FILE: gemfiles/Gemfile-rails-7-0
================================================
source "https://rubygems.org"

gemspec path: ".."

gem "rails", "~> 7.0.0"
gem "omniauth"
gem "omniauth-oauth2"
gem "rdoc"

gem "rails-controller-testing"

gem "responders", "~> 3.1"

group :test do
  gem "omniauth-facebook"
  gem "omniauth-openid"
  gem "rexml"
  gem "timecop"
  gem "webrat", "0.7.3", require: false
  gem "mocha", "~> 2.1", require: false
  gem "minitest", "< 6"
  gem "ostruct"
end

platforms :ruby do
  gem "sqlite3", "~> 1.4"
end

group :mongoid do
  gem "mongoid", "~> 7.5"
end


================================================
FILE: gemfiles/Gemfile-rails-7-1
================================================
source "https://rubygems.org"

gemspec path: ".."

gem "rails", "~> 7.1.0"
gem "omniauth"
gem "omniauth-oauth2"
gem "rdoc"

gem "rails-controller-testing"

gem "responders", "~> 3.1"

group :test do
  gem "omniauth-facebook"
  gem "omniauth-openid"
  gem "rexml"
  gem "timecop"
  gem "webrat"
  gem "mocha", "~> 2.1", require: false
  gem "minitest", "< 6"
  gem "ostruct"
end

platforms :ruby do
  gem "sqlite3", "~> 1.4"
end

group :mongoid do
  gem "mongoid", "~> 8.1"
end


================================================
FILE: gemfiles/Gemfile-rails-7-2
================================================
source "https://rubygems.org"

gemspec path: ".."

gem "rails", "~> 7.2.0"
gem "omniauth"
gem "omniauth-oauth2"
gem "rdoc"

gem "rails-controller-testing"

gem "responders", "~> 3.1"

group :test do
  gem "omniauth-facebook"
  gem "omniauth-openid"
  gem "rexml"
  gem "timecop"
  gem "webrat", require: false
  gem "mocha", "~> 2.1", require: false
  gem "minitest", "< 6"
  gem "ostruct"
end

platforms :ruby do
  gem "sqlite3"
end

group :mongoid do
  gem "mongoid", "~> 8.1"
end


================================================
FILE: gemfiles/Gemfile-rails-8-0
================================================
source "https://rubygems.org"

gemspec path: ".."

gem "rails", "~> 8.0.0"
gem "omniauth"
gem "omniauth-oauth2"
gem "rdoc"

gem "rails-controller-testing"

gem "responders", "~> 3.1"

group :test do
  gem "omniauth-facebook"
  gem "omniauth-openid"
  gem "rexml"
  gem "timecop"
  gem 'webrat'
  gem "mocha", "~> 2.1", require: false
  gem "minitest", "< 6"
  gem "ostruct"
end

platforms :ruby do
  gem "sqlite3"
end

group :mongoid do
  gem "mongoid", "~> 8.1"
end


================================================
FILE: gemfiles/Gemfile-rails-main
================================================
source "https://rubygems.org"

gemspec path: ".."

gem "rails", github: "rails/rails", branch: "main"
gem "omniauth"
gem "omniauth-oauth2"
gem "rdoc"

gem "rails-controller-testing"

gem "responders", "~> 3.1"

group :test do
  gem "omniauth-facebook"
  gem "omniauth-openid"
  gem "rexml"
  gem "timecop"
  gem "webrat", "0.7.3", require: false
  gem "mocha", "~> 2.1", require: false
  gem "minitest", "< 6"
  gem "ostruct"
end

platforms :ruby do
  gem "sqlite3"
end

group :mongoid do
  gem "mongoid", github: "mongodb/mongoid", branch: "master"
end


================================================
FILE: guides/bug_report_templates/integration_test.rb
================================================
# frozen_string_literal: true

begin
  require 'bundler/inline'
rescue LoadError => e
  $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
  raise e
end

gemfile(true) do
  source 'https://rubygems.org'
  # Activate the gem you are reporting the issue against.
  gem 'rails', '~> 4.2.0'
  gem 'devise', '~> 4.0'
  gem 'sqlite3'
  gem 'byebug'
end

require 'rack/test'
require 'action_controller/railtie'
require 'active_record'
require 'devise/rails/routes'
require 'devise/rails/warden_compat'

ActiveRecord::Base.establish_connection( adapter: :sqlite3, database:  ':memory:')

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      t.string :email,              null: false
      t.string :encrypted_password, null: true
      t.timestamps null: false
    end

  end
end

Devise.setup do |config|
  require 'devise/orm/active_record'
  config.secret_key = 'secret_key_base'
end

class TestApp < Rails::Application
  config.root = File.dirname(__FILE__)
  config.session_store :cookie_store, key: 'cookie_store_key'
  secrets.secret_token    = 'secret_token'
  secrets.secret_key_base = 'secret_key_base'
  config.eager_load = false

  config.middleware.use Warden::Manager do |config|
    Devise.warden_config = config
  end

  config.logger = Logger.new($stdout)
  Rails.logger  = config.logger

end

Rails.application.initialize!

DeviseCreateUsers.migrate(:up)

class User < ActiveRecord::Base
  devise :database_authenticatable
end

Rails.application.routes.draw do
  devise_for :users

  get '/' => 'test#index'
end

class ApplicationController < ActionController::Base
end

class TestController < ApplicationController
  include Rails.application.routes.url_helpers

  before_action :authenticate_user!

  def index
    render plain: 'Home'
  end
end

require 'minitest/autorun'

class BugTest < ActionDispatch::IntegrationTest
  include Rack::Test::Methods
  include Warden::Test::Helpers

  def test_returns_success
    Warden.test_mode!

    login_as User.create!(email: 'test@test.com', password: 'test123456', password_confirmation: 'test123456')

    get '/'
    assert last_response.ok?
  end

  private

  def app
    Rails.application
  end
end


================================================
FILE: lib/devise/controllers/helpers.rb
================================================
# frozen_string_literal: true

module Devise
  module Controllers
    # Those helpers are convenience methods added to ApplicationController.
    module Helpers
      extend ActiveSupport::Concern
      include Devise::Controllers::SignInOut
      include Devise::Controllers::StoreLocation

      included do
        if respond_to?(:helper_method)
          helper_method :warden, :signed_in?, :devise_controller?
        end
      end

      module ClassMethods
        # Define authentication filters and accessor helpers for a group of mappings.
        # These methods are useful when you are working with multiple mappings that
        # share some functionality. They are pretty much the same as the ones
        # defined for normal mappings.
        #
        # Example:
        #
        #   inside BlogsController (or any other controller, it doesn't matter which):
        #     devise_group :blogger, contains: [:user, :admin]
        #
        #   Generated methods:
        #     authenticate_blogger!  # Redirects unless user or admin are signed in
        #     blogger_signed_in?     # Checks whether there is either a user or an admin signed in
        #     current_blogger        # Currently signed in user or admin
        #     current_bloggers       # Currently signed in user and admin
        #
        #   Use:
        #     before_action :authenticate_blogger!              # Redirects unless either a user or an admin are authenticated
        #     before_action ->{ authenticate_blogger! :admin }  # Redirects to the admin login page
        #     current_blogger :user                             # Preferably returns a User if one is signed in
        #
        def devise_group(group_name, opts = {})
          mappings = "[#{ opts[:contains].map { |m| ":#{m}" }.join(',') }]"

          class_eval <<-METHODS, __FILE__, __LINE__ + 1
            def authenticate_#{group_name}!(favorite = nil, opts = {})
              unless #{group_name}_signed_in?
                mappings = #{mappings}
                mappings.unshift mappings.delete(favorite.to_sym) if favorite
                mappings.each do |mapping|
                  opts[:scope] = mapping
                  opts[:locale] = I18n.locale
                  warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
                end
              end
            end

            def #{group_name}_signed_in?
              #{mappings}.any? do |mapping|
                warden.authenticate?(scope: mapping)
              end
            end

            def current_#{group_name}(favorite = nil)
              mappings = #{mappings}
              mappings.unshift mappings.delete(favorite.to_sym) if favorite
              mappings.each do |mapping|
                current = warden.authenticate(scope: mapping)
                return current if current
              end
              nil
            end

            def current_#{group_name.to_s.pluralize}
              #{mappings}.map do |mapping|
                warden.authenticate(scope: mapping)
              end.compact
            end

            if respond_to?(:helper_method)
              helper_method "current_#{group_name}", "current_#{group_name.to_s.pluralize}", "#{group_name}_signed_in?"
            end
          METHODS
        end

        def log_process_action(payload)
          payload[:status] ||= 401 unless payload[:exception]
          super
        end
      end

      # Define authentication filters and accessor helpers based on mappings.
      # These filters should be used inside the controllers as before_actions,
      # so you can control the scope of the user who should be signed in to
      # access that specific controller/action.
      # Example:
      #
      #   Roles:
      #     User
      #     Admin
      #
      #   Generated methods:
      #     authenticate_user!  # Signs user in or redirect
      #     authenticate_admin! # Signs admin in or redirect
      #     user_signed_in?     # Checks whether there is a user signed in or not
      #     admin_signed_in?    # Checks whether there is an admin signed in or not
      #     current_user        # Current signed in user
      #     current_admin       # Current signed in admin
      #     user_session        # Session data available only to the user scope
      #     admin_session       # Session data available only to the admin scope
      #
      #   Use:
      #     before_action :authenticate_user!  # Tell devise to use :user map
      #     before_action :authenticate_admin! # Tell devise to use :admin map
      #
      def self.define_helpers(mapping) #:nodoc:
        mapping = mapping.name

        class_eval <<-METHODS, __FILE__, __LINE__ + 1
          def authenticate_#{mapping}!(opts = {})
            opts[:scope] = :#{mapping}
            opts[:locale] = I18n.locale
            warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
          end

          def #{mapping}_signed_in?
            !!current_#{mapping}
          end

          def current_#{mapping}
            @current_#{mapping} ||= warden.authenticate(scope: :#{mapping})
          end

          def #{mapping}_session
            current_#{mapping} && warden.session(:#{mapping})
          end
        METHODS

        ActiveSupport.on_load(:action_controller) do
          if respond_to?(:helper_method)
            helper_method "current_#{mapping}", "#{mapping}_signed_in?", "#{mapping}_session"
          end
        end
      end

      # The main accessor for the warden proxy instance
      def warden
        request.env['warden'] or raise MissingWarden
      end

      # Return true if it's a devise_controller. false to all controllers unless
      # the controllers defined inside devise. Useful if you want to apply a before
      # filter to all controllers, except the ones in devise:
      #
      #   before_action :my_filter, unless: :devise_controller?
      def devise_controller?
        is_a?(::DeviseController)
      end

      # Set up a param sanitizer to filter parameters using strong_parameters. See
      # lib/devise/parameter_sanitizer.rb for more info. Override this
      # method in your application controller to use your own parameter sanitizer.
      def devise_parameter_sanitizer
        @devise_parameter_sanitizer ||= Devise::ParameterSanitizer.new(resource_class, resource_name, params)
      end

      # Tell warden that params authentication is allowed for that specific page.
      def allow_params_authentication!
        request.env["devise.allow_params_authentication"] = true
      end

      # The scope root url to be used when they're signed in. By default, it first
      # tries to find a resource_root_path, otherwise it uses the root_path.
      def signed_in_root_path(resource_or_scope)
        scope = Devise::Mapping.find_scope!(resource_or_scope)
        router_name = Devise.mappings[scope].router_name

        home_path = "#{scope}_root_path"

        context = router_name ? send(router_name) : self

        if context.respond_to?(home_path, true)
          context.send(home_path)
        elsif context.respond_to?(:root_path)
          context.root_path
        elsif respond_to?(:root_path)
          root_path
        else
          "/"
        end
      end

      # The default url to be used after signing in. This is used by all Devise
      # controllers and you can overwrite it in your ApplicationController to
      # provide a custom hook for a custom resource.
      #
      # By default, it first tries to find a valid resource_return_to key in the
      # session, then it fallbacks to resource_root_path, otherwise it uses the
      # root path. For a user scope, you can define the default url in
      # the following way:
      #
      #   get '/users' => 'users#index', as: :user_root # creates user_root_path
      #
      #   namespace :user do
      #     root 'users#index' # creates user_root_path
      #   end
      #
      # If the resource root path is not defined, root_path is used. However,
      # if this default is not enough, you can customize it, for example:
      #
      #   def after_sign_in_path_for(resource)
      #     stored_location_for(resource) ||
      #       if resource.is_a?(User) && resource.can_publish?
      #         publisher_url
      #       else
      #         super
      #       end
      #   end
      #
      def after_sign_in_path_for(resource_or_scope)
        stored_location_for(resource_or_scope) || signed_in_root_path(resource_or_scope)
      end

      # Method used by sessions controller to sign out a user. You can overwrite
      # it in your ApplicationController to provide a custom hook for a custom
      # scope. Notice that differently from +after_sign_in_path_for+ this method
      # receives a symbol with the scope, and not the resource.
      #
      # By default it is the root_path.
      def after_sign_out_path_for(resource_or_scope)
        scope = Devise::Mapping.find_scope!(resource_or_scope)
        router_name = Devise.mappings[scope].router_name
        context = router_name ? send(router_name) : self
        context.respond_to?(:root_path) ? context.root_path : "/"
      end

      # Sign in a user and tries to redirect first to the stored location and
      # then to the url specified by after_sign_in_path_for. It accepts the same
      # parameters as the sign_in method.
      def sign_in_and_redirect(resource_or_scope, *args)
        options  = args.extract_options!
        scope    = Devise::Mapping.find_scope!(resource_or_scope)
        resource = args.last || resource_or_scope
        sign_in(scope, resource, options)
        redirect_to after_sign_in_path_for(resource)
      end

      # Sign out a user and tries to redirect to the url specified by
      # after_sign_out_path_for.
      def sign_out_and_redirect(resource_or_scope)
        scope = Devise::Mapping.find_scope!(resource_or_scope)
        redirect_path = after_sign_out_path_for(scope)
        Devise.sign_out_all_scopes ? sign_out : sign_out(scope)
        redirect_to redirect_path
      end

      # Overwrite Rails' handle unverified request to sign out all scopes,
      # clear run strategies and remove cached variables.
      def handle_unverified_request
        super # call the default behavior which resets/nullifies/raises
        request.env["devise.skip_storage"] = true
        sign_out_all_scopes(false)
      end

      def request_format
        @request_format ||= request.format.try(:ref)
      end

      def is_navigational_format?
        Devise.navigational_formats.include?(request_format)
      end

      # Check if flash messages should be emitted. Default is to do it on
      # navigational formats
      def is_flashing_format?
        request.respond_to?(:flash) && is_navigational_format?
      end

      private

      def expire_data_after_sign_out!
        Devise.mappings.each { |_,m| instance_variable_set("@current_#{m.name}", nil) }
        super
      end
    end
  end

  class MissingWarden < StandardError
    def initialize
      super "Devise could not find the `Warden::Proxy` instance on your request environment.\n" + \
        "Make sure that your application is loading Devise and Warden as expected and that " + \
        "the `Warden::Manager` middleware is present in your middleware stack.\n" + \
        "If you are seeing this on one of your tests, ensure that your tests are either " + \
        "executing the Rails middleware stack or that your tests are using the `Devise::Test::ControllerHelpers` " + \
        "module to inject the `request.env['warden']` object for you."
    end
  end
end


================================================
FILE: lib/devise/controllers/rememberable.rb
================================================
# frozen_string_literal: true

module Devise
  module Controllers
    # A module that may be optionally included in a controller in order
    # to provide remember me behavior. Useful when signing in is done
    # through a callback, like in OmniAuth.
    module Rememberable
      # Return default cookie values retrieved from session options.
      def self.cookie_values
        Rails.configuration.session_options.slice(:path, :domain, :secure)
      end

      def remember_me_is_active?(resource)
        return false unless resource.respond_to?(:remember_me)
        scope = Devise::Mapping.find_scope!(resource)
        _, token, generated_at = cookies.signed[remember_key(resource, scope)]
        resource.remember_me?(token, generated_at)
      end

      # Remembers the given resource by setting up a cookie
      def remember_me(resource)
        return if request.env["devise.skip_storage"]
        scope = Devise::Mapping.find_scope!(resource)
        resource.remember_me!
        cookies.signed[remember_key(resource, scope)] = remember_cookie_values(resource)
      end

      # Forgets the given resource by deleting a cookie
      def forget_me(resource)
        scope = Devise::Mapping.find_scope!(resource)
        resource.forget_me!
        cookies.delete(remember_key(resource, scope), forget_cookie_values(resource))
      end

      protected

      def forget_cookie_values(resource)
        Devise::Controllers::Rememberable.cookie_values.merge!(resource.rememberable_options)
      end

      def remember_cookie_values(resource)
        options = { httponly: true }
        options.merge!(forget_cookie_values(resource))
        options.merge!(
          value: resource.class.serialize_into_cookie(resource),
          expires: resource.remember_expires_at
        )
      end

      def remember_key(resource, scope)
        resource.rememberable_options.fetch(:key, "remember_#{scope}_token")
      end
    end
  end
end


================================================
FILE: lib/devise/controllers/responder.rb
================================================
# frozen_string_literal: true

module Devise
  module Controllers
    # Custom Responder to configure default statuses that only apply to Devise,
    # and allow to integrate more easily with Hotwire/Turbo.
    class Responder < ActionController::Responder
      if respond_to?(:error_status=) && respond_to?(:redirect_status=)
        self.error_status = :ok
        self.redirect_status = :found
      else
        # TODO: remove this support for older Rails versions, which aren't supported by Turbo
        # and/or responders. It won't allow configuring a custom response, but it allows Devise
        # to use these methods and defaults across the implementation more easily.
        def self.error_status
          :ok
        end

        def self.redirect_status
          :found
        end

        def self.error_status=(*)
          warn "[DEVISE] Setting the error status on the Devise responder has no effect with this " \
            "version of `responders`, please make sure you're using a newer version. Check the changelog for more info."
        end

        def self.redirect_status=(*)
          warn "[DEVISE] Setting the redirect status on the Devise responder has no effect with this " \
            "version of `responders`, please make sure you're using a newer version. Check the changelog for more info."
        end
      end
    end
  end
end


================================================
FILE: lib/devise/controllers/scoped_views.rb
================================================
# frozen_string_literal: true

module Devise
  module Controllers
    module ScopedViews
      extend ActiveSupport::Concern

      module ClassMethods
        def scoped_views?
          defined?(@scoped_views) ? @scoped_views : Devise.scoped_views
        end

        def scoped_views=(value)
          @scoped_views = value
        end
      end
    end
  end
end


================================================
FILE: lib/devise/controllers/sign_in_out.rb
================================================
# frozen_string_literal: true

module Devise
  module Controllers
    # Provide sign in and sign out functionality.
    # Included by default in all controllers.
    module SignInOut
      # Return true if the given scope is signed in session. If no scope given, return
      # true if any scope is signed in. This will run authentication hooks, which may
      # cause exceptions to be thrown from this method; if you simply want to check
      # if a scope has already previously been authenticated without running
      # authentication hooks, you can directly call `warden.authenticated?(scope: scope)`
      def signed_in?(scope = nil)
        [scope || Devise.mappings.keys].flatten.any? do |_scope|
          warden.authenticate?(scope: _scope)
        end
      end

      # Sign in a user that already was authenticated. This helper is useful for logging
      # users in after sign up. All options given to sign_in is passed forward
      # to the set_user method in warden.
      # If you are using a custom warden strategy and the timeoutable module, you have to
      # set `env["devise.skip_timeout"] = true` in the request to use this method, like we do
      # in the sessions controller: https://github.com/heartcombo/devise/blob/main/app/controllers/devise/sessions_controller.rb#L7
      #
      # Examples:
      #
      #   sign_in :user, @user                      # sign_in(scope, resource)
      #   sign_in @user                             # sign_in(resource)
      #   sign_in @user, event: :authentication     # sign_in(resource, options)
      #   sign_in @user, store: false               # sign_in(resource, options)
      #
      def sign_in(resource_or_scope, *args)
        options  = args.extract_options!
        scope    = Devise::Mapping.find_scope!(resource_or_scope)
        resource = args.last || resource_or_scope

        expire_data_after_sign_in!

        if warden.user(scope) == resource && !options.delete(:force)
          # Do nothing. User already signed in and we are not forcing it.
          true
        else
          warden.set_user(resource, options.merge!(scope: scope))
        end
      end

      # Sign in a user bypassing the warden callbacks and stores the user
      # straight in session. This option is useful in cases the user is already
      # signed in, but we want to refresh the credentials in session.
      #
      # Examples:
      #
      #   bypass_sign_in @user, scope: :user
      #   bypass_sign_in @user
      def bypass_sign_in(resource, scope: nil)
        scope ||= Devise::Mapping.find_scope!(resource)
        expire_data_after_sign_in!
        warden.session_serializer.store(resource, scope)
      end

      # Sign out a given user or scope. This helper is useful for signing out a user
      # after deleting accounts. Returns true if there was a logout and false if there
      # is no user logged in on the referred scope
      #
      # Examples:
      #
      #   sign_out :user     # sign_out(scope)
      #   sign_out @user     # sign_out(resource)
      #
      def sign_out(resource_or_scope = nil)
        return sign_out_all_scopes unless resource_or_scope
        scope = Devise::Mapping.find_scope!(resource_or_scope)
        user = warden.user(scope: scope, run_callbacks: false) # If there is no user

        warden.logout(scope)
        warden.clear_strategies_cache!(scope: scope)
        instance_variable_set(:"@current_#{scope}", nil)

        !!user
      end

      # Sign out all active users or scopes. This helper is useful for signing out all roles
      # in one click. This signs out ALL scopes in warden. Returns true if there was at least one logout
      # and false if there was no user logged in on all scopes.
      def sign_out_all_scopes(lock = true)
        users = Devise.mappings.keys.map { |s| warden.user(scope: s, run_callbacks: false) }

        warden.logout
        expire_data_after_sign_out!
        warden.clear_strategies_cache!
        warden.lock! if lock

        users.any?
      end

      private

      def expire_data_after_sign_in!
        session.keys.grep(/^devise\./).each { |k| session.delete(k) }
      end

      alias :expire_data_after_sign_out! :expire_data_after_sign_in!
    end
  end
end


================================================
FILE: lib/devise/controllers/store_location.rb
================================================
# frozen_string_literal: true

require "uri"

module Devise
  module Controllers
    # Provide the ability to store a location.
    # Used to redirect back to a desired path after sign in.
    # Included by default in all controllers.
    module StoreLocation
      # Returns and delete (if it's navigational format) the url stored in the session for
      # the given scope. Useful for giving redirect backs after sign up:
      #
      # Example:
      #
      #   redirect_to stored_location_for(:user) || root_path
      #
      def stored_location_for(resource_or_scope)
        session_key = stored_location_key_for(resource_or_scope)

        if is_navigational_format?
          session.delete(session_key)
        else
          session[session_key]
        end
      end

      # Stores the provided location to redirect the user after signing in.
      # Useful in combination with the `stored_location_for` helper.
      #
      # Example:
      #
      #   store_location_for(:user, dashboard_path)
      #   redirect_to user_facebook_omniauth_authorize_path
      #
      def store_location_for(resource_or_scope, location)
        session_key = stored_location_key_for(resource_or_scope)
        
        path = extract_path_from_location(location)
        session[session_key] = path if path
      end

      private

      def parse_uri(location)
        location && URI.parse(location)
      rescue URI::InvalidURIError
        nil
      end

      def stored_location_key_for(resource_or_scope)
        scope = Devise::Mapping.find_scope!(resource_or_scope)
        "#{scope}_return_to"
      end

      def extract_path_from_location(location)
        uri = parse_uri(location)

        if uri 
          path = remove_domain_from_uri(uri)
          path = add_fragment_back_to_path(uri, path)

          path
        end
      end

      def remove_domain_from_uri(uri)
        [uri.path.sub(/\A\/+/, '/'), uri.query].compact.join('?')
      end

      def add_fragment_back_to_path(uri, path)
        [path, uri.fragment].compact.join('#')
      end
    end
  end
end


================================================
FILE: lib/devise/controllers/url_helpers.rb
================================================
# frozen_string_literal: true

module Devise
  module Controllers
    # Create url helpers to be used with resource/scope configuration. Acts as
    # proxies to the generated routes created by devise.
    # Resource param can be a string or symbol, a class, or an instance object.
    # Example using a :user resource:
    #
    #   new_session_path(:user)      => new_user_session_path
    #   session_path(:user)          => user_session_path
    #   destroy_session_path(:user)  => destroy_user_session_path
    #
    #   new_password_path(:user)     => new_user_password_path
    #   password_path(:user)         => user_password_path
    #   edit_password_path(:user)    => edit_user_password_path
    #
    #   new_confirmation_path(:user) => new_user_confirmation_path
    #   confirmation_path(:user)     => user_confirmation_path
    #
    # Those helpers are included by default to ActionController::Base.
    #
    # In case you want to add such helpers to another class, you can do
    # that as long as this new class includes both url_helpers and
    # mounted_helpers. Example:
    #
    #     include Rails.application.routes.url_helpers
    #     include Rails.application.routes.mounted_helpers
    #
    module UrlHelpers
      def self.remove_helpers!
        self.instance_methods.map(&:to_s).grep(/_(url|path)$/).each do |method|
          remove_method method
        end
      end

      def self.generate_helpers!(routes = nil)
        routes ||= begin
          mappings = Devise.mappings.values.map(&:used_helpers).flatten.uniq
          Devise::URL_HELPERS.slice(*mappings)
        end

        routes.each do |module_name, actions|
          [:path, :url].each do |path_or_url|
            actions.each do |action|
              action = action ? "#{action}_" : ""
              method = :"#{action}#{module_name}_#{path_or_url}"

              define_method method do |resource_or_scope, *args|
                scope = Devise::Mapping.find_scope!(resource_or_scope)
                router_name = Devise.mappings[scope].router_name
                context = router_name ? send(router_name) : _devise_route_context
                context.send("#{action}#{scope}_#{module_name}_#{path_or_url}", *args)
              end
            end
          end
        end
      end

      generate_helpers!(Devise::URL_HELPERS)

      private

      def _devise_route_context
        @_devise_route_context ||= send(Devise.available_router_name)
      end
    end
  end
end


================================================
FILE: lib/devise/delegator.rb
================================================
# frozen_string_literal: true

module Devise
  # Checks the scope in the given environment and returns the associated failure app.
  class Delegator
    def call(env)
      failure_app(env).call(env)
    end

    def failure_app(env)
      app = env["warden.options"] &&
        (scope = env["warden.options"][:scope]) &&
        Devise.mappings[scope.to_sym].failure_app

      app || Devise::FailureApp
    end
  end
end


================================================
FILE: lib/devise/encryptor.rb
================================================
# frozen_string_literal: true

require 'bcrypt'

module Devise
  module Encryptor
    def self.digest(klass, password)
      if klass.pepper.present?
        password = "#{password}#{klass.pepper}"
      end
      ::BCrypt::Password.create(password, cost: klass.stretches).to_s
    end

    def self.compare(klass, hashed_password, password)
      return false if hashed_password.blank?
      bcrypt   = ::BCrypt::Password.new(hashed_password)
      if klass.pepper.present?
        password = "#{password}#{klass.pepper}"
      end
      password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
      Devise.secure_compare(password, hashed_password)
    end
  end
end


================================================
FILE: lib/devise/failure_app.rb
================================================
# frozen_string_literal: true

require "action_controller/metal"

module Devise
  # Failure application that will be called every time :warden is thrown from
  # any strategy or hook. It is responsible for redirecting the user to the sign
  # in page based on current scope and mapping. If no scope is given, it
  # redirects to the default_url.
  class FailureApp < ActionController::Metal
    include ActionController::UrlFor
    include ActionController::Redirecting

    include Rails.application.routes.url_helpers
    include Rails.application.routes.mounted_helpers

    include Devise::Controllers::StoreLocation

    delegate :flash, to: :request

    include AbstractController::Callbacks
    around_action do |failure_app, action|
      I18n.with_locale(failure_app.i18n_locale, &action)
    end

    def self.call(env)
      @respond ||= action(:respond)
      @respond.call(env)
    end

    # Try retrieving the URL options from the parent controller (usually
    # ApplicationController). Instance methods are not supported at the moment,
    # so only the class-level attribute is used.
    def self.default_url_options(*args)
      if defined?(Devise.parent_controller.constantize)
        Devise.parent_controller.constantize.try(:default_url_options) || {}
      else
        {}
      end
    end

    def respond
      if http_auth?
        http_auth
      elsif warden_options[:recall]
        recall
      else
        redirect
      end
    end

    def http_auth
      self.status = 401
      self.headers["WWW-Authenticate"] = %(Basic realm=#{Devise.http_authentication_realm.inspect}) if http_auth_header?
      self.content_type = request.format.to_s
      self.response_body = http_auth_body
    end

    def recall
      header_info = if relative_url_root?
        base_path = Pathname.new(relative_url_root)
        full_path = Pathname.new(attempted_path)

        { "SCRIPT_NAME" => relative_url_root,
          "PATH_INFO" => '/' + full_path.relative_path_from(base_path).to_s }
      else
        { "PATH_INFO" => attempted_path }
      end

      header_info.each do | var, value|
        if request.respond_to?(:set_header)
          request.set_header(var, value)
        else
          request.env[var]  = value
        end
      end

      flash.now[:alert] = i18n_message(:invalid) if is_flashing_format?
      self.response = recall_app(warden_options[:recall]).call(request.env).tap { |response|
        status = response[0].in?(300..399) ? Devise.responder.redirect_status : Devise.responder.error_status
        # Avoid warnings translating status to code using Rails if available (e.g. `unprocessable_entity` => `unprocessable_content`)
        response[0] = ActionDispatch::Response.try(:rack_status_code, status) || Rack::Utils.status_code(status)
      }
    end

    def redirect
      store_location!
      if is_flashing_format?
        if flash[:timedout] && flash[:alert]
          flash.keep(:timedout)
          flash.keep(:alert)
        else
          flash[:alert] = i18n_message
        end
      end
      redirect_to redirect_url
    end

  protected

    def i18n_options(options)
      options
    end

    def i18n_message(default = nil)
      message = warden_message || default || :unauthenticated

      if message.is_a?(Symbol)
        options = {}
        options[:resource_name] = scope
        options[:scope] = "devise.failure"
        options[:default] = [message]
        auth_keys = scope_class.authentication_keys
        human_keys = (auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys).map { |key|
          # TODO: Remove the fallback and just use `downcase_first` once we drop support for Rails 7.0.
          human_key = scope_class.human_attribute_name(key)
          human_key.respond_to?(:downcase_first) ? human_key.downcase_first : human_key[0].downcase + human_key[1..]
        }
        options[:authentication_keys] = human_keys.join(I18n.t(:"support.array.words_connector"))
        options = i18n_options(options)

        I18n.t(:"#{scope}.#{message}", **options).then { |msg|
          # Ensure that auth keys at the start of the translated string are properly cased.
          msg.start_with?(human_keys.first) ? msg.upcase_first : msg
        }
      else
        message.to_s
      end
    end

    def i18n_locale
      warden_options[:locale]
    end

    def redirect_url
      if warden_message == :timeout
        flash[:timedout] = true if is_flashing_format?

        path = if request.get?
          attempted_path
        else
          request.referrer
        end

        path || scope_url
      else
        scope_url
      end
    end

    def route(scope)
      :"new_#{scope}_session_url"
    end

    def scope_url
      opts  = {}

      # Initialize script_name with nil to prevent infinite loops in
      # authenticated mounted engines
      opts[:script_name] = nil

      route = route(scope)

      opts[:format] = request_format unless skip_format?

      router_name = Devise.mappings[scope].router_name || Devise.available_router_name
      context = send(router_name)

      if relative_url_root?
        opts[:script_name] = relative_url_root
      end

      if context.respond_to?(route)
        context.send(route, opts)
      elsif respond_to?(:root_url)
        root_url(opts)
      else
        "/"
      end
    end

    def skip_format?
      %w(html */* turbo_stream).include? request_format.to_s
    end

    # Choose whether we should respond in an HTTP authentication fashion,
    # including 401 and optional headers.
    #
    # This method allows the user to explicitly disable HTTP authentication
    # on AJAX requests in case they want to redirect on failures instead of
    # handling the errors on their own. This is useful in case your AJAX API
    # is the same as your public API and uses a format like JSON (so you
    # cannot mark JSON as a navigational format).
    def http_auth?
      if request.xhr?
        Devise.http_authenticatable_on_xhr
      else
        !(request_format && is_navigational_format?)
      end
    end

    # It doesn't make sense to send authenticate headers in AJAX requests
    # or if the user disabled them.
    def http_auth_header?
      scope_class.http_authenticatable && !request.xhr?
    end

    def http_auth_body
      return i18n_message unless request_format
      method = "to_#{request_format}"
      if method == "to_xml"
        { error: i18n_message }.to_xml(root: "errors")
      elsif {}.respond_to?(method)
        { error: i18n_message }.send(method)
      else
        i18n_message
      end
    end

    def recall_app(app)
      controller, action = app.split("#")
      controller_name  = ActiveSupport::Inflector.camelize(controller)
      controller_klass = ActiveSupport::Inflector.constantize("#{controller_name}Controller")
      controller_klass.action(action)
    end

    def warden
      request.respond_to?(:get_header) ? request.get_header("warden") : request.env["warden"]
    end

    def warden_options
      request.respond_to?(:get_header) ? request.get_header("warden.options") : request.env["warden.options"]
    end

    def warden_message
      @message ||= warden.message || warden_options[:message]
    end

    def scope
      @scope ||= warden_options[:scope] || Devise.default_scope
    end

    def scope_class
      @scope_class ||= Devise.mappings[scope].to
    end

    def attempted_path
      warden_options[:attempted_path]
    end

    # Stores requested URI to redirect the user after signing in. We can't use
    # the scoped session provided by warden here, since the user is not
    # authenticated yet, but we still need to store the URI based on scope, so
    # different scopes would never use the same URI to redirect.
    def store_location!
      store_location_for(scope, attempted_path) if request.get? && !http_auth?
    end

    def is_navigational_format?
      Devise.navigational_formats.include?(request_format)
    end

    # Check if flash messages should be emitted. Default is to do it on
    # navigational formats
    def is_flashing_format?
      request.respond_to?(:flash) && is_navigational_format?
    end

    def request_format
      @request_format ||= request.format.try(:ref)
    end

    def relative_url_root
      @relative_url_root ||= begin
        config = Rails.application.config

        config.try(:relative_url_root) || config.action_controller.try(:relative_url_root)
      end
    end

    def relative_url_root?
      relative_url_root.present?
    end

    ActiveSupport.run_load_hooks(:devise_failure_app, self)
  end
end


================================================
FILE: lib/devise/hooks/activatable.rb
================================================
# frozen_string_literal: true

# Deny user access whenever their account is not active yet.
# We need this as hook to validate the user activity on each request
# and in case the user is using other strategies beside Devise ones.
Warden::Manager.after_set_user do |record, warden, options|
  if record && record.respond_to?(:active_for_authentication?) && !record.active_for_authentication?
    scope = options[:scope]
    warden.logout(scope)
    throw :warden, scope: scope, message: record.inactive_message, locale: options.fetch(:locale, I18n.locale)
  end
end


================================================
FILE: lib/devise/hooks/csrf_cleaner.rb
================================================
# frozen_string_literal: true

Warden::Manager.after_authentication do |record, warden, options|
  clean_up_for_winning_strategy = !warden.winning_strategy.respond_to?(:clean_up_csrf?) ||
    warden.winning_strategy.clean_up_csrf?
  if Devise.clean_up_csrf_token_on_authentication && clean_up_for_winning_strategy
    if warden.request.respond_to?(:reset_csrf_token)
      # Rails 7.1+
      warden.request.reset_csrf_token
    else
      warden.request.session.try(:delete, :_csrf_token)
    end
  end
end


================================================
FILE: lib/devise/hooks/forgetable.rb
================================================
# frozen_string_literal: true

# Before logout hook to forget the user in the given scope, if it responds
# to forget_me! Also clear remember token to ensure the user won't be
# remembered again. Notice that we forget the user unless the record is not persisted.
# This avoids forgetting deleted users.
Warden::Manager.before_logout do |record, warden, options|
  if record.respond_to?(:forget_me!)
    Devise::Hooks::Proxy.new(warden).forget_me(record)
  end
end


================================================
FILE: lib/devise/hooks/lockable.rb
================================================
# frozen_string_literal: true

# After each sign in, if resource responds to failed_attempts, sets it to 0
# This is only triggered when the user is explicitly set (with set_user)
Warden::Manager.after_set_user except: :fetch do |record, warden, options|
  if record.respond_to?(:reset_failed_attempts!) && warden.authenticated?(options[:scope])
    record.reset_failed_attempts!
  end
end


================================================
FILE: lib/devise/hooks/proxy.rb
================================================
# frozen_string_literal: true

module Devise
  module Hooks
    # A small warden proxy so we can remember, forget and
    # sign out users from hooks.
    class Proxy #:nodoc:
      include Devise::Controllers::Rememberable
      include Devise::Controllers::SignInOut

      attr_reader :warden
      delegate :cookies, :request, to: :warden

      def initialize(warden)
        @warden = warden
      end

      def session
        warden.request.session
      end
    end
  end
end


================================================
FILE: lib/devise/hooks/rememberable.rb
================================================
# frozen_string_literal: true

Warden::Manager.after_set_user except: :fetch do |record, warden, options|
  scope = options[:scope]
  if record.respond_to?(:remember_me) && options[:store] != false &&
     record.remember_me && warden.authenticated?(scope)
    Devise::Hooks::Proxy.new(warden).remember_me(record)
  end
end


================================================
FILE: lib/devise/hooks/timeoutable.rb
================================================
# frozen_string_literal: true

# Each time a record is set we check whether its session has already timed out
# or not, based on last request time. If so, the record is logged out and
# redirected to the sign in page. Also, each time the request comes and the
# record is set, we set the last request time inside its scoped session to
# verify timeout in the following request.
Warden::Manager.after_set_user do |record, warden, options|
  scope = options[:scope]
  env   = warden.request.env

  if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) &&
     options[:store] != false && !env['devise.skip_timeoutable']
    last_request_at = warden.session(scope)['last_request_at']

    if last_request_at.is_a? Integer
      last_request_at = Time.at(last_request_at).utc
    elsif last_request_at.is_a? String
      last_request_at = Time.parse(last_request_at)
    end

    proxy = Devise::Hooks::Proxy.new(warden)

    if !env['devise.skip_timeout'] &&
        record.timedout?(last_request_at) &&
        !proxy.remember_me_is_active?(record)
      Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope)
      throw :warden, scope: scope, message: :timeout, locale: options.fetch(:locale, I18n.locale)
    end

    unless env['devise.skip_trackable']
      warden.session(scope)['last_request_at'] = Time.now.utc.to_i
    end
  end
end


================================================
FILE: lib/devise/hooks/trackable.rb
================================================
# frozen_string_literal: true

# After each sign in, update sign in time, sign in count and sign in IP.
# This is only triggered when the user is explicitly set (with set_user)
# and on authentication. Retrieving the user from session (:fetch) does
# not trigger it.
Warden::Manager.after_set_user except: :fetch do |record, warden, options|
  if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope]) && !warden.request.env['devise.skip_trackable']
    record.update_tracked_fields!(warden.request)
  end
end


================================================
FILE: lib/devise/mailers/helpers.rb
================================================
# frozen_string_literal: true

module Devise
  module Mailers
    module Helpers
      extend ActiveSupport::Concern

      included do
        include Devise::Controllers::ScopedViews
      end

      protected

      attr_reader :scope_name, :resource

      # Configure default email options
      def devise_mail(record, action, opts = {}, &block)
        initialize_from_record(record)
        mail headers_for(action, opts), &block
      end

      def initialize_from_record(record)
        @scope_name = Devise::Mapping.find_scope!(record)
        @resource   = instance_variable_set("@#{devise_mapping.name}", record)
      end

      def devise_mapping
        @devise_mapping ||= Devise.mappings[scope_name]
      end

      def headers_for(action, opts)
        headers = {
          subject: subject_for(action),
          to: resource.email,
          from: mailer_sender(devise_mapping),
          reply_to: mailer_sender(devise_mapping),
          template_path: template_paths,
          template_name: action
        }
        # Give priority to the mailer's default if they exists.
        headers.delete(:from) if default_params[:from]
        headers.delete(:reply_to) if default_params[:reply_to]

        headers.merge!(opts)

        @email = headers[:to]
        headers
      end

      def mailer_sender(mapping)
        if Devise.mailer_sender.is_a?(Proc)
          Devise.mailer_sender.call(mapping.name)
        else
          Devise.mailer_sender
        end
      end

      def template_paths
        template_path = _prefixes.dup
        template_path.unshift "#{@devise_mapping.scoped_path}/mailer" if self.class.scoped_views?
        template_path
      end

      # Set up a subject doing an I18n lookup. At first, it attempts to set a subject
      # based on the current mapping:
      #
      #   en:
      #     devise:
      #       mailer:
      #         confirmation_instructions:
      #           user_subject: '...'
      #
      # If one does not exist, it fallbacks to ActionMailer default:
      #
      #   en:
      #     devise:
      #       mailer:
      #         confirmation_instructions:
      #           subject: '...'
      #
      def subject_for(key)
        I18n.t(:"#{devise_mapping.name}_subject", scope: [:devise, :mailer, key],
          default: [:subject, key.to_s.humanize])
      end
    end
  end
end


================================================
FILE: lib/devise/mapping.rb
================================================
# frozen_string_literal: true

module Devise
  # Responsible for handling devise mappings and routes configuration. Each
  # resource configured by devise_for in routes is actually creating a mapping
  # object. You can refer to devise_for in routes for usage options.
  #
  # The required value in devise_for is actually not used internally, but it's
  # inflected to find all other values.
  #
  #   map.devise_for :users
  #   mapping = Devise.mappings[:user]
  #
  #   mapping.name #=> :user
  #   # is the scope used in controllers and warden, given in the route as :singular.
  #
  #   mapping.as   #=> "users"
  #   # how the mapping should be search in the path, given in the route as :as.
  #
  #   mapping.to   #=> User
  #   # is the class to be loaded from routes, given in the route as :class_name.
  #
  #   mapping.modules  #=> [:authenticatable]
  #   # is the modules included in the class
  #
  class Mapping #:nodoc:
    attr_reader :singular, :scoped_path, :path, :controllers, :path_names,
                :class_name, :sign_out_via, :format, :used_routes, :used_helpers,
                :failure_app, :router_name

    alias :name :singular

    # Receives an object and finds a scope for it. If a scope cannot be found,
    # raises an error. If a symbol is given, it's considered to be the scope.
    def self.find_scope!(obj)
      obj = obj.devise_scope if obj.respond_to?(:devise_scope)
      case obj
      when String, Symbol
        return obj.to_sym
      when Class
        Devise.mappings.each_value { |m| return m.name if obj <= m.to }
      else
        Devise.mappings.each_value { |m| return m.name if obj.is_a?(m.to) }
      end

      raise "Could not find a valid mapping for #{obj.inspect}"
    end

    def self.find_by_path!(path, path_type = :fullpath)
      Devise.mappings.each_value { |m| return m if path.include?(m.send(path_type)) }
      raise "Could not find a valid mapping for path #{path.inspect}"
    end

    def initialize(name, options) #:nodoc:
      @scoped_path = options[:as] ? "#{options[:as]}/#{name}" : name.to_s
      @singular = (options[:singular] || @scoped_path.tr('/', '_').singularize).to_sym

      @class_name = (options[:class_name] || name.to_s.classify).to_s
      @klass = Devise.ref(@class_name)

      @path = (options[:path] || name).to_s
      @path_prefix = options[:path_prefix]

      @sign_out_via = options[:sign_out_via] || Devise.sign_out_via
      @format = options[:format]

      @router_name = options[:router_name]

      default_failure_app(options)
      default_controllers(options)
      default_path_names(options)
      default_used_route(options)
      default_used_helpers(options)
    end

    # Return modules for the mapping.
    def modules
      @modules ||= to.respond_to?(:devise_modules) ? to.devise_modules : []
    end

    # Gives the class the mapping points to.
    def to
      @klass.get
    end

    def strategies
      @strategies ||= STRATEGIES.values_at(*self.modules).compact.uniq.reverse
    end

    def no_input_strategies
      self.strategies & Devise::NO_INPUT
    end

    def routes
      @routes ||= ROUTES.values_at(*self.modules).compact.uniq
    end

    def authenticatable?
      @authenticatable ||= self.modules.any? { |m| m.to_s =~ /authenticatable/ }
    end

    def fullpath
      "/#{@path_prefix}/#{@path}".squeeze("/")
    end

    # Create magic predicates for verifying what module is activated by this map.
    # Example:
    #
    #   def confirmable?
    #     self.modules.include?(:confirmable)
    #   end
    #
    def self.add_module(m)
      class_eval <<-METHOD, __FILE__, __LINE__ + 1
        def #{m}?
          self.modules.include?(:#{m})
        end
      METHOD
    end

    private

    def default_failure_app(options)
      @failure_app = options[:failure_app] || Devise::FailureApp
      if @failure_app.is_a?(String)
        ref = Devise.ref(@failure_app)
        @failure_app = lambda { |env| ref.get.call(env) }
      end
    end

    def default_controllers(options)
      mod = options[:module] || "devise"
      @controllers = Hash.new { |h,k| h[k] = "#{mod}/#{k}" }
      @controllers.merge!(options[:controllers]) if options[:controllers]
      @controllers.each { |k,v| @controllers[k] = v.to_s }
    end

    def default_path_names(options)
      @path_names = Hash.new { |h,k| h[k] = k.to_s }
      @path_names[:registration] = ""
      @path_names.merge!(options[:path_names]) if options[:path_names]
    end

    def default_constraints(options)
      @constraints = Hash.new
      @constraints.merge!(options[:constraints]) if options[:constraints]
    end

    def default_defaults(options)
      @defaults = Hash.new
      @defaults.merge!(options[:defaults]) if options[:defaults]
    end

    def default_used_route(options)
      singularizer = lambda { |s| s.to_s.singularize.to_sym }

      if options.has_key?(:only)
        @used_routes = self.routes & Array(options[:only]).map(&singularizer)
      elsif options[:skip] == :all
        @used_routes = []
      else
        @used_routes = self.routes - Array(options[:skip]).map(&singularizer)
      end
    end

    def default_used_helpers(options)
      singularizer = lambda { |s| s.to_s.singularize.to_sym }

      if options[:skip_helpers] == true
        @used_helpers = @used_routes
      elsif skip = options[:skip_helpers]
        @used_helpers = self.routes - Array(skip).map(&singularizer)
      else
        @used_helpers = self.routes
      end
    end
  end
end


================================================
FILE: lib/devise/models/authenticatable.rb
================================================
# frozen_string_literal: true

require 'devise/hooks/activatable'
require 'devise/hooks/csrf_cleaner'

module Devise
  module Models
    # Authenticatable module. Holds common settings for authentication.
    #
    # == Options
    #
    # Authenticatable adds the following options to +devise+:
    #
    #   * +authentication_keys+: parameters used for authentication. By default [:email].
    #
    #   * +http_authentication_key+: map the username passed via HTTP Auth to this parameter. Defaults to
    #     the first element in +authentication_keys+.
    #
    #   * +request_keys+: parameters from the request object used for authentication.
    #     By specifying a symbol (which should be a request method), it will automatically be
    #     passed to find_for_authentication method and considered in your model lookup.
    #
    #     For instance, if you set :request_keys to [:subdomain], :subdomain will be considered
    #     as key on authentication. This can also be a hash where the value is a boolean specifying
    #     if the value is required or not.
    #
    #   * +http_authenticatable+: if this model allows http authentication. By default false.
    #     It also accepts an array specifying the strategies that should allow http.
    #
    #   * +params_authenticatable+: if this model allows authentication through request params. By default true.
    #     It also accepts an array specifying the strategies that should allow params authentication.
    #
    #   * +skip_session_storage+: By default Devise will store the user in session.
    #     By default is set to skip_session_storage: [:http_auth].
    #
    # == active_for_authentication?
    #
    # After authenticating a user and in each request, Devise checks if your model is active by
    # calling model.active_for_authentication?. This method is overwritten by other devise modules. For instance,
    # :confirmable overwrites .active_for_authentication? to only return true if your model was confirmed.
    #
    # You can overwrite this method yourself, but if you do, don't forget to call super:
    #
    #   def active_for_authentication?
    #     super && special_condition_is_valid?
    #   end
    #
    # Whenever active_for_authentication? returns false, Devise asks the reason why your model is inactive using
    # the inactive_message method. You can overwrite it as well:
    #
    #   def inactive_message
    #     special_condition_is_valid? ? super : :special_condition_is_not_valid
    #   end
    #
    module Authenticatable
      extend ActiveSupport::Concern

      UNSAFE_ATTRIBUTES_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at,
        :remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip,
        :last_sign_in_ip, :password_salt, :confirmation_token, :confirmed_at, :confirmation_sent_at,
        :remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at]

      included do
        class_attribute :devise_modules, instance_writer: false
        self.devise_modules ||= []

        before_validation :downcase_keys
        before_validation :strip_whitespace
      end

      def self.required_fields(klass)
        []
      end

      # Check if the current object is valid for authentication. This method and
      # find_for_authentication are the methods used in a Warden::Strategy to check
      # if a model should be signed in or not.
      #
      # However, you should not overwrite this method, you should overwrite active_for_authentication?
      # and inactive_message instead.
      def valid_for_authentication?
        block_given? ? yield : true
      end

      def unauthenticated_message
        :invalid
      end

      def active_for_authentication?
        true
      end

      def inactive_message
        :inactive
      end

      def authenticatable_salt
      end

      # Redefine serializable_hash in models for more secure defaults.
      # By default, it removes from the serializable model all attributes that
      # are *not* accessible. You can remove this default by using :force_except
      # and passing a new list of attributes you want to exempt. All attributes
      # given to :except will simply add names to exempt to Devise internal list.
      def serializable_hash(options = nil)
        options = options.try(:dup) || {}
        options[:except] = Array(options[:except]).dup

        if options[:force_except]
          options[:except].concat Array(options[:force_except])
        else
          options[:except].concat UNSAFE_ATTRIBUTES_FOR_SERIALIZATION
        end

        super(options)
      end

      # Redefine inspect using serializable_hash, to ensure we don't accidentally
      # leak passwords into exceptions.
      def inspect
        inspection = serializable_hash.collect do |k,v|
          "#{k}: #{respond_to?(:attribute_for_inspect) ? attribute_for_inspect(k) : v.inspect}"
        end
        "#<#{self.class} #{inspection.join(", ")}>"
      end

      protected

      def devise_mailer
        Devise.mailer
      end

      # This is an internal method called every time Devise needs
      # to send a notification/mail. This can be overridden if you
      # need to customize the e-mail delivery logic. For instance,
      # if you are using a queue to deliver e-mails (active job, delayed
      # job, sidekiq, resque, etc), you must add the delivery to the queue
      # just after the transaction was committed. To achieve this,
      # you can override send_devise_notification to store the
      # deliveries until the after_commit callback is triggered.
      #
      # The following example uses Active Job's `deliver_later` :
      #
      #     class User
      #       devise :database_authenticatable, :confirmable
      #
      #       after_commit :send_pending_devise_notifications
      #
      #       protected
      #
      #       def send_devise_notification(notification, *args)
      #         # If the record is new or changed then delay the
      #         # delivery until the after_commit callback otherwise
      #         # send now because after_commit will not be called.
      #         # For Rails < 6 use `changed?` instead of `saved_changes?`.
      #         if new_record? || saved_changes?
      #           pending_devise_notifications << [notification, args]
      #         else
      #           render_and_send_devise_message(notification, *args)
      #         end
      #       end
      #
      #       private
      #
      #       def send_pending_devise_notifications
      #         pending_devise_notifications.each do |notification, args|
      #           render_and_send_devise_message(notification, *args)
      #         end
      #
      #         # Empty the pending notifications array because the
      #         # after_commit hook can be called multiple times which
      #         # could cause multiple emails to be sent.
      #         pending_devise_notifications.clear
      #       end
      #
      #       def pending_devise_notifications
      #         @pending_devise_notifications ||= []
      #       end
      #
      #       def render_and_send_devise_message(notification, *args)
      #         message = devise_mailer.send(notification, self, *args)
      #
      #         # Deliver later with Active Job's `deliver_later`
      #         if message.respond_to?(:deliver_later)
      #           message.deliver_later
      #         else
      #           message.deliver_now
      #         end
      #       end
      #
      #     end
      #
      def send_devise_notification(notification, *args)
        message = devise_mailer.send(notification, self, *args)
        message.deliver_now
      end

      def downcase_keys
        self.class.case_insensitive_keys.each { |k| apply_to_attribute_or_variable(k, :downcase) }
      end

      def strip_whitespace
        self.class.strip_whitespace_keys.each { |k| apply_to_attribute_or_variable(k, :strip) }
      end

      def apply_to_attribute_or_variable(attr, method)
        if self[attr]
          self[attr] = self[attr].try(method)

        # Use respond_to? here to avoid a regression where globally
        # configured strip_whitespace_keys or case_insensitive_keys were
        # attempting to strip or downcase when a model didn't have the
        # globally configured key.
        elsif respond_to?(attr) && respond_to?("#{attr}=")
          new_value = send(attr).try(method)
          send("#{attr}=", new_value)
        end
      end

      module ClassMethods
        Devise::Models.config(self, :authentication_keys, :request_keys, :strip_whitespace_keys,
          :case_insensitive_keys, :http_authenticatable, :params_authenticatable, :skip_session_storage,
          :http_authentication_key)

        def serialize_into_session(record)
          [record.to_key, record.authenticatable_salt]
        end

        def serialize_from_session(key, salt)
          record = to_adapter.get(key)
          record if record && record.authenticatable_salt == salt
        end

        def params_authenticatable?(strategy)
          params_authenticatable.is_a?(Array) ?
            params_authenticatable.include?(strategy) : params_authenticatable
        end

        def http_authenticatable?(strategy)
          http_authenticatable.is_a?(Array) ?
            http_authenticatable.include?(strategy) : http_authenticatable
        end

        # Find first record based on conditions given (ie by the sign in form).
        # This method is always called during an authentication process but
        # it may be wrapped as well. For instance, database authenticatable
        # provides a `find_for_database_authentication` that wraps a call to
        # this method. This allows you to customize both database authenticatable
        # or the whole authenticate stack by customize `find_for_authentication.`
        #
        # Overwrite to add customized conditions, create a join, or maybe use a
        # namedscope to filter records while authenticating.
        # Example:
        #
        #   def self.find_for_authentication(tainted_conditions)
        #     find_first_by_auth_conditions(tainted_conditions, active: true)
        #   end
        #
        # Finally, notice that Devise also queries for users in other scenarios
        # besides authentication, for example when retrieving a user to send
        # an e-mail for password reset. In such cases, find_for_authentication
        # is not called.
        def find_for_authentication(tainted_conditions)
          find_first_by_auth_conditions(tainted_conditions)
        end

        def find_first_by_auth_conditions(tainted_conditions, opts = {})
          to_adapter.find_first(devise_parameter_filter.filter(tainted_conditions).merge(opts))
        end

        # Find or initialize a record setting an error if it can't be found.
        def find_or_initialize_with_error_by(attribute, value, error = :invalid) #:nodoc:
          find_or_initialize_with_errors([attribute], { attribute => value }, error)
        end

        # Find or initialize a record with group of attributes based on a list of required attributes.
        def find_or_initialize_with_errors(required_attributes, attributes, error = :invalid) #:nodoc:
          attributes.try(:permit!)
          attributes = attributes.to_h.with_indifferent_access
                                 .slice(*required_attributes)
                                 .delete_if { |key, value| value.blank? }

          if attributes.size == required_attributes.size
            record = find_first_by_auth_conditions(attributes) and return record
          end

          new(devise_parameter_filter.filter(attributes)).tap do |record|
            required_attributes.each do |key|
              record.errors.add(key, attributes[key].blank? ? :blank : error)
            end
          end
        end

        protected

        def devise_parameter_filter
          @devise_parameter_filter ||= Devise::ParameterFilter.new(case_insensitive_keys, strip_whitespace_keys)
        end
      end
    end
  end
end


================================================
FILE: lib/devise/models/confirmable.rb
================================================
# frozen_string_literal: true

module Devise
  module Models
    # Confirmable is responsible to verify if an account is already confirmed to
    # sign in, and to send emails with confirmation instructions.
    # Confirmation instructions are sent to the user email after creating a
    # record and when manually requested by a new confirmation instruction request.
    #
    # Confirmable tracks the following columns:
    #
    # * confirmation_token   - A unique random token
    # * confirmed_at         - A timestamp when the user clicked the confirmation link
    # * confirmation_sent_at - A timestamp when the confirmation_token was generated (not sent)
    # * unconfirmed_email    - An email address copied from the email attr. After confirmation
    #                          this value is copied to the email attr then cleared
    #
    # == Options
    #
    # Confirmable adds the following options to +devise+:
    #
    #   * +allow_unconfirmed_access_for+: the time you want to allow the user to access their account
    #     before confirming it. After this period, the user access is denied. You can
    #     use this to let your user access some features of your application without
    #     confirming the account, but blocking it after a certain period (ie 7 days).
    #     By default allow_unconfirmed_access_for is zero, it means users always have to confirm to sign in.
    #   * +reconfirmable+: requires any email changes to be confirmed (exactly the same way as
    #     initial account confirmation) to be applied. Requires additional unconfirmed_email
    #     db field to be set up (t.reconfirmable in 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.
    #   * +confirm_within+: the time before a sent confirmation token becomes invalid.
    #     You can use this to force the user to confirm within a set period of time.
    #     Confirmable will not generate a new token if a repeat confirmation is requested
    #     during this time frame, unless the user's email changed too.
    #
    # == Examples
    #
    #   User.find(1).confirm       # returns true unless it's already confirmed
    #   User.find(1).confirmed?    # true/false
    #   User.find(1).send_confirmation_instructions # manually send instructions
    #
    module Confirmable
      extend ActiveSupport::Concern

      included do
        before_create :generate_confirmation_token, if: :confirmation_required?
        after_create :skip_reconfirmation_in_callback!, if: :send_confirmation_notification?
        if Devise::Orm.active_record?(self) # ActiveRecord
          after_commit :send_on_create_confirmation_instructions, on: :create, if: :send_confirmation_notification?
          after_commit :send_reconfirmation_instructions, on: :update, if: :reconfirmation_required?
        else # Mongoid
          after_create :send_on_create_confirmation_instructions, if: :send_confirmation_notification?
          after_update :send_reconfirmation_instructions, if: :reconfirmation_required?
        end
        before_update :postpone_email_change_until_confirmation_and_regenerate_confirmation_token, if: :postpone_email_change?
      end

      def initialize(*args, &block)
        @bypass_confirmation_postpone = false
        @skip_reconfirmation_in_callback = false
        @reconfirmation_required = false
        @skip_confirmation_notification = false
        @raw_confirmation_token = nil
        super
      end

      def self.required_fields(klass)
        required_methods = [:confirmation_token, :confirmed_at, :confirmation_sent_at]
        required_methods << :unconfirmed_email if klass.reconfirmable
        required_methods
      end

      # Confirm a user by setting it's confirmed_at to actual time. If the user
      # is already confirmed, add an error to email field. If the user is invalid
      # add errors
      def confirm(args = {})
        pending_any_confirmation do
          if confirmation_period_expired?
            self.errors.add(:email, :confirmation_period_expired,
              period: Devise::TimeInflector.time_ago_in_words(self.class.confirm_within.ago))
            return false
          end

          self.confirmed_at = Time.now.utc

          saved = if pending_reconfirmation?
            skip_reconfirmation!
            self.email = unconfirmed_email
            self.unconfirmed_email = nil

            # We need to validate in such cases to enforce e-mail uniqueness
            save(validate: true)
          else
            save(validate: args[:ensure_valid] == true)
          end

          after_confirmation if saved
          saved
        end
      end

      # Verifies whether a user is confirmed or not
      def confirmed?
        !!confirmed_at
      end

      def pending_reconfirmation?
        self.class.reconfirmable && unconfirmed_email.present?
      end

      # Send confirmation instructions by email
      def send_confirmation_instructions
        unless @raw_confirmation_token
          generate_confirmation_token!
        end

        opts = pending_reconfirmation? ? { to: unconfirmed_email } : { }
        send_devise_notification(:confirmation_instructions, @raw_confirmation_token, opts)
      end

      def send_reconfirmation_instructions
        @reconfirmation_required = false

        unless @skip_confirmation_notification
          send_confirmation_instructions
        end
      end

      # Resend confirmation token.
      # Regenerates the token if the period is expired.
      def resend_confirmation_instructions
        pending_any_confirmation do
          send_confirmation_instructions
        end
      end

      # Overwrites active_for_authentication? for confirmation
      # by verifying whether a user is active to sign in or not. If the user
      # is already confirmed, it should never be blocked. Otherwise we need to
      # calculate if the confirm time has not expired for this user.
      def active_for_authentication?
        super && (!confirmation_required? || confirmed? || confirmation_period_valid?)
      end

      # The message to be shown if the account is inactive.
      def inactive_message
        !confirmed? ? :unconfirmed : super
      end

      # If you don't want confirmation to be sent on create, neither a code
      # to be generated, call skip_confirmation!
      def skip_confirmation!
        self.confirmed_at = Time.now.utc
      end

      # Skips sending the confirmation/reconfirmation notification email after_create/after_update. Unlike
      # #skip_confirmation!, record still requires confirmation.
      def skip_confirmation_notification!
        @skip_confirmation_notification = true
      end

      # If you don't want reconfirmation to be sent, neither a code
      # to be generated, call skip_reconfirmation!
      def skip_reconfirmation!
        @bypass_confirmation_postpone = true
      end

      protected

        # To not require reconfirmation after creating with #save called in a
        # callback call skip_create_confirmation!
        def skip_reconfirmation_in_callback!
          @skip_reconfirmation_in_callback = true
        end

        # A callback method used to deliver confirmation
        # instructions on creation. This can be overridden
        # in models to map to a nice sign up e-mail.
        def send_on_create_confirmation_instructions
          send_confirmation_instructions
        end

        # Callback to overwrite if confirmation is required or not.
        def confirmation_required?
          !confirmed?
        end

        # Checks if the confirmation for the user is within the limit time.
        # We do this by calculating if the difference between today and the
        # confirmation sent date does not exceed the confirm in time configured.
        # allow_unconfirmed_access_for is a model configuration, must always be an integer value.
        #
        # Example:
        #
        #   # allow_unconfirmed_access_for = 1.day and confirmation_sent_at = today
        #   confirmation_period_valid?   # returns true
        #
        #   # allow_unconfirmed_access_for = 5.days and confirmation_sent_at = 4.days.ago
        #   confirmation_period_valid?   # returns true
        #
        #   # allow_unconfirmed_access_for = 5.days and confirmation_sent_at = 5.days.ago
        #   confirmation_period_valid?   # returns false
        #
        #   # allow_unconfirmed_access_for = 0.days
        #   confirmation_period_valid?   # will always return false
        #
        #   # allow_unconfirmed_access_for = nil
        #   confirmation_period_valid?   # will always return true
        #
        def confirmation_period_valid?
          return true if self.class.allow_unconfirmed_access_for.nil?
          return false if self.class.allow_unconfirmed_access_for == 0.days

          confirmation_sent_at && confirmation_sent_at.utc >= self.class.allow_unconfirmed_access_for.ago
        end

        # Checks if the user confirmation happens before the token becomes invalid
        # Examples:
        #
        #   # confirm_within = 3.days and confirmation_sent_at = 2.days.ago
        #   confirmation_period_expired?  # returns false
        #
        #   # confirm_within = 3.days and confirmation_sent_at = 4.days.ago
        #   confirmation_period_expired?  # returns true
        #
        #   # confirm_within = nil
        #   confirmation_period_expired?  # will always return false
        #
        def confirmation_period_expired?
          self.class.confirm_within && self.confirmation_sent_at && (Time.now.utc > self.confirmation_sent_at.utc + self.class.confirm_within)
        end

        # Checks whether the record requires any confirmation.
        def pending_any_confirmation
          if (!confirmed? || pending_reconfirmation?)
            yield
          else
            self.errors.add(:email, :already_confirmed)
            false
          end
        end

        # Generates a new random token for confirmation, and stores
        # the time this token is being generated in confirmation_sent_at
        def generate_confirmation_token
          if self.confirmation_token && !confirmation_period_expired?
            @raw_confirmation_token = self.confirmation_token
          else
            self.confirmation_token = @raw_confirmation_token = Devise.friendly_token
            self.confirmation_sent_at = Time.now.utc
          end
        end

        def generate_confirmation_token!
          generate_confirmation_token && save(validate: false)
        end

        def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
          @reconfirmation_required = true
          # Force unconfirmed_email to be updated, even if the value hasn't changed, to prevent a
          # race condition which could allow an attacker to confirm an email they don't own. See #5783.
          devise_unconfirmed_email_will_change!
          self.unconfirmed_email = self.email
          self.email = self.devise_email_in_database
          self.confirmation_token = nil
          generate_confirmation_token
        end

        def postpone_email_change?
          postpone = self.class.reconfirmable &&
            devise_will_save_change_to_email? &&
            !@bypass_confirmation_postpone &&
            self.email.present? &&
            (!@skip_reconfirmation_in_callback || !self.devise_email_in_database.nil?)
          @bypass_confirmation_postpone = false
          postpone
        end

        def reconfirmation_required?
          self.class.reconfirmable && @reconfirmation_required && (self.email.present? || self.unconfirmed_email.present?)
        end

        def send_confirmation_notification?
          confirmation_required? && !@skip_confirmation_notification && self.email.present?
        end

        # With reconfirmable, notify the original email when the user first
        # requests the email change, instead of when the change is confirmed.
        def send_email_changed_notification?
          if self.class.reconfirmable
            self.class.send_email_changed_notification && reconfirmation_required?
          else
            super
          end
        end

        # A callback initiated after successfully confirming. This can be
        # used to insert your own logic that is only run after the user successfully
        # confirms.
        #
        # Example:
        #
        #   def after_confirmation
        #     self.update_attribute(:invite_code, nil)
        #   end
        #
        def after_confirmation
        end

      module ClassMethods
        # Attempt to find a user by its email. If a record is found, send new
        # confirmation instructions to it. If not, try searching for a user by unconfirmed_email
        # field. If no user is found, returns a new user with an email not found error.
        # Options must contain the user email
        def send_confirmation_instructions(attributes = {})
          confirmable = find_by_unconfirmed_email_with_errors(attributes) if reconfirmable
          unless confirmable.try(:persisted?)
            confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
          end
          confirmable.resend_confirmation_instructions if confirmable.persisted?
          confirmable
        end

        # Find a user by its confirmation token and try to confirm it.
        # If no user is found, returns a new user with an error.
        # If the user is already confirmed, create an error for the user
        # Options must have the confirmation_token
        def confirm_by_token(confirmation_token)
          # When the `confirmation_token` parameter is blank, if there are any users with a blank
          # `confirmation_token` in the database, the first one would be confirmed here.
          # The error is being manually added here to ensure no users are confirmed by mistake.
          # This was done in the model for convenience, since validation errors are automatically
          # displayed in the view.
          if confirmation_token.blank?
            confirmable = new
            confirmable.errors.add(:confirmation_token, :blank)
            return confirmable
          end

          confirmable = find_first_by_auth_conditions(confirmation_token: confirmation_token)

          unless confirmable
            confirmation_digest = Devise.token_generator.digest(self, :confirmation_token, confirmation_token)
            confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_digest)
          end

          # TODO: replace above lines with
          # confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_token)
          # after enough time has passed that Devise clients do not use digested tokens

          confirmable.confirm if confirmable.persisted?
          confirmable
        end

        # Find a record for confirmation by unconfirmed email field
        def find_by_unconfirmed_email_with_errors(attributes = {})
          attributes = attributes.slice(*confirmation_keys).permit!.to_h if attributes.respond_to? :permit
          unconfirmed_required_attributes = confirmation_keys.map { |k| k == :email ? :unconfirmed_email : k }
          unconfirmed_attributes = attributes.symbolize_keys
          unconfirmed_attributes[:unconfirmed_email] = unconfirmed_attributes.delete(:email)
          find_or_initialize_with_errors(unconfirmed_required_attributes, unconfirmed_attributes, :not_found)
        end

        Devise::Models.config(self, :allow_unconfirmed_access_for, :confirmation_keys, :reconfirmable, :confirm_within)
      end
    end
  end
end


================================================
FILE: lib/devise/models/database_authenticatable.rb
================================================
# frozen_string_literal: true

require 'devise/strategies/database_authenticatable'

module Devise
  module Models
    # Authenticatable Module, responsible for hashing the password and
    # validating the authenticity of a user while signing in.
    #
    # This module defines a `password=` method. This method will hash the argument
    # and store it in the `encrypted_password` column, bypassing any pre-existing
    # `password` column if it exists.
    #
    # == Options
    #
    # DatabaseAuthenticatable adds the following options to +devise+:
    #
    #   * +pepper+: a random string used to provide a more secure hash. Use
    #     `rails secret` to generate new keys.
    #
    #   * +stretches+: the cost given to bcrypt.
    #
    #   * +send_email_changed_notification+: notify original email when it changes.
    #
    #   * +send_password_change_notification+: notify email when password changes.
    #
    # == Examples
    #
    #    User.find(1).valid_password?('password123')         # returns true/false
    #
    module DatabaseAuthenticatable
      extend ActiveSupport::Concern

      included do
        after_update :send_email_changed_notification, if: :send_email_changed_notification?
        after_update :send_password_change_notification, if: :send_password_change_notification?

        attr_reader :password, :current_password
        attr_accessor :password_confirmation
      end

      def initialize(*args, &block)
        @skip_email_changed_notification = false
        @skip_password_change_notification = false
        super
      end

      # Skips sending the email changed notification after_update
      def skip_email_changed_notification!
        @skip_email_changed_notification = true
      end

      # Skips sending the password change notification after_update
      def skip_password_change_notification!
        @skip_password_change_notification = true
      end

      def self.required_fields(klass)
        [:encrypted_password] + klass.authentication_keys
      end

      # Generates a hashed password based on the given value.
      # For legacy reasons, we use `encrypted_password` to store
      # the hashed password.
      def password=(new_password)
        @password = new_password
        self.encrypted_password = password_digest(@password) if @password.present?
      end

      # Verifies whether a password (ie from sign in) is the user password.
      def valid_password?(password)
        Devise::Encryptor.compare(self.class, encrypted_password, password)
      end

      # Set password and password confirmation to nil
      def clean_up_passwords
        self.password = self.password_confirmation = nil
      end

      # Update record attributes when :current_password matches, otherwise
      # returns error on :current_password.
      #
      # This method also rejects the password field if it is blank (allowing
      # users to change relevant information like the e-mail without changing
      # their password). In case the password field is rejected, the confirmation
      # is also rejected as long as it is also blank.
      def update_with_password(params)
        current_password = params.delete(:current_password)

        if params[:password].blank?
          params.delete(:password)
          params.delete(:password_confirmation) if params[:password_confirmation].blank?
        end

        result = if valid_password?(current_password)
          update(params)
        else
          assign_attributes(params)
          valid?
          errors.add(:current_password, current_password.blank? ? :blank : :invalid)
          false
        end

        clean_up_passwords
        result
      end

      # Updates record attributes without asking for the current password.
      # Never allows a change to the current password. If you are using this
      # method, you should probably override this method to protect other
      # attributes you would not like to be updated without a password.
      #
      # Example:
      #
      #   def update_without_password(params)
      #     params.delete(:email)
      #     super(params)
      #   end
      #
      def update_without_password(params)
        params.delete(:password)
        params.delete(:password_confirmation)

        result = update(params)
        clean_up_passwords
        result
      end

      # Destroy record when :current_password matches, otherwise returns
      # error on :current_password. It also automatically rejects
      # :current_password if it is blank.
      def destroy_with_password(current_password)
        result = if valid_password?(current_password)
          destroy
        else
          valid?
          errors.add(:current_password, current_password.blank? ? :blank : :invalid)
          false
        end

        result
      end

      # A callback initiated after successfully authenticating. This can be
      # used to insert your own logic that is only run after the user successfully
      # authenticates.
      #
      # Example:
      #
      #   def after_database_authentication
      #     self.update_attribute(:invite_code, nil)
      #   end
      #
      def after_database_authentication
      end

      # A reliable way to expose the salt regardless of the implementation.
      def authenticatable_salt
        encrypted_password[0,29] if encrypted_password
      end

      # Send notification to user when email changes.
      def send_email_changed_notification
        send_devise_notification(:email_changed, to: devise_email_before_last_save)
      end

      # Send notification to user when password changes.
      def send_password_change_notification
        send_devise_notification(:password_change)
      end

    protected

      # Hashes the password using bcrypt. Custom hash functions should override
      # this method to apply their own algorithm.
      #
      # See https://github.com/heartcombo/devise-encryptable for examples
      # of other hashing engines.
      def password_digest(password)
        Devise::Encryptor.digest(self.class, password)
      end

      def send_email_changed_notification?
        self.class.send_email_changed_notification && devise_saved_change_to_email? && !@skip_email_changed_notification
      end

      def send_password_change_notification?
        self.class.send_password_change_notification && devise_saved_change_to_encrypted_password? && !@skip_password_change_notification
      end

      module ClassMethods
        Devise::Models.config(self, :pepper, :stretches, :send_email_changed_notification, :send_password_change_notification)

        # We assume this method already gets the sanitized values from the
        # DatabaseAuthenticatable strategy. If you are using this method on
        # your own, be sure to sanitize the conditions hash to only include
        # the proper fields.
        def find_for_database_authentication(conditions)
          find_for_authentication(conditions)
        end
      end
    end
  end
end


================================================
FILE: lib/devise/models/lockable.rb
================================================
# frozen_string_literal: true

require "devise/hooks/lockable"

module Devise
  module Models
    # Handles blocking a user access after a certain number of attempts.
    # Lockable accepts two different strategies to unlock a user after it's
    # blocked: email and time. The former will send an email to the user when
    # the lock happens, containing a link to unlock its account. The second
    # will unlock the user automatically after some configured time (ie 2.hours).
    # It's also possible to set up lockable to use both email and time strategies.
    #
    # == Options
    #
    # Lockable adds the following options to +devise+:
    #
    #   * +maximum_attempts+: how many attempts should be accepted before blocking the user.
    #   * +lock_strategy+: lock the user account by :failed_attempts or :none.
    #   * +unlock_strategy+: unlock the user account by :time, :email, :both or :none.
    #   * +unlock_in+: the time you want to unlock the user after lock happens. Only available when unlock_strategy is :time or :both.
    #   * +unlock_keys+: the keys you want to use when locking and unlocking an account
    #
    module Lockable
      extend  ActiveSupport::Concern

      delegate :lock_strategy_enabled?, :unlock_strategy_enabled?, to: "self.class"

      def self.required_fields(klass)
        attributes = []
        attributes << :failed_attempts if klass.lock_strategy_enabled?(:failed_attempts)
        attributes << :locked_at if klass.unlock_strategy_enabled?(:time)
        attributes << :unlock_token if klass.unlock_strategy_enabled?(:email)

        attributes
      end

      # Lock a user setting its locked_at to actual time.
      # * +opts+: Hash options if you don't want to send email
      #   when you lock access, you could pass the next hash
      #   `{ send_instructions: false } as option`.
      def lock_access!(opts = { })
        self.locked_at = Time.now.utc

        if unlock_strategy_enabled?(:email) && opts.fetch(:send_instructions, true)
          send_unlock_instructions
        else
          save(validate: false)
        end
      end

      # Unlock a user by cleaning locked_at and failed_attempts.
      def unlock_access!
        self.locked_at = nil
        self.failed_attempts = 0 if respond_to?(:failed_attempts=)
        self.unlock_token = nil  if respond_to?(:unlock_token=)
        save(validate: false)
      end

      # Resets failed attempts counter to 0.
      def reset_failed_attempts!
        if respond_to?(:failed_attempts) && !failed_attempts.to_i.zero?
          self.failed_attempts = 0
          save(validate: false)
        end
      end

      # Verifies whether a user is locked or not.
      def access_locked?
        !!locked_at && !lock_expired?
      end

      # Send unlock instructions by email
      def send_unlock_instructions
        raw, enc = Devise.token_generator.generate(self.class, :unlock_token)
        self.unlock_token = enc
        save(validate: false)
        send_devise_notification(:unlock_instructions, raw, {})
        raw
      end

      # Resend the unlock instructions if the user is locked.
      def resend_unlock_instructions
        if_access_locked { send_unlock_instructions }
      end

      # Overwrites active_for_authentication? from Devise::Models::Authenticatable for locking purposes
      # by verifying whether a user is active to sign in or not based on locked?
      def active_for_authentication?
        super && !access_locked?
      end

      # Overwrites invalid_message from Devise::Models::Authenticatable to define
      # the correct reason for blocking the sign in.
      def inactive_message
        access_locked? ? :locked : super
      end

      # Overwrites valid_for_authentication? from Devise::Models::Authenticatable
      # for verifying whether a user is allowed to sign in or not. If the user
      # is locked, it should never be allowed.
      def valid_for_authentication?
        return super unless persisted? && lock_strategy_enabled?(:failed_attempts)

        # Unlock the user if the lock is expired, no matter
        # if the user can login or not (wrong password, etc)
        unlock_access! if lock_expired?

        if super && !access_locked?
          true
        else
          increment_failed_attempts
          if attempts_exceeded?
            lock_access! unless access_locked?
          else
            save(validate: false)
          end
          false
        end
      end

      def increment_failed_attempts
        self.class.increment_counter(:failed_attempts, id)
        reload
      end

      def unauthenticated_message
        # If set to paranoid mode, do not show the locked message because it
        # leaks the existence of an account.
        if Devise.paranoid
          super
        elsif access_locked? || (lock_strategy_enabled?(:failed_attempts) && attempts_exceeded?)
          :locked
        elsif lock_strategy_enabled?(:failed_attempts) && last_attempt? && self.class.last_attempt_warning
          :last_attempt
        else
          super
        end
      end

      protected

        def attempts_exceeded?
          self.failed_attempts >= self.class.maximum_attempts
        end

        def last_attempt?
          self.failed_attempts == self.class.maximum_attempts - 1
        end

        # Tells if the lock is expired if :time unlock strategy is active
        def lock_expired?
          if unlock_strategy_enabled?(:time)
            locked_at && locked_at < self.class.unlock_in.ago
          else
            false
          end
        end

        # Checks whether the record is locked or not, yielding to the block
        # if it's locked, otherwise adds an error to email.
        def if_access_locked
          if access_locked?
            yield
          else
            self.errors.add(Devise.unlock_keys.first, :not_locked)
            false
          end
        end

      module ClassMethods
        # List of strategies that are enabled/supported if :both is used.
        BOTH_STRATEGIES = [:time, :email]

        # Attempt to find a user by its unlock keys. If a record is found, send new
        # unlock instructions to it. If not user is found, returns a new user
        # with an email not found error.
        # Options must contain the user's unlock keys
        def send_unlock_instructions(attributes = {})
          lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
          lockable.resend_unlock_instructions if lockable.persisted?
          lockable
        end

        # Find a user by its unlock token and try to unlock it.
        # If no user is found, returns a new user with an error.
        # If the user is not locked, creates an error for the user
        # Options must have the unlock_token
        def unlock_access_by_token(unlock_token)
          original_token = unlock_token
          unlock_token   = Devise.token_generator.digest(self, :unlock_token, unlock_token)

          lockable = find_or_initialize_with_error_by(:unlock_token, unlock_token)
          lockable.unlock_access! if lockable.persisted?
          lockable.unlock_token = original_token
          lockable
        end

        # Is the unlock enabled for the given unlock strategy?
        def unlock_strategy_enabled?(strategy)
          self.unlock_strategy == strategy ||
            (self.unlock_strategy == :both && BOTH_STRATEGIES.include?(strategy))
        end

        # Is the lock enabled for the given lock strategy?
        def lock_strategy_enabled?(strategy)
          self.lock_strategy == strategy
        end

        Devise::Models.config(self, :maximum_attempts, :lock_strategy, :unlock_strategy, :unlock_in, :unlock_keys, :last_attempt_warning)
      end
    end
  end
end


================================================
FILE: lib/devise/models/omniauthable.rb
================================================
# frozen_string_literal: true

require 'devise/omniauth'

module Devise
  module Models
    # Adds OmniAuth support to your model.
    #
    # == Options
    #
    # Oauthable adds the following options to +devise+:
    #
    #   * +omniauth_providers+: Which providers are available to this model. It expects an array:
    #
    #       devise :database_authenticatable, :omniauthable, omniauth_providers: [:twitter]
    #
    module Omniauthable
      extend ActiveSupport::Concern

      def self.required_fields(klass)
        []
      end

      module ClassMethods
        Devise::Models.config(self, :omniauth_providers)
      end
    end
  end
end


================================================
FILE: lib/devise/models/recoverable.rb
================================================
# frozen_string_literal: true

module Devise
  module Models

    # Recoverable takes care of resetting the user password and send reset instructions.
    #
    # ==Options
    #
    # Recoverable adds the following options to +devise+:
    #
    #   * +reset_password_keys+: the keys you want to use when recovering the password for an account
    #   * +reset_password_within+: the time period within which the password must be reset or the token expires.
    #   * +sign_in_after_reset_password+: whether or not to sign in the user automatically after a password reset.
    #
    # == Examples
    #
    #   # resets the user password and save the record, true if valid passwords are given, otherwise false
    #   User.find(1).reset_password('password123', 'password123')
    #
    #   # creates a new token and send it with instructions about how to reset the password
    #   User.find(1).send_reset_password_instructions
    #
    module Recoverable
      extend ActiveSupport::Concern

      def self.required_fields(klass)
        [:reset_password_sent_at, :reset_password_token]
      end

      included do
        before_update :clear_reset_password_token, if: :clear_reset_password_token?
      end

      # Update password saving the record and clearing token. Returns true if
      # the passwords are valid and the record was saved, false otherwise.
      def reset_password(new_password, new_password_confirmation)
        if new_password.present?
          self.password = new_password
          self.password_confirmation = new_password_confirmation
          save
        else
          errors.add(:password, :blank)
          false
        end
      end

      # Resets reset password token and send reset password instructions by email.
      # Returns the token sent in the e-mail.
      def send_reset_password_instructions
        token = set_reset_password_token
        send_reset_password_instructions_notification(token)

        token
      end

      # Checks if the reset password token sent is within the limit time.
      # We do this by calculating if the difference between today and the
      # sending date does not exceed the conf
Download .txt
gitextract_4bqfrk55/

├── .devcontainer/
│   └── devcontainer.json
├── .github/
│   ├── code-scanning.yml
│   ├── dependabot.yml
│   └── workflows/
│       └── test.yml
├── .gitignore
├── .yardopts
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Gemfile
├── ISSUE_TEMPLATE.md
├── MIT-LICENSE
├── README.md
├── Rakefile
├── app/
│   ├── controllers/
│   │   ├── devise/
│   │   │   ├── confirmations_controller.rb
│   │   │   ├── omniauth_callbacks_controller.rb
│   │   │   ├── passwords_controller.rb
│   │   │   ├── registrations_controller.rb
│   │   │   ├── sessions_controller.rb
│   │   │   └── unlocks_controller.rb
│   │   └── devise_controller.rb
│   ├── helpers/
│   │   └── devise_helper.rb
│   ├── mailers/
│   │   └── devise/
│   │       └── mailer.rb
│   └── views/
│       └── devise/
│           ├── confirmations/
│           │   └── new.html.erb
│           ├── mailer/
│           │   ├── confirmation_instructions.html.erb
│           │   ├── email_changed.html.erb
│           │   ├── password_change.html.erb
│           │   ├── reset_password_instructions.html.erb
│           │   └── unlock_instructions.html.erb
│           ├── passwords/
│           │   ├── edit.html.erb
│           │   └── new.html.erb
│           ├── registrations/
│           │   ├── edit.html.erb
│           │   └── new.html.erb
│           ├── sessions/
│           │   └── new.html.erb
│           ├── shared/
│           │   ├── _error_messages.html.erb
│           │   └── _links.html.erb
│           └── unlocks/
│               └── new.html.erb
├── bin/
│   └── test
├── config/
│   └── locales/
│       └── en.yml
├── devise.gemspec
├── gemfiles/
│   ├── Gemfile-rails-7-0
│   ├── Gemfile-rails-7-1
│   ├── Gemfile-rails-7-2
│   ├── Gemfile-rails-8-0
│   └── Gemfile-rails-main
├── guides/
│   └── bug_report_templates/
│       └── integration_test.rb
├── lib/
│   ├── devise/
│   │   ├── controllers/
│   │   │   ├── helpers.rb
│   │   │   ├── rememberable.rb
│   │   │   ├── responder.rb
│   │   │   ├── scoped_views.rb
│   │   │   ├── sign_in_out.rb
│   │   │   ├── store_location.rb
│   │   │   └── url_helpers.rb
│   │   ├── delegator.rb
│   │   ├── encryptor.rb
│   │   ├── failure_app.rb
│   │   ├── hooks/
│   │   │   ├── activatable.rb
│   │   │   ├── csrf_cleaner.rb
│   │   │   ├── forgetable.rb
│   │   │   ├── lockable.rb
│   │   │   ├── proxy.rb
│   │   │   ├── rememberable.rb
│   │   │   ├── timeoutable.rb
│   │   │   └── trackable.rb
│   │   ├── mailers/
│   │   │   └── helpers.rb
│   │   ├── mapping.rb
│   │   ├── models/
│   │   │   ├── authenticatable.rb
│   │   │   ├── confirmable.rb
│   │   │   ├── database_authenticatable.rb
│   │   │   ├── lockable.rb
│   │   │   ├── omniauthable.rb
│   │   │   ├── recoverable.rb
│   │   │   ├── registerable.rb
│   │   │   ├── rememberable.rb
│   │   │   ├── timeoutable.rb
│   │   │   ├── trackable.rb
│   │   │   └── validatable.rb
│   │   ├── models.rb
│   │   ├── modules.rb
│   │   ├── omniauth/
│   │   │   ├── config.rb
│   │   │   └── url_helpers.rb
│   │   ├── omniauth.rb
│   │   ├── orm/
│   │   │   ├── active_record.rb
│   │   │   └── mongoid.rb
│   │   ├── orm.rb
│   │   ├── parameter_filter.rb
│   │   ├── parameter_sanitizer.rb
│   │   ├── rails/
│   │   │   ├── routes.rb
│   │   │   └── warden_compat.rb
│   │   ├── rails.rb
│   │   ├── strategies/
│   │   │   ├── authenticatable.rb
│   │   │   ├── base.rb
│   │   │   ├── database_authenticatable.rb
│   │   │   └── rememberable.rb
│   │   ├── test/
│   │   │   ├── controller_helpers.rb
│   │   │   └── integration_helpers.rb
│   │   ├── time_inflector.rb
│   │   ├── token_generator.rb
│   │   └── version.rb
│   ├── devise.rb
│   └── generators/
│       ├── active_record/
│       │   ├── devise_generator.rb
│       │   └── templates/
│       │       ├── migration.rb
│       │       └── migration_existing.rb
│       ├── devise/
│       │   ├── controllers_generator.rb
│       │   ├── devise_generator.rb
│       │   ├── install_generator.rb
│       │   ├── orm_helpers.rb
│       │   └── views_generator.rb
│       ├── mongoid/
│       │   └── devise_generator.rb
│       └── templates/
│           ├── README
│           ├── controllers/
│           │   ├── README
│           │   ├── confirmations_controller.rb
│           │   ├── omniauth_callbacks_controller.rb
│           │   ├── passwords_controller.rb
│           │   ├── registrations_controller.rb
│           │   ├── sessions_controller.rb
│           │   └── unlocks_controller.rb
│           ├── devise.rb
│           ├── markerb/
│           │   ├── confirmation_instructions.markerb
│           │   ├── email_changed.markerb
│           │   ├── password_change.markerb
│           │   ├── reset_password_instructions.markerb
│           │   └── unlock_instructions.markerb
│           └── simple_form_for/
│               ├── confirmations/
│               │   └── new.html.erb
│               ├── passwords/
│               │   ├── edit.html.erb
│               │   └── new.html.erb
│               ├── registrations/
│               │   ├── edit.html.erb
│               │   └── new.html.erb
│               ├── sessions/
│               │   └── new.html.erb
│               └── unlocks/
│                   └── new.html.erb
└── test/
    ├── controllers/
    │   ├── custom_registrations_controller_test.rb
    │   ├── custom_strategy_test.rb
    │   ├── helper_methods_test.rb
    │   ├── helpers_test.rb
    │   ├── inherited_controller_i18n_messages_test.rb
    │   ├── internal_helpers_test.rb
    │   ├── load_hooks_controller_test.rb
    │   ├── passwords_controller_test.rb
    │   ├── sessions_controller_test.rb
    │   └── url_helpers_test.rb
    ├── delegator_test.rb
    ├── devise_test.rb
    ├── failure_app_test.rb
    ├── generators/
    │   ├── active_record_generator_test.rb
    │   ├── controllers_generator_test.rb
    │   ├── devise_generator_test.rb
    │   ├── install_generator_test.rb
    │   ├── mongoid_generator_test.rb
    │   └── views_generator_test.rb
    ├── helpers/
    │   └── devise_helper_test.rb
    ├── integration/
    │   ├── authenticatable_test.rb
    │   ├── confirmable_test.rb
    │   ├── database_authenticatable_test.rb
    │   ├── http_authenticatable_test.rb
    │   ├── lockable_test.rb
    │   ├── mounted_engine_test.rb
    │   ├── omniauthable_test.rb
    │   ├── recoverable_test.rb
    │   ├── registerable_test.rb
    │   ├── rememberable_test.rb
    │   ├── timeoutable_test.rb
    │   └── trackable_test.rb
    ├── mailers/
    │   ├── confirmation_instructions_test.rb
    │   ├── email_changed_test.rb
    │   ├── mailer_test.rb
    │   ├── reset_password_instructions_test.rb
    │   └── unlock_instructions_test.rb
    ├── mapping_test.rb
    ├── models/
    │   ├── authenticatable_test.rb
    │   ├── confirmable_test.rb
    │   ├── database_authenticatable_test.rb
    │   ├── lockable_test.rb
    │   ├── omniauthable_test.rb
    │   ├── recoverable_test.rb
    │   ├── registerable_test.rb
    │   ├── rememberable_test.rb
    │   ├── serializable_test.rb
    │   ├── timeoutable_test.rb
    │   ├── trackable_test.rb
    │   └── validatable_test.rb
    ├── models_test.rb
    ├── omniauth/
    │   ├── config_test.rb
    │   └── url_helpers_test.rb
    ├── orm/
    │   ├── active_record.rb
    │   └── mongoid.rb
    ├── parameter_sanitizer_test.rb
    ├── rails_app/
    │   ├── Rakefile
    │   ├── app/
    │   │   ├── active_record/
    │   │   │   ├── admin.rb
    │   │   │   ├── shim.rb
    │   │   │   ├── user.rb
    │   │   │   ├── user_on_engine.rb
    │   │   │   ├── user_on_main_app.rb
    │   │   │   ├── user_with_validations.rb
    │   │   │   └── user_without_email.rb
    │   │   ├── controllers/
    │   │   │   ├── admins/
    │   │   │   │   └── sessions_controller.rb
    │   │   │   ├── admins_controller.rb
    │   │   │   ├── application_controller.rb
    │   │   │   ├── application_with_fake_engine.rb
    │   │   │   ├── custom/
    │   │   │   │   └── registrations_controller.rb
    │   │   │   ├── home_controller.rb
    │   │   │   ├── publisher/
    │   │   │   │   ├── registrations_controller.rb
    │   │   │   │   └── sessions_controller.rb
    │   │   │   ├── streaming_controller.rb
    │   │   │   ├── users/
    │   │   │   │   └── omniauth_callbacks_controller.rb
    │   │   │   └── users_controller.rb
    │   │   ├── helpers/
    │   │   │   └── application_helper.rb
    │   │   ├── mailers/
    │   │   │   └── users/
    │   │   │       ├── from_proc_mailer.rb
    │   │   │       ├── mailer.rb
    │   │   │       └── reply_to_mailer.rb
    │   │   ├── mongoid/
    │   │   │   ├── admin.rb
    │   │   │   ├── shim.rb
    │   │   │   ├── user.rb
    │   │   │   ├── user_on_engine.rb
    │   │   │   ├── user_on_main_app.rb
    │   │   │   ├── user_with_validations.rb
    │   │   │   └── user_without_email.rb
    │   │   └── views/
    │   │       ├── admins/
    │   │       │   ├── index.html.erb
    │   │       │   └── sessions/
    │   │       │       └── new.html.erb
    │   │       ├── home/
    │   │       │   ├── admin_dashboard.html.erb
    │   │       │   ├── index.html.erb
    │   │       │   ├── join.html.erb
    │   │       │   ├── private.html.erb
    │   │       │   └── user_dashboard.html.erb
    │   │       ├── layouts/
    │   │       │   └── application.html.erb
    │   │       └── users/
    │   │           ├── edit_form.html.erb
    │   │           ├── index.html.erb
    │   │           ├── mailer/
    │   │           │   └── confirmation_instructions.erb
    │   │           └── sessions/
    │   │               └── new.html.erb
    │   ├── bin/
    │   │   ├── bundle
    │   │   ├── rails
    │   │   └── rake
    │   ├── config/
    │   │   ├── application.rb
    │   │   ├── boot.rb
    │   │   ├── database.yml
    │   │   ├── environment.rb
    │   │   ├── environments/
    │   │   │   ├── development.rb
    │   │   │   ├── production.rb
    │   │   │   └── test.rb
    │   │   ├── initializers/
    │   │   │   ├── backtrace_silencers.rb
    │   │   │   ├── devise.rb
    │   │   │   ├── inflections.rb
    │   │   │   ├── secret_token.rb
    │   │   │   └── session_store.rb
    │   │   └── routes.rb
    │   ├── config.ru
    │   ├── db/
    │   │   ├── migrate/
    │   │   │   └── 20100401102949_create_tables.rb
    │   │   └── schema.rb
    │   ├── lib/
    │   │   ├── lazy_load_test_module.rb
    │   │   ├── shared_admin.rb
    │   │   ├── shared_user.rb
    │   │   ├── shared_user_without_email.rb
    │   │   └── shared_user_without_omniauth.rb
    │   └── public/
    │       ├── 404.html
    │       ├── 422.html
    │       └── 500.html
    ├── rails_test.rb
    ├── routes_test.rb
    ├── support/
    │   ├── action_controller/
    │   │   └── record_identifier.rb
    │   ├── assertions.rb
    │   ├── helpers.rb
    │   ├── http_method_compatibility.rb
    │   ├── integration.rb
    │   ├── locale/
    │   │   ├── de.yml
    │   │   ├── en.yml
    │   │   └── pt-BR.yml
    │   ├── mongoid.yml
    │   └── webrat/
    │       ├── integrations/
    │       │   └── rails.rb
    │       └── matchers.rb
    ├── test/
    │   ├── controller_helpers_test.rb
    │   └── integration_helpers_test.rb
    ├── test_helper.rb
    └── test_models.rb
Download .txt
SYMBOL INDEX (1041 symbols across 172 files)

FILE: app/controllers/devise/confirmations_controller.rb
  class Devise::ConfirmationsController (line 3) | class Devise::ConfirmationsController < DeviseController
    method new (line 5) | def new
    method create (line 10) | def create
    method show (line 22) | def show
    method after_resending_confirmation_instructions_path_for (line 38) | def after_resending_confirmation_instructions_path_for(resource_name)
    method after_confirmation_path_for (line 43) | def after_confirmation_path_for(resource_name, resource)
    method translation_scope (line 51) | def translation_scope

FILE: app/controllers/devise/omniauth_callbacks_controller.rb
  class Devise::OmniauthCallbacksController (line 3) | class Devise::OmniauthCallbacksController < DeviseController
    method passthru (line 6) | def passthru
    method failure (line 10) | def failure
    method failed_strategy (line 17) | def failed_strategy
    method failure_message (line 21) | def failure_message
    method after_omniauth_failure_path_for (line 29) | def after_omniauth_failure_path_for(scope)
    method translation_scope (line 33) | def translation_scope

FILE: app/controllers/devise/passwords_controller.rb
  class Devise::PasswordsController (line 3) | class Devise::PasswordsController < DeviseController
    method new (line 9) | def new
    method create (line 14) | def create
    method edit (line 26) | def edit
    method update (line 33) | def update
    method after_resetting_password_path_for (line 55) | def after_resetting_password_path_for(resource)
    method after_sending_reset_password_instructions_path_for (line 60) | def after_sending_reset_password_instructions_path_for(resource_name)
    method assert_reset_token_passed (line 65) | def assert_reset_token_passed
    method sign_in_after_reset_password? (line 73) | def sign_in_after_reset_password?
    method unlockable? (line 79) | def unlockable?(resource)
    method translation_scope (line 85) | def translation_scope

FILE: app/controllers/devise/registrations_controller.rb
  class Devise::RegistrationsController (line 3) | class Devise::RegistrationsController < DeviseController
    method new (line 9) | def new
    method create (line 16) | def create
    method edit (line 39) | def edit
    method update (line 46) | def update
    method destroy (line 65) | def destroy
    method cancel (line 78) | def cancel
    method update_resource (line 87) | def update_resource(resource, params)
    method build_resource (line 93) | def build_resource(hash = {})
    method sign_up (line 99) | def sign_up(resource_name, resource)
    method after_sign_up_path_for (line 105) | def after_sign_up_path_for(resource)
    method after_inactive_sign_up_path_for (line 111) | def after_inactive_sign_up_path_for(resource)
    method after_update_path_for (line 120) | def after_update_path_for(resource)
    method authenticate_scope! (line 125) | def authenticate_scope!
    method sign_in_after_change_password? (line 131) | def sign_in_after_change_password?
    method sign_up_params (line 137) | def sign_up_params
    method account_update_params (line 141) | def account_update_params
    method translation_scope (line 145) | def translation_scope
    method set_flash_message_for_update (line 151) | def set_flash_message_for_update(resource, prev_unconfirmed_email)
    method update_needs_confirmation? (line 164) | def update_needs_confirmation?(resource, previous)

FILE: app/controllers/devise/sessions_controller.rb
  class Devise::SessionsController (line 3) | class Devise::SessionsController < DeviseController
    method new (line 10) | def new
    method create (line 18) | def create
    method destroy (line 27) | def destroy
    method sign_in_params (line 36) | def sign_in_params
    method serialize_options (line 40) | def serialize_options(resource)
    method auth_options (line 47) | def auth_options
    method translation_scope (line 51) | def translation_scope
    method verify_signed_out_user (line 61) | def verify_signed_out_user
    method all_signed_out? (line 69) | def all_signed_out?
    method respond_to_on_destroy (line 75) | def respond_to_on_destroy(non_navigational_status: :no_content)

FILE: app/controllers/devise/unlocks_controller.rb
  class Devise::UnlocksController (line 3) | class Devise::UnlocksController < DeviseController
    method new (line 7) | def new
    method create (line 12) | def create
    method show (line 24) | def show
    method after_sending_unlock_instructions_path_for (line 40) | def after_sending_unlock_instructions_path_for(resource)
    method after_unlock_path_for (line 45) | def after_unlock_path_for(resource)
    method translation_scope (line 49) | def translation_scope

FILE: app/controllers/devise_controller.rb
  class DeviseController (line 4) | class DeviseController < Devise.parent_controller.constantize
    method _prefixes (line 28) | def _prefixes #:nodoc:
    method internal_methods (line 45) | def self.internal_methods #:nodoc:
    method resource (line 52) | def resource
    method resource_name (line 57) | def resource_name
    method resource_class (line 63) | def resource_class
    method signed_in_resource (line 68) | def signed_in_resource
    method devise_mapping (line 73) | def devise_mapping
    method assert_is_devise_resource! (line 78) | def assert_is_devise_resource! #:nodoc:
    method navigational_formats (line 98) | def navigational_formats
    method unknown_action! (line 102) | def unknown_action!(msg)
    method resource= (line 108) | def resource=(new_resource)
    method require_no_authentication (line 116) | def require_no_authentication
    method successfully_sent? (line 137) | def successfully_sent?(resource)
    method set_flash_message (line 168) | def set_flash_message(key, kind, options = {})
    method set_flash_message! (line 178) | def set_flash_message!(key, kind, options = {})
    method set_minimum_password_length (line 185) | def set_minimum_password_length
    method devise_i18n_options (line 191) | def devise_i18n_options(options)
    method find_message (line 196) | def find_message(kind, options = {})
    method translation_scope (line 207) | def translation_scope
    method clean_up_passwords (line 211) | def clean_up_passwords(object)
    method respond_with_navigational (line 215) | def respond_with_navigational(*args, &block)
    method resource_params (line 221) | def resource_params

FILE: app/helpers/devise_helper.rb
  type DeviseHelper (line 4) | module DeviseHelper

FILE: app/mailers/devise/mailer.rb
  class Devise::Mailer (line 4) | class Devise::Mailer < Devise.parent_mailer.constantize
    method confirmation_instructions (line 7) | def confirmation_instructions(record, token, opts = {})
    method reset_password_instructions (line 12) | def reset_password_instructions(record, token, opts = {})
    method unlock_instructions (line 17) | def unlock_instructions(record, token, opts = {})
    method email_changed (line 22) | def email_changed(record, opts = {})
    method password_change (line 26) | def password_change(record, opts = {})

FILE: guides/bug_report_templates/integration_test.rb
  class DeviseCreateUsers (line 27) | class DeviseCreateUsers < ActiveRecord::Migration
    method change (line 28) | def change
  class TestApp (line 43) | class TestApp < Rails::Application
  class User (line 63) | class User < ActiveRecord::Base
  class ApplicationController (line 73) | class ApplicationController < ActionController::Base
  class TestController (line 76) | class TestController < ApplicationController
    method index (line 81) | def index
  class BugTest (line 88) | class BugTest < ActionDispatch::IntegrationTest
    method test_returns_success (line 92) | def test_returns_success
    method app (line 103) | def app

FILE: lib/devise.rb
  type Devise (line 11) | module Devise
    type Controllers (line 22) | module Controllers
    type Hooks (line 32) | module Hooks
    type Mailers (line 36) | module Mailers
    type Strategies (line 40) | module Strategies
    type Test (line 45) | module Test
    function mappings (line 277) | def self.mappings
    function setup (line 317) | def self.setup
    class Getter (line 321) | class Getter
      method initialize (line 322) | def initialize(name)
      method get (line 326) | def get
    function ref (line 336) | def self.ref(arg)
    function available_router_name (line 344) | def self.available_router_name
    function omniauth_providers (line 348) | def self.omniauth_providers
    function mailer (line 353) | def self.mailer
    function mailer= (line 358) | def self.mailer=(class_name)
    function add_mapping (line 364) | def self.add_mapping(resource, options)
    function add_module (line 397) | def self.add_module(module_name, options = {})
    function warden (line 453) | def self.warden(&block)
    function omniauth (line 461) | def self.omniauth(provider, *args)
    function include_helpers (line 467) | def self.include_helpers(scope)
    function regenerate_helpers! (line 479) | def self.regenerate_helpers!
    function configure_warden! (line 486) | def self.configure_warden! #:nodoc:
    function friendly_token (line 511) | def self.friendly_token(length = 20)
    function secure_compare (line 519) | def self.secure_compare(a, b)
    function deprecator (line 524) | def self.deprecator

FILE: lib/devise/controllers/helpers.rb
  type Devise (line 3) | module Devise
    type Controllers (line 4) | module Controllers
      type Helpers (line 6) | module Helpers
        type ClassMethods (line 17) | module ClassMethods
          function devise_group (line 39) | def devise_group(group_name, opts = {})
          function log_process_action (line 83) | def log_process_action(payload)
        function define_helpers (line 113) | def self.define_helpers(mapping) #:nodoc:
        function warden (line 144) | def warden
        function devise_controller? (line 153) | def devise_controller?
        function devise_parameter_sanitizer (line 160) | def devise_parameter_sanitizer
        function allow_params_authentication! (line 165) | def allow_params_authentication!
        function signed_in_root_path (line 171) | def signed_in_root_path(resource_or_scope)
        function after_sign_in_path_for (line 217) | def after_sign_in_path_for(resource_or_scope)
        function after_sign_out_path_for (line 227) | def after_sign_out_path_for(resource_or_scope)
        function sign_in_and_redirect (line 237) | def sign_in_and_redirect(resource_or_scope, *args)
        function sign_out_and_redirect (line 247) | def sign_out_and_redirect(resource_or_scope)
        function handle_unverified_request (line 256) | def handle_unverified_request
        function request_format (line 262) | def request_format
        function is_navigational_format? (line 266) | def is_navigational_format?
        function is_flashing_format? (line 272) | def is_flashing_format?
        function expire_data_after_sign_out! (line 278) | def expire_data_after_sign_out!
    class MissingWarden (line 285) | class MissingWarden < StandardError
      method initialize (line 286) | def initialize

FILE: lib/devise/controllers/rememberable.rb
  type Devise (line 3) | module Devise
    type Controllers (line 4) | module Controllers
      type Rememberable (line 8) | module Rememberable
        function cookie_values (line 10) | def self.cookie_values
        function remember_me_is_active? (line 14) | def remember_me_is_active?(resource)
        function remember_me (line 22) | def remember_me(resource)
        function forget_me (line 30) | def forget_me(resource)
        function forget_cookie_values (line 38) | def forget_cookie_values(resource)
        function remember_cookie_values (line 42) | def remember_cookie_values(resource)
        function remember_key (line 51) | def remember_key(resource, scope)

FILE: lib/devise/controllers/responder.rb
  type Devise (line 3) | module Devise
    type Controllers (line 4) | module Controllers
      class Responder (line 7) | class Responder < ActionController::Responder
        method error_status (line 15) | def self.error_status
        method redirect_status (line 19) | def self.redirect_status
        method error_status= (line 23) | def self.error_status=(*)
        method redirect_status= (line 28) | def self.redirect_status=(*)

FILE: lib/devise/controllers/scoped_views.rb
  type Devise (line 3) | module Devise
    type Controllers (line 4) | module Controllers
      type ScopedViews (line 5) | module ScopedViews
        type ClassMethods (line 8) | module ClassMethods
          function scoped_views? (line 9) | def scoped_views?
          function scoped_views= (line 13) | def scoped_views=(value)

FILE: lib/devise/controllers/sign_in_out.rb
  type Devise (line 3) | module Devise
    type Controllers (line 4) | module Controllers
      type SignInOut (line 7) | module SignInOut
        function signed_in? (line 13) | def signed_in?(scope = nil)
        function sign_in (line 33) | def sign_in(resource_or_scope, *args)
        function bypass_sign_in (line 56) | def bypass_sign_in(resource, scope: nil)
        function sign_out (line 71) | def sign_out(resource_or_scope = nil)
        function sign_out_all_scopes (line 86) | def sign_out_all_scopes(lock = true)
        function expire_data_after_sign_in! (line 99) | def expire_data_after_sign_in!

FILE: lib/devise/controllers/store_location.rb
  type Devise (line 5) | module Devise
    type Controllers (line 6) | module Controllers
      type StoreLocation (line 10) | module StoreLocation
        function stored_location_for (line 18) | def stored_location_for(resource_or_scope)
        function store_location_for (line 36) | def store_location_for(resource_or_scope, location)
        function parse_uri (line 45) | def parse_uri(location)
        function stored_location_key_for (line 51) | def stored_location_key_for(resource_or_scope)
        function extract_path_from_location (line 56) | def extract_path_from_location(location)
        function remove_domain_from_uri (line 67) | def remove_domain_from_uri(uri)
        function add_fragment_back_to_path (line 71) | def add_fragment_back_to_path(uri, path)

FILE: lib/devise/controllers/url_helpers.rb
  type Devise (line 3) | module Devise
    type Controllers (line 4) | module Controllers
      type UrlHelpers (line 30) | module UrlHelpers
        function remove_helpers! (line 31) | def self.remove_helpers!
        function generate_helpers! (line 37) | def self.generate_helpers!(routes = nil)
        function _devise_route_context (line 64) | def _devise_route_context

FILE: lib/devise/delegator.rb
  type Devise (line 3) | module Devise
    class Delegator (line 5) | class Delegator
      method call (line 6) | def call(env)
      method failure_app (line 10) | def failure_app(env)

FILE: lib/devise/encryptor.rb
  type Devise (line 5) | module Devise
    type Encryptor (line 6) | module Encryptor
      function digest (line 7) | def self.digest(klass, password)
      function compare (line 14) | def self.compare(klass, hashed_password, password)

FILE: lib/devise/failure_app.rb
  type Devise (line 5) | module Devise
    class FailureApp (line 10) | class FailureApp < ActionController::Metal
      method call (line 26) | def self.call(env)
      method default_url_options (line 34) | def self.default_url_options(*args)
      method respond (line 42) | def respond
      method http_auth (line 52) | def http_auth
      method recall (line 59) | def recall
      method redirect (line 86) | def redirect
      method i18n_options (line 101) | def i18n_options(options)
      method i18n_message (line 105) | def i18n_message(default = nil)
      method i18n_locale (line 131) | def i18n_locale
      method redirect_url (line 135) | def redirect_url
      method route (line 151) | def route(scope)
      method scope_url (line 155) | def scope_url
      method skip_format? (line 182) | def skip_format?
      method http_auth? (line 194) | def http_auth?
      method http_auth_header? (line 204) | def http_auth_header?
      method http_auth_body (line 208) | def http_auth_body
      method recall_app (line 220) | def recall_app(app)
      method warden (line 227) | def warden
      method warden_options (line 231) | def warden_options
      method warden_message (line 235) | def warden_message
      method scope (line 239) | def scope
      method scope_class (line 243) | def scope_class
      method attempted_path (line 247) | def attempted_path
      method store_location! (line 255) | def store_location!
      method is_navigational_format? (line 259) | def is_navigational_format?
      method is_flashing_format? (line 265) | def is_flashing_format?
      method request_format (line 269) | def request_format
      method relative_url_root (line 273) | def relative_url_root
      method relative_url_root? (line 281) | def relative_url_root?

FILE: lib/devise/hooks/proxy.rb
  type Devise (line 3) | module Devise
    type Hooks (line 4) | module Hooks
      class Proxy (line 7) | class Proxy #:nodoc:
        method initialize (line 14) | def initialize(warden)
        method session (line 18) | def session

FILE: lib/devise/mailers/helpers.rb
  type Devise (line 3) | module Devise
    type Mailers (line 4) | module Mailers
      type Helpers (line 5) | module Helpers
        function devise_mail (line 17) | def devise_mail(record, action, opts = {}, &block)
        function initialize_from_record (line 22) | def initialize_from_record(record)
        function devise_mapping (line 27) | def devise_mapping
        function headers_for (line 31) | def headers_for(action, opts)
        function mailer_sender (line 50) | def mailer_sender(mapping)
        function template_paths (line 58) | def template_paths
        function subject_for (line 81) | def subject_for(key)

FILE: lib/devise/mapping.rb
  type Devise (line 3) | module Devise
    class Mapping (line 26) | class Mapping #:nodoc:
      method find_scope! (line 35) | def self.find_scope!(obj)
      method find_by_path! (line 49) | def self.find_by_path!(path, path_type = :fullpath)
      method initialize (line 54) | def initialize(name, options) #:nodoc:
      method modules (line 77) | def modules
      method to (line 82) | def to
      method strategies (line 86) | def strategies
      method no_input_strategies (line 90) | def no_input_strategies
      method routes (line 94) | def routes
      method authenticatable? (line 98) | def authenticatable?
      method fullpath (line 102) | def fullpath
      method add_module (line 113) | def self.add_module(m)
      method default_failure_app (line 123) | def default_failure_app(options)
      method default_controllers (line 131) | def default_controllers(options)
      method default_path_names (line 138) | def default_path_names(options)
      method default_constraints (line 144) | def default_constraints(options)
      method default_defaults (line 149) | def default_defaults(options)
      method default_used_route (line 154) | def default_used_route(options)
      method default_used_helpers (line 166) | def default_used_helpers(options)

FILE: lib/devise/models.rb
  type Devise (line 3) | module Devise
    type Models (line 4) | module Models
      class MissingAttribute (line 5) | class MissingAttribute < StandardError
        method initialize (line 6) | def initialize(attributes)
        method message (line 10) | def message
      function config (line 31) | def self.config(mod, *accessors) #:nodoc:
      function check_fields! (line 54) | def self.check_fields!(klass)
      function devise (line 79) | def devise(*modules)
      function devise_modules_hook! (line 116) | def devise_modules_hook!

FILE: lib/devise/models/authenticatable.rb
  type Devise (line 6) | module Devise
    type Models (line 7) | module Models
      type Authenticatable (line 55) | module Authenticatable
        function required_fields (line 71) | def self.required_fields(klass)
        function valid_for_authentication? (line 81) | def valid_for_authentication?
        function unauthenticated_message (line 85) | def unauthenticated_message
        function active_for_authentication? (line 89) | def active_for_authentication?
        function inactive_message (line 93) | def inactive_message
        function authenticatable_salt (line 97) | def authenticatable_salt
        function serializable_hash (line 105) | def serializable_hash(options = nil)
        function inspect (line 120) | def inspect
        function devise_mailer (line 129) | def devise_mailer
        function send_devise_notification (line 193) | def send_devise_notification(notification, *args)
        function downcase_keys (line 198) | def downcase_keys
        function strip_whitespace (line 202) | def strip_whitespace
        function apply_to_attribute_or_variable (line 206) | def apply_to_attribute_or_variable(attr, method)
        type ClassMethods (line 220) | module ClassMethods
          function serialize_into_session (line 225) | def serialize_into_session(record)
          function serialize_from_session (line 229) | def serialize_from_session(key, salt)
          function params_authenticatable? (line 234) | def params_authenticatable?(strategy)
          function http_authenticatable? (line 239) | def http_authenticatable?(strategy)
          function find_for_authentication (line 263) | def find_for_authentication(tainted_conditions)
          function find_first_by_auth_conditions (line 267) | def find_first_by_auth_conditions(tainted_conditions, opts = {})
          function find_or_initialize_with_error_by (line 272) | def find_or_initialize_with_error_by(attribute, value, error = :...
          function find_or_initialize_with_errors (line 277) | def find_or_initialize_with_errors(required_attributes, attribut...
          function devise_parameter_filter (line 296) | def devise_parameter_filter

FILE: lib/devise/models/confirmable.rb
  type Devise (line 3) | module Devise
    type Models (line 4) | module Models
      type Confirmable (line 45) | module Confirmable
        function initialize (line 61) | def initialize(*args, &block)
        function required_fields (line 70) | def self.required_fields(klass)
        function confirm (line 79) | def confirm(args = {})
        function confirmed? (line 106) | def confirmed?
        function pending_reconfirmation? (line 110) | def pending_reconfirmation?
        function send_confirmation_instructions (line 115) | def send_confirmation_instructions
        function send_reconfirmation_instructions (line 124) | def send_reconfirmation_instructions
        function resend_confirmation_instructions (line 134) | def resend_confirmation_instructions
        function active_for_authentication? (line 144) | def active_for_authentication?
        function inactive_message (line 149) | def inactive_message
        function skip_confirmation! (line 155) | def skip_confirmation!
        function skip_confirmation_notification! (line 161) | def skip_confirmation_notification!
        function skip_reconfirmation! (line 167) | def skip_reconfirmation!
        function skip_reconfirmation_in_callback! (line 175) | def skip_reconfirmation_in_callback!
        function send_on_create_confirmation_instructions (line 182) | def send_on_create_confirmation_instructions
        function confirmation_required? (line 187) | def confirmation_required?
        function confirmation_period_valid? (line 213) | def confirmation_period_valid?
        function confirmation_period_expired? (line 232) | def confirmation_period_expired?
        function pending_any_confirmation (line 237) | def pending_any_confirmation
        function generate_confirmation_token (line 248) | def generate_confirmation_token
        function generate_confirmation_token! (line 257) | def generate_confirmation_token!
        function postpone_email_change_until_confirmation_and_regenerate_confirmation_token (line 261) | def postpone_email_change_until_confirmation_and_regenerate_confir...
        function postpone_email_change? (line 272) | def postpone_email_change?
        function reconfirmation_required? (line 282) | def reconfirmation_required?
        function send_confirmation_notification? (line 286) | def send_confirmation_notification?
        function send_email_changed_notification? (line 292) | def send_email_changed_notification?
        function after_confirmation (line 310) | def after_confirmation
        type ClassMethods (line 313) | module ClassMethods
          function send_confirmation_instructions (line 318) | def send_confirmation_instructions(attributes = {})
          function confirm_by_token (line 331) | def confirm_by_token(confirmation_token)
          function find_by_unconfirmed_email_with_errors (line 359) | def find_by_unconfirmed_email_with_errors(attributes = {})

FILE: lib/devise/models/database_authenticatable.rb
  type Devise (line 5) | module Devise
    type Models (line 6) | module Models
      type DatabaseAuthenticatable (line 31) | module DatabaseAuthenticatable
        function initialize (line 42) | def initialize(*args, &block)
        function skip_email_changed_notification! (line 49) | def skip_email_changed_notification!
        function skip_password_change_notification! (line 54) | def skip_password_change_notification!
        function required_fields (line 58) | def self.required_fields(klass)
        function password= (line 65) | def password=(new_password)
        function valid_password? (line 71) | def valid_password?(password)
        function clean_up_passwords (line 76) | def clean_up_passwords
        function update_with_password (line 87) | def update_with_password(params)
        function update_without_password (line 120) | def update_without_password(params)
        function destroy_with_password (line 132) | def destroy_with_password(current_password)
        function after_database_authentication (line 154) | def after_database_authentication
        function authenticatable_salt (line 158) | def authenticatable_salt
        function send_email_changed_notification (line 163) | def send_email_changed_notification
        function send_password_change_notification (line 168) | def send_password_change_notification
        function password_digest (line 179) | def password_digest(password)
        function send_email_changed_notification? (line 183) | def send_email_changed_notification?
        function send_password_change_notification? (line 187) | def send_password_change_notification?
        type ClassMethods (line 191) | module ClassMethods
          function find_for_database_authentication (line 198) | def find_for_database_authentication(conditions)

FILE: lib/devise/models/lockable.rb
  type Devise (line 5) | module Devise
    type Models (line 6) | module Models
      type Lockable (line 24) | module Lockable
        function required_fields (line 29) | def self.required_fields(klass)
        function lock_access! (line 42) | def lock_access!(opts = { })
        function unlock_access! (line 53) | def unlock_access!
        function reset_failed_attempts! (line 61) | def reset_failed_attempts!
        function access_locked? (line 69) | def access_locked?
        function send_unlock_instructions (line 74) | def send_unlock_instructions
        function resend_unlock_instructions (line 83) | def resend_unlock_instructions
        function active_for_authentication? (line 89) | def active_for_authentication?
        function inactive_message (line 95) | def inactive_message
        function valid_for_authentication? (line 102) | def valid_for_authentication?
        function increment_failed_attempts (line 122) | def increment_failed_attempts
        function unauthenticated_message (line 127) | def unauthenticated_message
        function attempts_exceeded? (line 143) | def attempts_exceeded?
        function last_attempt? (line 147) | def last_attempt?
        function lock_expired? (line 152) | def lock_expired?
        function if_access_locked (line 162) | def if_access_locked
        type ClassMethods (line 171) | module ClassMethods
          function send_unlock_instructions (line 179) | def send_unlock_instructions(attributes = {})
          function unlock_access_by_token (line 189) | def unlock_access_by_token(unlock_token)
          function unlock_strategy_enabled? (line 200) | def unlock_strategy_enabled?(strategy)
          function lock_strategy_enabled? (line 206) | def lock_strategy_enabled?(strategy)

FILE: lib/devise/models/omniauthable.rb
  type Devise (line 5) | module Devise
    type Models (line 6) | module Models
      type Omniauthable (line 17) | module Omniauthable
        function required_fields (line 20) | def self.required_fields(klass)
        type ClassMethods (line 24) | module ClassMethods

FILE: lib/devise/models/recoverable.rb
  type Devise (line 3) | module Devise
    type Models (line 4) | module Models
      type Recoverable (line 24) | module Recoverable
        function required_fields (line 27) | def self.required_fields(klass)
        function reset_password (line 37) | def reset_password(new_password, new_password_confirmation)
        function send_reset_password_instructions (line 50) | def send_reset_password_instructions
        function reset_password_period_valid? (line 77) | def reset_password_period_valid?
        function clear_reset_password_token (line 84) | def clear_reset_password_token
        function set_reset_password_token (line 89) | def set_reset_password_token
        function send_reset_password_instructions_notification (line 98) | def send_reset_password_instructions_notification(token)
        function clear_reset_password_token? (line 102) | def clear_reset_password_token?
        type ClassMethods (line 111) | module ClassMethods
          function with_reset_password_token (line 114) | def with_reset_password_token(token)
          function send_reset_password_instructions (line 123) | def send_reset_password_instructions(attributes = {})
          function reset_password_by_token (line 134) | def reset_password_by_token(attributes = {})

FILE: lib/devise/models/registerable.rb
  type Devise (line 3) | module Devise
    type Models (line 4) | module Models
      type Registerable (line 7) | module Registerable
        function required_fields (line 10) | def self.required_fields(klass)
        type ClassMethods (line 14) | module ClassMethods
          function new_with_session (line 21) | def new_with_session(params, session)

FILE: lib/devise/models/rememberable.rb
  type Devise (line 7) | module Devise
    type Models (line 8) | module Models
      type Rememberable (line 41) | module Rememberable
        function required_fields (line 46) | def self.required_fields(klass)
        function remember_me! (line 50) | def remember_me!
        function forget_me! (line 58) | def forget_me!
        function remember_expires_at (line 65) | def remember_expires_at
        function extend_remember_period (line 69) | def extend_remember_period
        function rememberable_value (line 73) | def rememberable_value
        function rememberable_options (line 86) | def rememberable_options
        function after_remembered (line 100) | def after_remembered
        function remember_me? (line 103) | def remember_me?(token, generated_at)
        function time_from_json (line 124) | def time_from_json(value)
        type ClassMethods (line 132) | module ClassMethods
          function serialize_into_cookie (line 134) | def serialize_into_cookie(record)
          function serialize_from_cookie (line 139) | def serialize_from_cookie(*args)
          function remember_token (line 147) | def remember_token #:nodoc:

FILE: lib/devise/models/timeoutable.rb
  type Devise (line 5) | module Devise
    type Models (line 6) | module Models
      type Timeoutable (line 22) | module Timeoutable
        function required_fields (line 25) | def self.required_fields(klass)
        function timedout? (line 30) | def timedout?(last_access)
        function timeout_in (line 34) | def timeout_in
        type ClassMethods (line 40) | module ClassMethods

FILE: lib/devise/models/trackable.rb
  type Devise (line 5) | module Devise
    type Models (line 6) | module Models
      type Trackable (line 15) | module Trackable
        function required_fields (line 16) | def self.required_fields(klass)
        function update_tracked_fields (line 20) | def update_tracked_fields(request)
        function update_tracked_fields! (line 33) | def update_tracked_fields!(request)
        function extract_ip_from (line 45) | def extract_ip_from(request)

FILE: lib/devise/models/validatable.rb
  type Devise (line 3) | module Devise
    type Models (line 4) | module Models
      type Validatable (line 19) | module Validatable
        function required_fields (line 24) | def self.required_fields(klass)
        function included (line 28) | def self.included(base)
        function assert_validations_api! (line 43) | def self.assert_validations_api!(base) #:nodoc:
        function password_required? (line 57) | def password_required?
        function email_required? (line 61) | def email_required?
        type ClassMethods (line 65) | module ClassMethods

FILE: lib/devise/omniauth.rb
  type Devise (line 22) | module Devise
    type OmniAuth (line 23) | module OmniAuth

FILE: lib/devise/omniauth/config.rb
  type Devise (line 3) | module Devise
    type OmniAuth (line 4) | module OmniAuth
      class StrategyNotFound (line 5) | class StrategyNotFound < NameError
        method initialize (line 6) | def initialize(strategy)
      class Config (line 13) | class Config
        method initialize (line 17) | def initialize(provider, args)
        method strategy_class (line 26) | def strategy_class
        method find_strategy (line 30) | def find_strategy
        method autoload_strategy (line 37) | def autoload_strategy

FILE: lib/devise/omniauth/url_helpers.rb
  type Devise (line 3) | module Devise
    type OmniAuth (line 4) | module OmniAuth
      type UrlHelpers (line 5) | module UrlHelpers
        function omniauth_authorize_path (line 6) | def omniauth_authorize_path(resource_or_scope, provider, *args)
        function omniauth_authorize_url (line 11) | def omniauth_authorize_url(resource_or_scope, provider, *args)
        function omniauth_callback_path (line 16) | def omniauth_callback_path(resource_or_scope, provider, *args)
        function omniauth_callback_url (line 21) | def omniauth_callback_url(resource_or_scope, provider, *args)

FILE: lib/devise/orm.rb
  type Devise (line 3) | module Devise
    type Orm (line 4) | module Orm # :nodoc:
      function active_record? (line 5) | def self.active_record?(model)
      function included (line 9) | def self.included(model)
      type DirtyTrackingActiveRecordMethods (line 17) | module DirtyTrackingActiveRecordMethods
        function devise_email_before_last_save (line 18) | def devise_email_before_last_save
        function devise_email_in_database (line 22) | def devise_email_in_database
        function devise_saved_change_to_email? (line 26) | def devise_saved_change_to_email?
        function devise_saved_change_to_encrypted_password? (line 30) | def devise_saved_change_to_encrypted_password?
        function devise_will_save_change_to_email? (line 34) | def devise_will_save_change_to_email?
        function devise_unconfirmed_email_will_change! (line 38) | def devise_unconfirmed_email_will_change!
        function devise_respond_to_and_will_save_change_to_attribute? (line 42) | def devise_respond_to_and_will_save_change_to_attribute?(attribute)
      type DirtyTrackingMongoidMethods (line 47) | module DirtyTrackingMongoidMethods
        function devise_email_before_last_save (line 48) | def devise_email_before_last_save
        function devise_email_in_database (line 52) | def devise_email_in_database
        function devise_saved_change_to_email? (line 56) | def devise_saved_change_to_email?
        function devise_saved_change_to_encrypted_password? (line 60) | def devise_saved_change_to_encrypted_password?
        function devise_will_save_change_to_email? (line 64) | def devise_will_save_change_to_email?
        function devise_unconfirmed_email_will_change! (line 68) | def devise_unconfirmed_email_will_change!
        function devise_respond_to_and_will_save_change_to_attribute? (line 75) | def devise_respond_to_and_will_save_change_to_attribute?(attribute)

FILE: lib/devise/parameter_filter.rb
  type Devise (line 3) | module Devise
    class ParameterFilter (line 4) | class ParameterFilter
      method initialize (line 5) | def initialize(case_insensitive_keys, strip_whitespace_keys)
      method filter (line 10) | def filter(conditions)
      method filtered_hash_by_method_for_given_keys (line 19) | def filtered_hash_by_method_for_given_keys(conditions, method, condi...
      method stringify_params (line 31) | def stringify_params(conditions)
      method param_requires_string_conversion? (line 40) | def param_requires_string_conversion?(value)

FILE: lib/devise/parameter_sanitizer.rb
  type Devise (line 3) | module Devise
    class ParameterSanitizer (line 37) | class ParameterSanitizer
      method initialize (line 44) | def initialize(resource_class, resource_name, params)
      method sanitize (line 70) | def sanitize(action)
      method permit (line 110) | def permit(action, keys: nil, except: nil, &block)
      method cast_to_hash (line 132) | def cast_to_hash(params)
      method default_params (line 136) | def default_params
      method hashable_resource_params? (line 144) | def hashable_resource_params?
      method empty_params (line 148) | def empty_params
      method permit_keys (line 152) | def permit_keys(parameters, keys)
      method extract_auth_keys (line 156) | def extract_auth_keys(klass)
      method unknown_action! (line 162) | def unknown_action!(action)

FILE: lib/devise/rails.rb
  type Devise (line 6) | module Devise
    class Engine (line 7) | class Engine < ::Rails::Engine

FILE: lib/devise/rails/routes.rb
  type Devise (line 6) | module Devise
    type RouteSet (line 7) | module RouteSet
      function finalize! (line 8) | def finalize!
  type ActionDispatch::Routing (line 28) | module ActionDispatch::Routing
    class RouteSet (line 29) | class RouteSet #:nodoc:
    class Mapper (line 35) | class Mapper
      method devise_for (line 226) | def devise_for(*resources)
      method authenticate (line 289) | def authenticate(scope = nil, block = nil)
      method authenticated (line 313) | def authenticated(scope = nil, block = nil)
      method unauthenticated (line 330) | def unauthenticated(scope = nil)
      method devise_scope (line 362) | def devise_scope(scope)
      method devise_session (line 376) | def devise_session(mapping, controllers) #:nodoc:
      method devise_password (line 384) | def devise_password(mapping, controllers) #:nodoc:
      method devise_confirmation (line 389) | def devise_confirmation(mapping, controllers) #:nodoc:
      method devise_unlock (line 394) | def devise_unlock(mapping, controllers) #:nodoc:
      method devise_registration (line 401) | def devise_registration(mapping, controllers) #:nodoc:
      method devise_omniauth_callback (line 420) | def devise_omniauth_callback(mapping, controllers) #:nodoc:
      method with_devise_exclusive_scope (line 460) | def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
      method constraints_for (line 476) | def constraints_for(method_to_apply, scope = nil, block = nil)
      method set_omniauth_path_prefix! (line 487) | def set_omniauth_path_prefix!(path_prefix) #:nodoc:
      method raise_no_secret_key (line 498) | def raise_no_secret_key #:nodoc:
      method raise_no_devise_method_error! (line 508) | def raise_no_devise_method_error!(klass) #:nodoc:

FILE: lib/devise/rails/warden_compat.rb
  type Warden::Mixins::Common (line 3) | module Warden::Mixins::Common
    function request (line 4) | def request
    function reset_session! (line 8) | def reset_session!
    function cookies (line 12) | def cookies

FILE: lib/devise/strategies/authenticatable.rb
  type Devise (line 5) | module Devise
    type Strategies (line 6) | module Strategies
      class Authenticatable (line 10) | class Authenticatable < Base
        method store? (line 13) | def store?
        method valid? (line 17) | def valid?
        method clean_up_csrf? (line 24) | def clean_up_csrf?
        method validate (line 37) | def validate(resource, &block)
        method remember_me (line 51) | def remember_me(resource)
        method remember_me? (line 56) | def remember_me?
        method valid_for_http_auth? (line 66) | def valid_for_http_auth?
        method valid_for_params_auth? (line 77) | def valid_for_params_auth?
        method http_authenticatable? (line 83) | def http_authenticatable?
        method params_authenticatable? (line 88) | def params_authenticatable?
        method params_auth_hash (line 93) | def params_auth_hash
        method http_auth_hash (line 98) | def http_auth_hash
        method valid_params_request? (line 104) | def valid_params_request?
        method valid_params? (line 109) | def valid_params?
        method valid_password? (line 117) | def valid_password?
        method decode_credentials (line 122) | def decode_credentials
        method with_authentication_hash (line 128) | def with_authentication_hash(auth_type, auth_values)
        method authentication_keys (line 136) | def authentication_keys
        method http_authentication_key (line 140) | def http_authentication_key
        method request_keys (line 147) | def request_keys
        method request_values (line 151) | def request_values
        method parse_authentication_key_values (line 157) | def parse_authentication_key_values(hash, keys)
        method authenticatable_name (line 171) | def authenticatable_name

FILE: lib/devise/strategies/base.rb
  type Devise (line 3) | module Devise
    type Strategies (line 4) | module Strategies
      class Base (line 6) | class Base < ::Warden::Strategies::Base
        method store? (line 8) | def store?
        method mapping (line 13) | def mapping

FILE: lib/devise/strategies/database_authenticatable.rb
  type Devise (line 5) | module Devise
    type Strategies (line 6) | module Strategies
      class DatabaseAuthenticatable (line 8) | class DatabaseAuthenticatable < Authenticatable
        method authenticate! (line 9) | def authenticate!

FILE: lib/devise/strategies/rememberable.rb
  type Devise (line 5) | module Devise
    type Strategies (line 6) | module Strategies
      class Rememberable (line 11) | class Rememberable < Authenticatable
        method valid? (line 13) | def valid?
        method authenticate! (line 21) | def authenticate!
        method clean_up_csrf? (line 41) | def clean_up_csrf?
        method extend_remember_me? (line 47) | def extend_remember_me?(resource)
        method remember_me? (line 51) | def remember_me?
        method remember_key (line 55) | def remember_key
        method remember_cookie (line 59) | def remember_cookie

FILE: lib/devise/test/controller_helpers.rb
  type Devise (line 3) | module Devise
    type Test (line 4) | module Test
      type ControllerHelpers (line 26) | module ControllerHelpers
        function process (line 34) | def process(*)
        function setup_controller_for_warden (line 43) | def setup_controller_for_warden #:nodoc:
        function warden (line 48) | def warden #:nodoc:
        function sign_in (line 67) | def sign_in(resource, scope: nil)
        function sign_out (line 82) | def sign_out(resource_or_scope)
        function _catch_warden (line 93) | def _catch_warden(&block)
        function _process_unauthenticated (line 116) | def _process_unauthenticated(env, options = {})

FILE: lib/devise/test/integration_helpers.rb
  type Devise (line 3) | module Devise
    type Test (line 20) | module Test
      type IntegrationHelpers (line 21) | module IntegrationHelpers
        function included (line 22) | def self.included(base)
        function sign_in (line 37) | def sign_in(resource, scope: nil)
        function sign_out (line 46) | def sign_out(resource_or_scope)
        function setup_integration_for_devise (line 54) | def setup_integration_for_devise
        function teardown_integration_for_devise (line 58) | def teardown_integration_for_devise

FILE: lib/devise/time_inflector.rb
  type Devise (line 5) | module Devise
    class TimeInflector (line 6) | class TimeInflector

FILE: lib/devise/token_generator.rb
  type Devise (line 5) | module Devise
    class TokenGenerator (line 6) | class TokenGenerator
      method initialize (line 7) | def initialize(key_generator, digest = "SHA256")
      method digest (line 12) | def digest(klass, column, value)
      method generate (line 16) | def generate(klass, column)
      method key_for (line 28) | def key_for(column)

FILE: lib/devise/version.rb
  type Devise (line 3) | module Devise

FILE: lib/generators/active_record/devise_generator.rb
  type ActiveRecord (line 6) | module ActiveRecord
    type Generators (line 7) | module Generators
      class DeviseGenerator (line 8) | class DeviseGenerator < Base
        method copy_devise_migration (line 16) | def copy_devise_migration
        method generate_model (line 24) | def generate_model
        method inject_devise_content (line 28) | def inject_devise_content
        method migration_data (line 43) | def migration_data
        method ip_column (line 76) | def ip_column
        method inet? (line 81) | def inet?
        method rails61_and_up? (line 85) | def rails61_and_up?
        method postgresql? (line 89) | def postgresql?
        method ar_config (line 93) | def ar_config
        method migration_version (line 105) | def migration_version
        method primary_key_type (line 109) | def primary_key_type
        method primary_key_string (line 113) | def primary_key_string

FILE: lib/generators/devise/controllers_generator.rb
  type Devise (line 5) | module Devise
    type Generators (line 6) | module Generators
      class ControllersGenerator (line 7) | class ControllersGenerator < Rails::Generators::Base
        method create_controllers (line 32) | def create_controllers
        method show_readme (line 41) | def show_readme

FILE: lib/generators/devise/devise_generator.rb
  type Devise (line 5) | module Devise
    type Generators (line 6) | module Generators
      class DeviseGenerator (line 7) | class DeviseGenerator < Rails::Generators::NamedBase
        method add_devise_routes (line 20) | def add_devise_routes

FILE: lib/generators/devise/install_generator.rb
  type Devise (line 6) | module Devise
    type Generators (line 7) | module Generators
      class InstallGenerator (line 10) | class InstallGenerator < Rails::Generators::Base
        method copy_initializer (line 16) | def copy_initializer
        method copy_locale (line 33) | def copy_locale
        method show_readme (line 37) | def show_readme

FILE: lib/generators/devise/orm_helpers.rb
  type Devise (line 3) | module Devise
    type Generators (line 4) | module Generators
      type OrmHelpers (line 5) | module OrmHelpers
        function model_contents (line 6) | def model_contents
        function model_exists? (line 19) | def model_exists?
        function migration_exists? (line 23) | def migration_exists?(table_name)
        function migration_path (line 27) | def migration_path
        function model_path (line 31) | def model_path

FILE: lib/generators/devise/views_generator.rb
  type Devise (line 5) | module Devise
    type Generators (line 6) | module Generators
      type ViewPathTemplates (line 10) | module ViewPathTemplates #:nodoc:
        function copy_views (line 26) | def copy_views
        function view_directory (line 42) | def view_directory(name, _target_path = nil)
        function target_path (line 52) | def target_path
        function plural_scope (line 56) | def plural_scope
      class SharedViewsGenerator (line 61) | class SharedViewsGenerator < Rails::Generators::Base #:nodoc:
        method copy_views (line 68) | def copy_views
      class FormForGenerator (line 73) | class FormForGenerator < Rails::Generators::Base #:nodoc:
      class SimpleFormForGenerator (line 80) | class SimpleFormForGenerator < Rails::Generators::Base #:nodoc:
        method copy_views (line 86) | def copy_views
      class ErbGenerator (line 94) | class ErbGenerator < Rails::Generators::Base #:nodoc:
        method copy_views (line 100) | def copy_views
      class MarkerbGenerator (line 107) | class MarkerbGenerator < Rails::Generators::Base #:nodoc:
        method copy_views (line 113) | def copy_views
        method target_path (line 119) | def target_path
      class ViewsGenerator (line 124) | class ViewsGenerator < Rails::Generators::Base

FILE: lib/generators/mongoid/devise_generator.rb
  type Mongoid (line 6) | module Mongoid
    type Generators (line 7) | module Generators
      class DeviseGenerator (line 8) | class DeviseGenerator < Rails::Generators::NamedBase
        method generate_model (line 11) | def generate_model
        method inject_field_types (line 15) | def inject_field_types
        method inject_devise_content (line 19) | def inject_devise_content
        method migration_data (line 23) | def migration_data

FILE: lib/generators/templates/controllers/confirmations_controller.rb
  class ConfirmationsController (line 3) | class <%= @scope_prefix %>ConfirmationsController < Devise::Confirmation...

FILE: lib/generators/templates/controllers/omniauth_callbacks_controller.rb
  class OmniauthCallbacksController (line 3) | class <%= @scope_prefix %>OmniauthCallbacksController < Devise::Omniauth...

FILE: lib/generators/templates/controllers/passwords_controller.rb
  class PasswordsController (line 3) | class <%= @scope_prefix %>PasswordsController < Devise::PasswordsController

FILE: lib/generators/templates/controllers/registrations_controller.rb
  class RegistrationsController (line 3) | class <%= @scope_prefix %>RegistrationsController < Devise::Registration...

FILE: lib/generators/templates/controllers/sessions_controller.rb
  class SessionsController (line 3) | class <%= @scope_prefix %>SessionsController < Devise::SessionsController

FILE: lib/generators/templates/controllers/unlocks_controller.rb
  class UnlocksController (line 3) | class <%= @scope_prefix %>UnlocksController < Devise::UnlocksController

FILE: test/controllers/custom_registrations_controller_test.rb
  class CustomRegistrationsControllerTest (line 5) | class CustomRegistrationsControllerTest < Devise::ControllerTestCase

FILE: test/controllers/custom_strategy_test.rb
  class CustomStrategyController (line 8) | class CustomStrategyController < ActionController::Base
    method new (line 9) | def new
  class CustomStrategy (line 21) | class CustomStrategy < Warden::Strategies::Base
    method authenticate! (line 22) | def authenticate!
  class CustomStrategyTest (line 29) | class CustomStrategyTest < Devise::ControllerTestCase

FILE: test/controllers/helper_methods_test.rb
  class ApiController (line 5) | class ApiController < ActionController::Metal
  class HelperMethodsTest (line 9) | class HelperMethodsTest < Devise::ControllerTestCase

FILE: test/controllers/helpers_test.rb
  class ControllerAuthenticatableTest (line 6) | class ControllerAuthenticatableTest < Devise::ControllerTestCase
    method setup (line 9) | def setup

FILE: test/controllers/inherited_controller_i18n_messages_test.rb
  class SessionsInheritedController (line 5) | class SessionsInheritedController < Devise::SessionsController
    method test_i18n_scope (line 6) | def test_i18n_scope
  class AnotherInheritedController (line 11) | class AnotherInheritedController < SessionsInheritedController
    method translation_scope (line 14) | def translation_scope
  class InheritedControllerTest (line 19) | class InheritedControllerTest < Devise::ControllerTestCase
    method setup (line 22) | def setup
  class AnotherInheritedControllerTest (line 37) | class AnotherInheritedControllerTest < Devise::ControllerTestCase
    method setup (line 40) | def setup

FILE: test/controllers/internal_helpers_test.rb
  class MyController (line 5) | class MyController < DeviseController
  class HelpersTest (line 8) | class HelpersTest < Devise::ControllerTestCase
    method setup (line 11) | def setup

FILE: test/controllers/load_hooks_controller_test.rb
  class LoadHooksControllerTest (line 5) | class LoadHooksControllerTest < Devise::ControllerTestCase

FILE: test/controllers/passwords_controller_test.rb
  class PasswordsControllerTest (line 5) | class PasswordsControllerTest < Devise::ControllerTestCase
    method put_update_with_params (line 15) | def put_update_with_params

FILE: test/controllers/sessions_controller_test.rb
  class SessionsControllerTest (line 5) | class SessionsControllerTest < Devise::ControllerTestCase

FILE: test/controllers/url_helpers_test.rb
  class RoutesTest (line 5) | class RoutesTest < Devise::ControllerTestCase
    method assert_path_and_url (line 8) | def assert_path_and_url(name, prepend_path = nil)

FILE: test/delegator_test.rb
  class DelegatorTest (line 5) | class DelegatorTest < ActiveSupport::TestCase
    method delegator (line 6) | def delegator

FILE: test/devise_test.rb
  type Devise (line 5) | module Devise
    function yield_and_restore (line 6) | def self.yield_and_restore
  class DeviseTest (line 15) | class DeviseTest < ActiveSupport::TestCase

FILE: test/failure_app_test.rb
  class FailureTest (line 6) | class FailureTest < ActiveSupport::TestCase
    class RootFailureApp (line 7) | class RootFailureApp < Devise::FailureApp
      method fake_app (line 8) | def fake_app
    class FailureWithSubdomain (line 13) | class FailureWithSubdomain < RootFailureApp
    class FailureWithI18nOptions (line 25) | class FailureWithI18nOptions < Devise::FailureApp
      method i18n_options (line 26) | def i18n_options(options)
    class FailureWithoutRootPath (line 31) | class FailureWithoutRootPath < Devise::FailureApp
      class FakeURLHelpers (line 32) | class FakeURLHelpers
      class FakeRoutesWithoutRoot (line 35) | class FakeRoutesWithoutRoot
        method url_helpers (line 36) | def url_helpers
      class FakeAppWithoutRootPath (line 41) | class FakeAppWithoutRootPath
        method routes (line 42) | def routes
      method main_app (line 47) | def main_app
    class FakeEngineApp (line 52) | class FakeEngineApp < Devise::FailureApp
      class FakeEngine (line 53) | class FakeEngine
        method new_user_on_engine_session_url (line 54) | def new_user_on_engine_session_url _
      method main_app (line 59) | def main_app
      method fake_engine (line 63) | def fake_engine
    class RequestWithoutFlashSupport (line 68) | class RequestWithoutFlashSupport < ActionDispatch::Request
    method context (line 72) | def self.context(name, &block)
    method call_failure (line 76) | def call_failure(env_params = {})

FILE: test/generators/active_record_generator_test.rb
  class ActiveRecordGeneratorTest (line 8) | class ActiveRecordGeneratorTest < Rails::Generators::TestCase
  type RailsEngine (line 83) | module RailsEngine
    class Engine (line 84) | class Engine < Rails::Engine
  function simulate_inside_engine (line 89) | def simulate_inside_engine(engine, namespace)
  class ActiveRecordEngineGeneratorTest (line 101) | class ActiveRecordEngineGeneratorTest < Rails::Generators::TestCase

FILE: test/generators/controllers_generator_test.rb
  class ControllersGeneratorTest (line 5) | class ControllersGeneratorTest < Rails::Generators::TestCase
    method assert_class_names (line 40) | def assert_class_names(scope, options = {})

FILE: test/generators/devise_generator_test.rb
  class DeviseGeneratorTest (line 7) | class DeviseGeneratorTest < Rails::Generators::TestCase
    method copy_routes (line 33) | def copy_routes

FILE: test/generators/install_generator_test.rb
  class InstallGeneratorTest (line 5) | class InstallGeneratorTest < Rails::Generators::TestCase

FILE: test/generators/mongoid_generator_test.rb
  class MongoidGeneratorTest (line 8) | class MongoidGeneratorTest < Rails::Generators::TestCase

FILE: test/generators/views_generator_test.rb
  class ViewsGeneratorTest (line 5) | class ViewsGeneratorTest < Rails::Generators::TestCase
    method assert_files (line 80) | def assert_files(scope = nil, options = {})
    method assert_shared_links (line 98) | def assert_shared_links(scope = nil)
    method assert_error_messages (line 110) | def assert_error_messages(scope = nil)

FILE: test/helpers/devise_helper_test.rb
  class DeviseHelperTest (line 5) | class DeviseHelperTest < Devise::IntegrationTest

FILE: test/integration/authenticatable_test.rb
  class AuthenticationSanityTest (line 5) | class AuthenticationSanityTest < Devise::IntegrationTest
  class AuthenticationRoutesRestrictions (line 145) | class AuthenticationRoutesRestrictions < Devise::IntegrationTest
  class AuthenticationRedirectTest (line 265) | class AuthenticationRedirectTest < Devise::IntegrationTest
  class AuthenticationSessionTest (line 345) | class AuthenticationSessionTest < Devise::IntegrationTest
  class AuthenticationWithScopedViewsTest (line 391) | class AuthenticationWithScopedViewsTest < Devise::IntegrationTest
  class AuthenticationOthersTest (line 432) | class AuthenticationOthersTest < Devise::IntegrationTest
  class AuthenticationKeysTest (line 562) | class AuthenticationKeysTest < Devise::IntegrationTest
  class AuthenticationRequestKeysTest (line 579) | class AuthenticationRequestKeysTest < Devise::IntegrationTest
  class AuthenticationSignOutViaTest (line 620) | class AuthenticationSignOutViaTest < Devise::IntegrationTest
    method sign_in! (line 621) | def sign_in!(scope)
  class DoubleAuthenticationRedirectTest (line 675) | class DoubleAuthenticationRedirectTest < Devise::IntegrationTest
  class DoubleSignOutRedirectTest (line 698) | class DoubleSignOutRedirectTest < Devise::IntegrationTest

FILE: test/integration/confirmable_test.rb
  class ConfirmationTest (line 5) | class ConfirmationTest < Devise::IntegrationTest
    method visit_user_confirmation_with_token (line 7) | def visit_user_confirmation_with_token(confirmation_token)
    method resend_confirmation (line 11) | def resend_confirmation
  class ConfirmationOnChangeTest (line 285) | class ConfirmationOnChangeTest < Devise::IntegrationTest
    method create_second_admin (line 286) | def create_second_admin(options = {})
    method visit_admin_confirmation_with_token (line 291) | def visit_admin_confirmation_with_token(confirmation_token)

FILE: test/integration/database_authenticatable_test.rb
  class DatabaseAuthenticationTest (line 5) | class DatabaseAuthenticationTest < Devise::IntegrationTest

FILE: test/integration/http_authenticatable_test.rb
  class HttpAuthenticationTest (line 5) | class HttpAuthenticationTest < Devise::IntegrationTest
    method sign_in_as_new_user_with_http (line 102) | def sign_in_as_new_user_with_http(username = "user@test.com", password...
    method add_oauth2_header (line 109) | def add_oauth2_header

FILE: test/integration/lockable_test.rb
  class LockTest (line 5) | class LockTest < Devise::IntegrationTest
    method visit_user_unlock_with_token (line 7) | def visit_user_unlock_with_token(unlock_token)
    method send_unlock_request (line 11) | def send_unlock_request

FILE: test/integration/mounted_engine_test.rb
  type MyMountableEngine (line 5) | module MyMountableEngine
    class Engine (line 6) | class Engine < ::Rails::Engine
    class TestsController (line 9) | class TestsController < ActionController::Base
      method index (line 10) | def index
      method inner_route (line 13) | def inner_route
  class AuthenticatedMountedEngineTest (line 35) | class AuthenticatedMountedEngineTest < Devise::IntegrationTest

FILE: test/integration/omniauthable_test.rb
  class OmniauthableIntegrationTest (line 6) | class OmniauthableIntegrationTest < Devise::IntegrationTest
    method stub_action! (line 36) | def stub_action!(name)

FILE: test/integration/recoverable_test.rb
  class PasswordTest (line 5) | class PasswordTest < Devise::IntegrationTest
    method visit_new_password_path (line 7) | def visit_new_password_path
    method request_forgot_password (line 12) | def request_forgot_password(&block)
    method reset_password (line 24) | def reset_password(options = {}, &block)

FILE: test/integration/registerable_test.rb
  class RegistrationTest (line 5) | class RegistrationTest < Devise::IntegrationTest
    method user_sign_up (line 46) | def user_sign_up
  class ReconfirmableRegistrationTest (line 347) | class ReconfirmableRegistrationTest < Devise::IntegrationTest

FILE: test/integration/rememberable_test.rb
  class RememberMeTest (line 5) | class RememberMeTest < Devise::IntegrationTest
    method create_user_and_remember (line 6) | def create_user_and_remember(add_to_token = '')
    method generate_signed_cookie (line 14) | def generate_signed_cookie(raw_cookie)
    method signed_cookie (line 20) | def signed_cookie(key)
    method cookie_expires (line 24) | def cookie_expires(key)

FILE: test/integration/timeoutable_test.rb
  class SessionTimeoutTest (line 5) | class SessionTimeoutTest < Devise::IntegrationTest
    method last_request_at (line 7) | def last_request_at

FILE: test/integration/trackable_test.rb
  class TrackableHooksTest (line 5) | class TrackableHooksTest < Devise::IntegrationTest

FILE: test/mailers/confirmation_instructions_test.rb
  class ConfirmationInstructionsTest (line 5) | class ConfirmationInstructionsTest < ActionMailer::TestCase
    method setup (line 7) | def setup
    method teardown (line 13) | def teardown
    method user (line 18) | def user
    method mail (line 22) | def mail

FILE: test/mailers/email_changed_test.rb
  class EmailChangedTest (line 5) | class EmailChangedTest < ActionMailer::TestCase
    method setup (line 6) | def setup
    method teardown (line 13) | def teardown
    method user (line 19) | def user
    method mail (line 26) | def mail
  class EmailChangedReconfirmationTest (line 94) | class EmailChangedReconfirmationTest < ActionMailer::TestCase
    method setup (line 95) | def setup
    method teardown (line 102) | def teardown
    method admin (line 108) | def admin
    method mail (line 115) | def mail

FILE: test/mailers/mailer_test.rb
  class MailerTest (line 5) | class MailerTest < ActionMailer::TestCase
    class TestMailer (line 7) | class TestMailer < Devise::Mailer
      method confirmation_instructions (line 8) | def confirmation_instructions(record, token, opts = {})
    class TestMailerWithDefault (line 22) | class TestMailerWithDefault < Devise::Mailer
      method confirmation_instructions (line 26) | def confirmation_instructions(record, token, opts = {})
      method computed_from (line 33) | def computed_from
      method computed_reply_to (line 37) | def computed_reply_to

FILE: test/mailers/reset_password_instructions_test.rb
  class ResetPasswordInstructionsTest (line 5) | class ResetPasswordInstructionsTest < ActionMailer::TestCase
    method setup (line 6) | def setup
    method teardown (line 12) | def teardown
    method user (line 17) | def user
    method mail (line 25) | def mail

FILE: test/mailers/unlock_instructions_test.rb
  class UnlockInstructionsTest (line 5) | class UnlockInstructionsTest < ActionMailer::TestCase
    method setup (line 7) | def setup
    method teardown (line 13) | def teardown
    method user (line 18) | def user
    method mail (line 26) | def mail

FILE: test/mapping_test.rb
  class FakeRequest (line 5) | class FakeRequest < Struct.new(:path_info, :params)
  class MappingTest (line 8) | class MappingTest < ActiveSupport::TestCase
    method fake_request (line 9) | def fake_request(path, params = {})
    method devise_scope (line 78) | def user.devise_scope; :special_scope; end

FILE: test/models/authenticatable_test.rb
  class AuthenticatableTest (line 5) | class AuthenticatableTest < ActiveSupport::TestCase

FILE: test/models/confirmable_test.rb
  class ConfirmableTest (line 5) | class ConfirmableTest < ActiveSupport::TestCase
    method setup (line 7) | def setup
    method confirmation_required? (line 186) | def confirmation_required?; false end
    method confirmation_required? (line 288) | def confirmation_required?; false end
    method confirmation_required? (line 297) | def confirmation_required?; false end
    method confirm_user_by_token_with_confirmation_sent_at (line 321) | def confirm_user_by_token_with_confirmation_sent_at(confirmation_sent_at)
  class ReconfirmableTest (line 392) | class ReconfirmableTest < ActiveSupport::TestCase
    class Admin::WithSaveInCallback (line 545) | class Admin::WithSaveInCallback < Admin

FILE: test/models/database_authenticatable_test.rb
  class DatabaseAuthenticatableTest (line 7) | class DatabaseAuthenticatableTest < ActiveSupport::TestCase
    method setup (line 8) | def setup

FILE: test/models/lockable_test.rb
  class LockableTest (line 5) | class LockableTest < ActiveSupport::TestCase
    method setup (line 6) | def setup

FILE: test/models/omniauthable_test.rb
  class OmniauthableTest (line 5) | class OmniauthableTest < ActiveSupport::TestCase

FILE: test/models/recoverable_test.rb
  class RecoverableTest (line 5) | class RecoverableTest < ActiveSupport::TestCase
    method setup (line 7) | def setup

FILE: test/models/registerable_test.rb
  class RegisterableTest (line 5) | class RegisterableTest < ActiveSupport::TestCase

FILE: test/models/rememberable_test.rb
  class RememberableTest (line 5) | class RememberableTest < ActiveSupport::TestCase
    method resource_class (line 6) | def resource_class
    method create_resource (line 10) | def create_resource
    method remember_token (line 109) | def user_with_remember_token.remember_token; '123-token'; end
    method authenticatable_salt (line 113) | def user_with_salt.authenticatable_salt; '123-salt'; end
    method authenticatable_salt (line 119) | def user.authenticatable_salt; nil; end
    method authenticatable_salt (line 125) | def user.authenticatable_salt; ""; end

FILE: test/models/serializable_test.rb
  class SerializableTest (line 5) | class SerializableTest < ActiveSupport::TestCase
    method assert_key (line 34) | def assert_key(key, subject)
    method assert_no_key (line 38) | def assert_no_key(key, subject)
    method from_json (line 42) | def from_json(options = nil)

FILE: test/models/timeoutable_test.rb
  class TimeoutableTest (line 5) | class TimeoutableTest < ActiveSupport::TestCase
    method timeout_in (line 21) | def timeout_in; 10.minutes end
    method timeout_in (line 29) | def timeout_in; nil end

FILE: test/models/trackable_test.rb
  class TrackableTest (line 5) | class TrackableTest < ActiveSupport::TestCase
    class UserWithOverride (line 64) | class UserWithOverride < User
      method extract_ip_from (line 66) | def extract_ip_from(request)

FILE: test/models/validatable_test.rb
  class ValidatableTest (line 6) | class ValidatableTest < ActiveSupport::TestCase

FILE: test/models_test.rb
  class ActiveRecordTest (line 6) | class ActiveRecordTest < ActiveSupport::TestCase
    method include_module? (line 7) | def include_module?(klass, mod)
    method assert_include_modules (line 12) | def assert_include_modules(klass, *modules)
    method send_devise_notification (line 90) | def send_devise_notification(*); end
  type StubModelFilters (line 97) | module StubModelFilters
    function stub_filter (line 98) | def stub_filter(name)
  class CheckFieldsTest (line 103) | class CheckFieldsTest < ActiveSupport::TestCase

FILE: test/omniauth/config_test.rb
  class OmniAuthConfigTest (line 5) | class OmniAuthConfigTest < ActiveSupport::TestCase
    class MyStrategy (line 6) | class MyStrategy
    class NamedTestStrategy (line 30) | class NamedTestStrategy
    class UnNamedTestStrategy (line 40) | class UnNamedTestStrategy

FILE: test/omniauth/url_helpers_test.rb
  class OmniAuthRoutesTest (line 5) | class OmniAuthRoutesTest < ActionController::TestCase
    method assert_path (line 8) | def assert_path(action, provider, with_param = true)

FILE: test/orm/active_record.rb
  class ActiveSupport::TestCase (line 14) | class ActiveSupport::TestCase

FILE: test/orm/mongoid.rb
  class ActiveSupport::TestCase (line 11) | class ActiveSupport::TestCase

FILE: test/parameter_sanitizer_test.rb
  class ParameterSanitizerTest (line 6) | class ParameterSanitizerTest < ActiveSupport::TestCase
    method sanitizer (line 7) | def sanitizer(params)

FILE: test/rails_app/app/active_record/admin.rb
  class Admin (line 5) | class Admin < ActiveRecord::Base

FILE: test/rails_app/app/active_record/shim.rb
  type Shim (line 3) | module Shim

FILE: test/rails_app/app/active_record/user.rb
  class User (line 5) | class User < ActiveRecord::Base
    method after_validation_callback (line 15) | def after_validation_callback

FILE: test/rails_app/app/active_record/user_on_engine.rb
  class UserOnEngine (line 5) | class UserOnEngine < ActiveRecord::Base

FILE: test/rails_app/app/active_record/user_on_main_app.rb
  class UserOnMainApp (line 5) | class UserOnMainApp < ActiveRecord::Base

FILE: test/rails_app/app/active_record/user_with_validations.rb
  class UserWithValidations (line 5) | class UserWithValidations < ActiveRecord::Base

FILE: test/rails_app/app/active_record/user_without_email.rb
  class UserWithoutEmail (line 5) | class UserWithoutEmail < ActiveRecord::Base

FILE: test/rails_app/app/controllers/admins/sessions_controller.rb
  class Admins::SessionsController (line 3) | class Admins::SessionsController < Devise::SessionsController
    method new (line 4) | def new

FILE: test/rails_app/app/controllers/admins_controller.rb
  class AdminsController (line 3) | class AdminsController < ApplicationController
    method index (line 6) | def index

FILE: test/rails_app/app/controllers/application_controller.rb
  class ApplicationController (line 6) | class ApplicationController < ActionController::Base
    method set_locale (line 17) | def set_locale
    method default_url_options (line 21) | def default_url_options

FILE: test/rails_app/app/controllers/application_with_fake_engine.rb
  class ApplicationWithFakeEngine (line 3) | class ApplicationWithFakeEngine < ApplicationController
    method fake_engine (line 7) | def fake_engine
  class FakeEngine (line 12) | class FakeEngine
    method user_on_engine_confirmation_path (line 13) | def user_on_engine_confirmation_path
    method new_user_on_engine_session_path (line 17) | def new_user_on_engine_session_path
    method new_user_on_engine_registration_path (line 21) | def new_user_on_engine_registration_path
    method new_user_on_engine_password_path (line 25) | def new_user_on_engine_password_path
    method new_user_on_engine_unlock_path (line 29) | def new_user_on_engine_unlock_path

FILE: test/rails_app/app/controllers/custom/registrations_controller.rb
  class Custom::RegistrationsController (line 3) | class Custom::RegistrationsController < Devise::RegistrationsController
    method new (line 4) | def new
    method create (line 10) | def create
    method update (line 16) | def update
    method create_block_called? (line 22) | def create_block_called?
    method update_block_called? (line 26) | def update_block_called?
    method new_block_called? (line 30) | def new_block_called?

FILE: test/rails_app/app/controllers/home_controller.rb
  class HomeController (line 3) | class HomeController < ApplicationController
    method index (line 4) | def index
    method private (line 7) | def private
    method user_dashboard (line 10) | def user_dashboard
    method admin_dashboard (line 13) | def admin_dashboard
    method join (line 16) | def join
    method set (line 19) | def set
    method unauthenticated (line 24) | def unauthenticated

FILE: test/rails_app/app/controllers/publisher/registrations_controller.rb
  class Publisher::RegistrationsController (line 3) | class Publisher::RegistrationsController < ApplicationController

FILE: test/rails_app/app/controllers/publisher/sessions_controller.rb
  class Publisher::SessionsController (line 3) | class Publisher::SessionsController < ApplicationController

FILE: test/rails_app/app/controllers/streaming_controller.rb
  class StreamingController (line 3) | class StreamingController < ApplicationController
    method index (line 8) | def index

FILE: test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb
  class Users::OmniauthCallbacksController (line 3) | class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksCont...
    method facebook (line 4) | def facebook
    method sign_in_facebook (line 10) | def sign_in_facebook

FILE: test/rails_app/app/controllers/users_controller.rb
  class UsersController (line 3) | class UsersController < ApplicationController
    method index (line 9) | def index
    method edit_form (line 14) | def edit_form
    method update_form (line 18) | def update_form
    method accept (line 22) | def accept
    method exhibit (line 26) | def exhibit
    method expire (line 30) | def expire

FILE: test/rails_app/app/helpers/application_helper.rb
  type ApplicationHelper (line 4) | module ApplicationHelper

FILE: test/rails_app/app/mailers/users/from_proc_mailer.rb
  class Users::FromProcMailer (line 3) | class Users::FromProcMailer < Devise::Mailer

FILE: test/rails_app/app/mailers/users/mailer.rb
  class Users::Mailer (line 3) | class Users::Mailer < Devise::Mailer

FILE: test/rails_app/app/mailers/users/reply_to_mailer.rb
  class Users::ReplyToMailer (line 3) | class Users::ReplyToMailer < Devise::Mailer

FILE: test/rails_app/app/mongoid/admin.rb
  class Admin (line 5) | class Admin

FILE: test/rails_app/app/mongoid/shim.rb
  type Shim (line 3) | module Shim
    type ClassMethods (line 11) | module ClassMethods
      function order (line 12) | def order(attribute)
      function find_by_email (line 16) | def find_by_email(email)
    function == (line 22) | def ==(other)

FILE: test/rails_app/app/mongoid/user.rb
  class User (line 5) | class User
    method after_validation_callback (line 46) | def after_validation_callback

FILE: test/rails_app/app/mongoid/user_on_engine.rb
  class UserOnEngine (line 5) | class UserOnEngine

FILE: test/rails_app/app/mongoid/user_on_main_app.rb
  class UserOnMainApp (line 5) | class UserOnMainApp

FILE: test/rails_app/app/mongoid/user_with_validations.rb
  class UserWithValidations (line 5) | class UserWithValidations

FILE: test/rails_app/app/mongoid/user_without_email.rb
  class UserWithoutEmail (line 5) | class UserWithoutEmail

FILE: test/rails_app/config/application.rb
  type RailsApp (line 19) | module RailsApp
    class Application (line 20) | class Application < Rails::Application

FILE: test/rails_app/config/boot.rb
  type Devise (line 7) | module Devise
    type Test (line 8) | module Test
      function rails71_and_up? (line 11) | def self.rails71_and_up?
      function rails70_and_up? (line 15) | def self.rails70_and_up?
      function rails70? (line 19) | def self.rails70?

FILE: test/rails_app/db/migrate/20100401102949_create_tables.rb
  class CreateTables (line 3) | class CreateTables < ActiveRecord::Migration[5.0]
    method up (line 4) | def self.up
    method down (line 69) | def self.down

FILE: test/rails_app/lib/lazy_load_test_module.rb
  type LazyLoadTestModule (line 1) | module LazyLoadTestModule
    function lazy_loading_works? (line 2) | def lazy_loading_works?

FILE: test/rails_app/lib/shared_admin.rb
  type SharedAdmin (line 3) | module SharedAdmin
    function raw_confirmation_token (line 16) | def raw_confirmation_token

FILE: test/rails_app/lib/shared_user.rb
  type SharedUser (line 3) | module SharedUser
    function raw_confirmation_token (line 18) | def raw_confirmation_token
    type ExtendMethods (line 22) | module ExtendMethods
      function new_with_session (line 23) | def new_with_session(params, session)

FILE: test/rails_app/lib/shared_user_without_email.rb
  type SharedUserWithoutEmail (line 3) | module SharedUserWithoutEmail
    function email_changed? (line 20) | def email_changed?
    function respond_to? (line 24) | def respond_to?(method_name, include_all = false)

FILE: test/rails_app/lib/shared_user_without_omniauth.rb
  type SharedUserWithoutOmniauth (line 3) | module SharedUserWithoutOmniauth
    function raw_confirmation_token (line 12) | def raw_confirmation_token

FILE: test/rails_test.rb
  class RailsTest (line 5) | class RailsTest < ActiveSupport::TestCase

FILE: test/routes_test.rb
  class DefaultRoutingTest (line 7) | class DefaultRoutingTest < ActionController::TestCase
    method assert_named_route (line 115) | def assert_named_route(result, *args)
  class CustomizedRoutingTest (line 120) | class CustomizedRoutingTest < ActionController::TestCase
  class ScopedRoutingTest (line 266) | class ScopedRoutingTest < ActionController::TestCase

FILE: test/support/action_controller/record_identifier.rb
  type ActionController (line 9) | module ActionController

FILE: test/support/assertions.rb
  class ActiveSupport::TestCase (line 5) | class ActiveSupport::TestCase
    method assert_blank (line 6) | def assert_blank(assertion)
    method assert_present (line 10) | def assert_present(assertion)
    method assert_email_sent (line 14) | def assert_email_sent(address = nil, &block)
    method assert_email_not_sent (line 21) | def assert_email_not_sent(&block)
    method assert_raise_with_message (line 25) | def assert_raise_with_message(exception_klass, message, &block)

FILE: test/support/helpers.rb
  class ActiveSupport::TestCase (line 5) | class ActiveSupport::TestCase
    method setup_mailer (line 6) | def setup_mailer
    method store_translations (line 10) | def store_translations(locale, translations, &block)
    method generate_unique_email (line 22) | def generate_unique_email
    method valid_attributes (line 28) | def valid_attributes(attributes = {})
    method new_user (line 35) | def new_user(attributes = {})
    method create_user (line 39) | def create_user(attributes = {})
    method create_admin (line 43) | def create_admin(attributes = {})
    method create_user_without_email (line 49) | def create_user_without_email(attributes = {})
    method create_user_with_validations (line 53) | def create_user_with_validations(attributes = {})
    method swap (line 59) | def swap(object, new_values)
    method swap_model_config (line 74) | def swap_model_config(model, new_values)
    method clear_cached_variables (line 85) | def clear_cached_variables(options)

FILE: test/support/http_method_compatibility.rb
  type Devise (line 3) | module Devise
    class IntegrationTest (line 4) | class IntegrationTest < ActionDispatch::IntegrationTest
    class ControllerTestCase (line 7) | class ControllerTestCase < ActionController::TestCase

FILE: test/support/integration.rb
  class ActionDispatch::IntegrationTest (line 5) | class ActionDispatch::IntegrationTest
    method warden (line 6) | def warden
    method create_user (line 10) | def create_user(options = {})
    method create_admin (line 27) | def create_admin(options = {})
    method sign_in_as_user (line 39) | def sign_in_as_user(options = {}, &block)
    method sign_in_as_admin (line 50) | def sign_in_as_admin(options = {}, &block)
    method assert_redirected_to (line 63) | def assert_redirected_to(url)
    method assert_current_url (line 70) | def assert_current_url(expected)
    method assert_url (line 74) | def assert_url(expected, actual)
    method visit_with_option (line 80) | def visit_with_option(given, default)
    method prepend_host (line 91) | def prepend_host(url)

FILE: test/support/webrat/integrations/rails.rb
  type Webrat (line 6) | module Webrat
    function parse_rails_request_params (line 8) | def self.parse_rails_request_params(params)
    type Logging (line 13) | module Logging
      function logger (line 15) | def logger # :nodoc:
    class RailsAdapter (line 20) | class RailsAdapter
      method response (line 23) | def response
      method do_request (line 29) | def do_request(http_method, url, data, headers)
  type ActionDispatch (line 36) | module ActionDispatch #:nodoc:

FILE: test/support/webrat/matchers.rb
  type Webrat (line 2) | module Webrat
    type Matchers (line 3) | module Matchers
      class HaveSelector (line 4) | class HaveSelector
        method query (line 5) | def query

FILE: test/test/controller_helpers_test.rb
  class TestControllerHelpersTest (line 5) | class TestControllerHelpersTest < Devise::ControllerTestCase
    method redirect (line 72) | def redirect
    method respond (line 85) | def respond
  class TestControllerHelpersForStreamingControllerTest (line 195) | class TestControllerHelpersForStreamingControllerTest < Devise::Controll...

FILE: test/test/integration_helpers_test.rb
  class TestIntegrationsHelpersTest (line 5) | class TestIntegrationsHelpersTest < Devise::IntegrationTest

FILE: test/test_models.rb
  class Configurable (line 3) | class Configurable < User
  class WithValidation (line 9) | class WithValidation < Admin
  class UserWithValidation (line 13) | class UserWithValidation < User
  class UserWithCustomHashing (line 17) | class UserWithCustomHashing < User
    method password_digest (line 19) | def password_digest(password)
  class UserWithVirtualAttributes (line 24) | class UserWithVirtualAttributes < User
  class Several (line 29) | class Several < Admin
  class Inheritable (line 34) | class Inheritable < Admin
Condensed preview — 272 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (714K chars).
[
  {
    "path": ".devcontainer/devcontainer.json",
    "chars": 941,
    "preview": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the\n// README at: https://github.co"
  },
  {
    "path": ".github/code-scanning.yml",
    "chars": 26,
    "preview": "paths-ignore:\n  - test/**\n"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 118,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 1989,
    "preview": "name: Test\n\npermissions:\n  contents: read\non:\n  push:\n    branches:\n      - main\n  pull_request:\n  workflow_dispatch:\njo"
  },
  {
    "path": ".gitignore",
    "chars": 116,
    "preview": "test/rails_app/log/*\ntest/rails_app/tmp/*\n*~\ncoverage/*\n*.sqlite3\n.bundle\nrdoc/*\npkg\nlog\ntest/tmp/*\ngemfiles/*.lock\n"
  },
  {
    "path": ".yardopts",
    "chars": 108,
    "preview": "--protected\n--no-private\n--embed-mixin ClassMethods\n-\nREADME.md\nCHANGELOG.rdoc\nCONTRIBUTING.md\nMIT-LICENSE\n\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 7118,
    "preview": "### 5.0.3 - 2026-03-16\n\n* security fixes\n  * Fix race condition vulnerability on confirmable \"change email\" which would "
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 2037,
    "preview": "# Contributor Code of Conduct\n\nAs contributors and maintainers of this project, and in the interest of fostering an open"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 4324,
    "preview": "# How to contribute to Devise\n\nThanks for your interest on contributing to Devise! Here are a few general\nguidelines on "
  },
  {
    "path": "Gemfile",
    "chars": 536,
    "preview": "# frozen_string_literal: true\n\nsource \"https://rubygems.org\"\n\ngemspec\n\ngem \"omniauth\"\ngem \"omniauth-oauth2\"\ngem \"rails\","
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "chars": 645,
    "preview": "## Pre-check\n\n- Do not use the issues tracker for help or support, try Stack Overflow.\n- For bugs, do a quick search and"
  },
  {
    "path": "MIT-LICENSE",
    "chars": 1128,
    "preview": "Copyright (c) 2020-CURRENT Rafael França, Carlos Antonio da Silva\nCopyright (c) 2009-2019 Plataformatec\n\nPermission is h"
  },
  {
    "path": "README.md",
    "chars": 34760,
    "preview": "![Devise Logo](https://raw.github.com/heartcombo/devise/main/devise.png)\n\nDevise is a flexible authentication solution f"
  },
  {
    "path": "Rakefile",
    "chars": 1026,
    "preview": "# encoding: UTF-8\n# frozen_string_literal: true\n\nrequire 'bundler/gem_tasks'\nrequire 'rake/testtask'\nrequire 'rdoc/task'"
  },
  {
    "path": "app/controllers/devise/confirmations_controller.rb",
    "chars": 1675,
    "preview": "# frozen_string_literal: true\n\nclass Devise::ConfirmationsController < DeviseController\n  # GET /resource/confirmation/n"
  },
  {
    "path": "app/controllers/devise/omniauth_callbacks_controller.rb",
    "chars": 1235,
    "preview": "# frozen_string_literal: true\n\nclass Devise::OmniauthCallbacksController < DeviseController\n  prepend_before_action { re"
  },
  {
    "path": "app/controllers/devise/passwords_controller.rb",
    "chars": 2894,
    "preview": "# frozen_string_literal: true\n\nclass Devise::PasswordsController < DeviseController\n  prepend_before_action :require_no_"
  },
  {
    "path": "app/controllers/devise/registrations_controller.rb",
    "chars": 5613,
    "preview": "# frozen_string_literal: true\n\nclass Devise::RegistrationsController < DeviseController\n  prepend_before_action :require"
  },
  {
    "path": "app/controllers/devise/sessions_controller.rb",
    "chars": 2635,
    "preview": "# frozen_string_literal: true\n\nclass Devise::SessionsController < DeviseController\n  prepend_before_action :require_no_a"
  },
  {
    "path": "app/controllers/devise/unlocks_controller.rb",
    "chars": 1541,
    "preview": "# frozen_string_literal: true\n\nclass Devise::UnlocksController < DeviseController\n  prepend_before_action :require_no_au"
  },
  {
    "path": "app/controllers/devise_controller.rb",
    "chars": 6982,
    "preview": "# frozen_string_literal: true\n\n# All Devise controllers are inherited from here.\nclass DeviseController < Devise.parent_"
  },
  {
    "path": "app/helpers/devise_helper.rb",
    "chars": 111,
    "preview": "# frozen_string_literal: true\n\n# Keeping the helper around for backward compatibility.\nmodule DeviseHelper\nend\n"
  },
  {
    "path": "app/mailers/devise/mailer.rb",
    "chars": 804,
    "preview": "# frozen_string_literal: true\n\nif defined?(ActionMailer)\n  class Devise::Mailer < Devise.parent_mailer.constantize\n    i"
  },
  {
    "path": "app/views/devise/confirmations/new.html.erb",
    "chars": 595,
    "preview": "<h2>Resend confirmation instructions</h2>\n\n<%= form_for(resource, as: resource_name, url: confirmation_path(resource_nam"
  },
  {
    "path": "app/views/devise/mailer/confirmation_instructions.html.erb",
    "chars": 198,
    "preview": "<p>Welcome <%= @email %>!</p>\n\n<p>You can confirm your account email through the link below:</p>\n\n<p><%= link_to 'Confir"
  },
  {
    "path": "app/views/devise/mailer/email_changed.html.erb",
    "chars": 314,
    "preview": "<p>Hello <%= @email %>!</p>\n\n<% if @resource.try(:unconfirmed_email?) %>\n  <p>We're contacting you to notify you that yo"
  },
  {
    "path": "app/views/devise/mailer/password_change.html.erb",
    "chars": 117,
    "preview": "<p>Hello <%= @resource.email %>!</p>\n\n<p>We're contacting you to notify you that your password has been changed.</p>\n"
  },
  {
    "path": "app/views/devise/mailer/reset_password_instructions.html.erb",
    "chars": 393,
    "preview": "<p>Hello <%= @resource.email %>!</p>\n\n<p>Someone has requested a link to change your password. You can do this through t"
  },
  {
    "path": "app/views/devise/mailer/unlock_instructions.html.erb",
    "chars": 276,
    "preview": "<p>Hello <%= @resource.email %>!</p>\n\n<p>Your account has been locked due to an excessive number of unsuccessful sign in"
  },
  {
    "path": "app/views/devise/passwords/edit.html.erb",
    "chars": 873,
    "preview": "<h2>Change your password</h2>\n\n<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { meth"
  },
  {
    "path": "app/views/devise/passwords/new.html.erb",
    "chars": 494,
    "preview": "<h2>Forgot your password?</h2>\n\n<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { met"
  },
  {
    "path": "app/views/devise/registrations/edit.html.erb",
    "chars": 1572,
    "preview": "<h2>Edit <%= resource_name.to_s.humanize %></h2>\n\n<%= form_for(resource, as: resource_name, url: registration_path(resou"
  },
  {
    "path": "app/views/devise/registrations/new.html.erb",
    "chars": 870,
    "preview": "<h2>Sign up</h2>\n\n<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>\n  <%= rende"
  },
  {
    "path": "app/views/devise/sessions/new.html.erb",
    "chars": 677,
    "preview": "<h2>Log in</h2>\n\n<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>\n  <div class=\"fie"
  },
  {
    "path": "app/views/devise/shared/_error_messages.html.erb",
    "chars": 419,
    "preview": "<% if resource.errors.any? %>\n  <div id=\"error_explanation\" data-turbo-temporary>\n    <h2>\n      <%= I18n.t(\"errors.mess"
  },
  {
    "path": "app/views/devise/shared/_links.html.erb",
    "chars": 1174,
    "preview": "<%- if controller_name != 'sessions' %>\n  <p><%= link_to \"Log in\", new_session_path(resource_name) %></p>\n<% end %>\n\n<%-"
  },
  {
    "path": "app/views/devise/unlocks/new.html.erb",
    "chars": 488,
    "preview": "<h2>Resend unlock instructions</h2>\n\n<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { "
  },
  {
    "path": "bin/test",
    "chars": 347,
    "preview": "#!/usr/bin/env ruby\n$: << File.expand_path(File.expand_path('../../test', __FILE__))\n\nrequire 'bundler/setup'\nrequire 'r"
  },
  {
    "path": "config/locales/en.yml",
    "chars": 4283,
    "preview": "# Additional translations at https://github.com/heartcombo/devise/wiki/I18n\n\nen:\n  devise:\n    confirmations:\n      conf"
  },
  {
    "path": "devise.gemspec",
    "chars": 1423,
    "preview": "# -*- encoding: utf-8 -*-\n# frozen_string_literal: true\n\n$:.push File.expand_path(\"../lib\", __FILE__)\nrequire \"devise/ve"
  },
  {
    "path": "gemfiles/Gemfile-rails-7-0",
    "chars": 502,
    "preview": "source \"https://rubygems.org\"\n\ngemspec path: \"..\"\n\ngem \"rails\", \"~> 7.0.0\"\ngem \"omniauth\"\ngem \"omniauth-oauth2\"\ngem \"rdo"
  },
  {
    "path": "gemfiles/Gemfile-rails-7-1",
    "chars": 477,
    "preview": "source \"https://rubygems.org\"\n\ngemspec path: \"..\"\n\ngem \"rails\", \"~> 7.1.0\"\ngem \"omniauth\"\ngem \"omniauth-oauth2\"\ngem \"rdo"
  },
  {
    "path": "gemfiles/Gemfile-rails-7-2",
    "chars": 483,
    "preview": "source \"https://rubygems.org\"\n\ngemspec path: \"..\"\n\ngem \"rails\", \"~> 7.2.0\"\ngem \"omniauth\"\ngem \"omniauth-oauth2\"\ngem \"rdo"
  },
  {
    "path": "gemfiles/Gemfile-rails-8-0",
    "chars": 467,
    "preview": "source \"https://rubygems.org\"\n\ngemspec path: \"..\"\n\ngem \"rails\", \"~> 8.0.0\"\ngem \"omniauth\"\ngem \"omniauth-oauth2\"\ngem \"rdo"
  },
  {
    "path": "gemfiles/Gemfile-rails-main",
    "chars": 554,
    "preview": "source \"https://rubygems.org\"\n\ngemspec path: \"..\"\n\ngem \"rails\", github: \"rails/rails\", branch: \"main\"\ngem \"omniauth\"\ngem"
  },
  {
    "path": "guides/bug_report_templates/integration_test.rb",
    "chars": 2243,
    "preview": "# frozen_string_literal: true\n\nbegin\n  require 'bundler/inline'\nrescue LoadError => e\n  $stderr.puts 'Bundler version 1."
  },
  {
    "path": "lib/devise/controllers/helpers.rb",
    "chars": 11705,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Controllers\n    # Those helpers are convenience methods added to A"
  },
  {
    "path": "lib/devise/controllers/rememberable.rb",
    "chars": 1956,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Controllers\n    # A module that may be optionally included in a co"
  },
  {
    "path": "lib/devise/controllers/responder.rb",
    "chars": 1375,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Controllers\n    # Custom Responder to configure default statuses t"
  },
  {
    "path": "lib/devise/controllers/scoped_views.rb",
    "chars": 368,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Controllers\n    module ScopedViews\n      extend ActiveSupport::Con"
  },
  {
    "path": "lib/devise/controllers/sign_in_out.rb",
    "chars": 4251,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Controllers\n    # Provide sign in and sign out functionality.\n    "
  },
  {
    "path": "lib/devise/controllers/store_location.rb",
    "chars": 2090,
    "preview": "# frozen_string_literal: true\n\nrequire \"uri\"\n\nmodule Devise\n  module Controllers\n    # Provide the ability to store a lo"
  },
  {
    "path": "lib/devise/controllers/url_helpers.rb",
    "chars": 2493,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Controllers\n    # Create url helpers to be used with resource/scop"
  },
  {
    "path": "lib/devise/delegator.rb",
    "chars": 423,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  # Checks the scope in the given environment and returns the associated fa"
  },
  {
    "path": "lib/devise/encryptor.rb",
    "chars": 675,
    "preview": "# frozen_string_literal: true\n\nrequire 'bcrypt'\n\nmodule Devise\n  module Encryptor\n    def self.digest(klass, password)\n "
  },
  {
    "path": "lib/devise/failure_app.rb",
    "chars": 8619,
    "preview": "# frozen_string_literal: true\n\nrequire \"action_controller/metal\"\n\nmodule Devise\n  # Failure application that will be cal"
  },
  {
    "path": "lib/devise/hooks/activatable.rb",
    "chars": 565,
    "preview": "# frozen_string_literal: true\n\n# Deny user access whenever their account is not active yet.\n# We need this as hook to va"
  },
  {
    "path": "lib/devise/hooks/csrf_cleaner.rb",
    "chars": 507,
    "preview": "# frozen_string_literal: true\n\nWarden::Manager.after_authentication do |record, warden, options|\n  clean_up_for_winning_"
  },
  {
    "path": "lib/devise/hooks/forgetable.rb",
    "chars": 464,
    "preview": "# frozen_string_literal: true\n\n# Before logout hook to forget the user in the given scope, if it responds\n# to forget_me"
  },
  {
    "path": "lib/devise/hooks/lockable.rb",
    "chars": 390,
    "preview": "# frozen_string_literal: true\n\n# After each sign in, if resource responds to failed_attempts, sets it to 0\n# This is onl"
  },
  {
    "path": "lib/devise/hooks/proxy.rb",
    "chars": 486,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Hooks\n    # A small warden proxy so we can remember, forget and\n  "
  },
  {
    "path": "lib/devise/hooks/rememberable.rb",
    "chars": 324,
    "preview": "# frozen_string_literal: true\n\nWarden::Manager.after_set_user except: :fetch do |record, warden, options|\n  scope = opti"
  },
  {
    "path": "lib/devise/hooks/timeoutable.rb",
    "chars": 1375,
    "preview": "# frozen_string_literal: true\n\n# Each time a record is set we check whether its session has already timed out\n# or not, "
  },
  {
    "path": "lib/devise/hooks/trackable.rb",
    "chars": 541,
    "preview": "# frozen_string_literal: true\n\n# After each sign in, update sign in time, sign in count and sign in IP.\n# This is only t"
  },
  {
    "path": "lib/devise/mailers/helpers.rb",
    "chars": 2376,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Mailers\n    module Helpers\n      extend ActiveSupport::Concern\n\n  "
  },
  {
    "path": "lib/devise/mapping.rb",
    "chars": 5519,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  # Responsible for handling devise mappings and routes configuration. Each"
  },
  {
    "path": "lib/devise/models/authenticatable.rb",
    "chars": 12220,
    "preview": "# frozen_string_literal: true\n\nrequire 'devise/hooks/activatable'\nrequire 'devise/hooks/csrf_cleaner'\n\nmodule Devise\n  m"
  },
  {
    "path": "lib/devise/models/confirmable.rb",
    "chars": 16029,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Models\n    # Confirmable is responsible to verify if an account is"
  },
  {
    "path": "lib/devise/models/database_authenticatable.rb",
    "chars": 7039,
    "preview": "# frozen_string_literal: true\n\nrequire 'devise/strategies/database_authenticatable'\n\nmodule Devise\n  module Models\n    #"
  },
  {
    "path": "lib/devise/models/lockable.rb",
    "chars": 7800,
    "preview": "# frozen_string_literal: true\n\nrequire \"devise/hooks/lockable\"\n\nmodule Devise\n  module Models\n    # Handles blocking a u"
  },
  {
    "path": "lib/devise/models/omniauthable.rb",
    "chars": 656,
    "preview": "# frozen_string_literal: true\n\nrequire 'devise/omniauth'\n\nmodule Devise\n  module Models\n    # Adds OmniAuth support to y"
  },
  {
    "path": "lib/devise/models/recoverable.rb",
    "chars": 6400,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Models\n\n    # Recoverable takes care of resetting the user passwor"
  },
  {
    "path": "lib/devise/models/registerable.rb",
    "chars": 825,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Models\n    # Registerable is responsible for everything related to"
  },
  {
    "path": "lib/devise/models/rememberable.rb",
    "chars": 5632,
    "preview": "# frozen_string_literal: true\n\nrequire 'devise/strategies/rememberable'\nrequire 'devise/hooks/rememberable'\nrequire 'dev"
  },
  {
    "path": "lib/devise/models/timeoutable.rb",
    "chars": 1105,
    "preview": "# frozen_string_literal: true\n\nrequire 'devise/hooks/timeoutable'\n\nmodule Devise\n  module Models\n    # Timeoutable takes"
  },
  {
    "path": "lib/devise/models/trackable.rb",
    "chars": 1727,
    "preview": "# frozen_string_literal: true\n\nrequire 'devise/hooks/trackable'\n\nmodule Devise\n  module Models\n    # Track information a"
  },
  {
    "path": "lib/devise/models/validatable.rb",
    "chars": 2666,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Models\n    # Validatable creates all needed validations for a user"
  },
  {
    "path": "lib/devise/models.rb",
    "chars": 3579,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Models\n    class MissingAttribute < StandardError\n      def initia"
  },
  {
    "path": "lib/devise/modules.rb",
    "chars": 1107,
    "preview": "# frozen_string_literal: true\n\nrequire 'active_support/core_ext/object/with_options'\n\nDevise.with_options model: true do"
  },
  {
    "path": "lib/devise/omniauth/config.rb",
    "chars": 1413,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module OmniAuth\n    class StrategyNotFound < NameError\n      def initiali"
  },
  {
    "path": "lib/devise/omniauth/url_helpers.rb",
    "chars": 1030,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module OmniAuth\n    module UrlHelpers\n      def omniauth_authorize_path(r"
  },
  {
    "path": "lib/devise/omniauth.rb",
    "chars": 883,
    "preview": "# frozen_string_literal: true\n\nbegin\n  gem \"omniauth\", \">= 1.0.0\"\n\n  require \"omniauth\"\nrescue LoadError\n  warn \"Could n"
  },
  {
    "path": "lib/devise/orm/active_record.rb",
    "chars": 146,
    "preview": "# frozen_string_literal: true\n\nrequire 'orm_adapter/adapters/active_record'\n\nActiveSupport.on_load(:active_record) do\n  "
  },
  {
    "path": "lib/devise/orm/mongoid.rb",
    "chars": 176,
    "preview": "# frozen_string_literal: true\n\nActiveSupport.on_load(:mongoid) do\n  require 'orm_adapter/adapters/mongoid'\n\n  Mongoid::D"
  },
  {
    "path": "lib/devise/orm.rb",
    "chars": 2286,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Orm # :nodoc:\n    def self.active_record?(model)\n      defined?(Ac"
  },
  {
    "path": "lib/devise/parameter_filter.rb",
    "chars": 1272,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  class ParameterFilter\n    def initialize(case_insensitive_keys, strip_whi"
  },
  {
    "path": "lib/devise/parameter_sanitizer.rb",
    "chars": 5606,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  # The +ParameterSanitizer+ deals with permitting specific parameters valu"
  },
  {
    "path": "lib/devise/rails/routes.rb",
    "chars": 20127,
    "preview": "# frozen_string_literal: true\n\nrequire \"active_support/core_ext/object/try\"\nrequire \"active_support/core_ext/hash/slice\""
  },
  {
    "path": "lib/devise/rails/warden_compat.rb",
    "chars": 233,
    "preview": "# frozen_string_literal: true\n\nmodule Warden::Mixins::Common\n  def request\n    @request ||= ActionDispatch::Request.new("
  },
  {
    "path": "lib/devise/rails.rb",
    "chars": 1698,
    "preview": "# frozen_string_literal: true\n\nrequire 'devise/rails/routes'\nrequire 'devise/rails/warden_compat'\n\nmodule Devise\n  class"
  },
  {
    "path": "lib/devise/strategies/authenticatable.rb",
    "chars": 6241,
    "preview": "# frozen_string_literal: true\n\nrequire 'devise/strategies/base'\n\nmodule Devise\n  module Strategies\n    # This strategy s"
  },
  {
    "path": "lib/devise/strategies/base.rb",
    "chars": 638,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Strategies\n    # Base strategy for Devise. Responsible for verifyi"
  },
  {
    "path": "lib/devise/strategies/database_authenticatable.rb",
    "chars": 1234,
    "preview": "# frozen_string_literal: true\n\nrequire 'devise/strategies/authenticatable'\n\nmodule Devise\n  module Strategies\n    # Defa"
  },
  {
    "path": "lib/devise/strategies/rememberable.rb",
    "chars": 1973,
    "preview": "# frozen_string_literal: true\n\nrequire 'devise/strategies/authenticatable'\n\nmodule Devise\n  module Strategies\n    # Reme"
  },
  {
    "path": "lib/devise/test/controller_helpers.rb",
    "chars": 5312,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Test\n    # `Devise::Test::ControllerHelpers` provides a facility t"
  },
  {
    "path": "lib/devise/test/integration_helpers.rb",
    "chars": 1733,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  # Devise::Test::IntegrationHelpers is a helper module for facilitating\n  "
  },
  {
    "path": "lib/devise/time_inflector.rb",
    "chars": 299,
    "preview": "# frozen_string_literal: true\n\nrequire \"active_support/core_ext/module/delegation\"\n\nmodule Devise\n  class TimeInflector\n"
  },
  {
    "path": "lib/devise/token_generator.rb",
    "chars": 716,
    "preview": "# frozen_string_literal: true\n\nrequire 'openssl'\n\nmodule Devise\n  class TokenGenerator\n    def initialize(key_generator,"
  },
  {
    "path": "lib/devise/version.rb",
    "chars": 76,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  VERSION = \"5.0.3\".freeze\nend\n"
  },
  {
    "path": "lib/devise.rb",
    "chars": 17661,
    "preview": "# frozen_string_literal: true\n\nrequire 'rails'\nrequire 'active_support/core_ext/numeric/time'\nrequire 'active_support/de"
  },
  {
    "path": "lib/generators/active_record/devise_generator.rb",
    "chars": 3726,
    "preview": "# frozen_string_literal: true\n\nrequire 'rails/generators/active_record'\nrequire 'generators/devise/orm_helpers'\n\nmodule "
  },
  {
    "path": "lib/generators/active_record/templates/migration.rb",
    "chars": 666,
    "preview": "# frozen_string_literal: true\n\nclass DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_versi"
  },
  {
    "path": "lib/generators/active_record/templates/migration_existing.rb",
    "chars": 998,
    "preview": "# frozen_string_literal: true\n\nclass AddDeviseTo<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_versio"
  },
  {
    "path": "lib/generators/devise/controllers_generator.rb",
    "chars": 1579,
    "preview": "# frozen_string_literal: true\n\nrequire 'rails/generators/base'\n\nmodule Devise\n  module Generators\n    class ControllersG"
  },
  {
    "path": "lib/generators/devise/devise_generator.rb",
    "chars": 869,
    "preview": "# frozen_string_literal: true\n\nrequire 'rails/generators/named_base'\n\nmodule Devise\n  module Generators\n    class Devise"
  },
  {
    "path": "lib/generators/devise/install_generator.rb",
    "chars": 1137,
    "preview": "# frozen_string_literal: true\n\nrequire 'rails/generators/base'\nrequire 'securerandom'\n\nmodule Devise\n  module Generators"
  },
  {
    "path": "lib/generators/devise/orm_helpers.rb",
    "chars": 877,
    "preview": "# frozen_string_literal: true\n\nmodule Devise\n  module Generators\n    module OrmHelpers\n      def model_contents\n        "
  },
  {
    "path": "lib/generators/devise/views_generator.rb",
    "chars": 4491,
    "preview": "# frozen_string_literal: true\n\nrequire 'rails/generators/base'\n\nmodule Devise\n  module Generators\n    # Include this mod"
  },
  {
    "path": "lib/generators/mongoid/devise_generator.rb",
    "chars": 1748,
    "preview": "# frozen_string_literal: true\n\nrequire 'rails/generators/named_base'\nrequire 'generators/devise/orm_helpers'\n\nmodule Mon"
  },
  {
    "path": "lib/generators/templates/README",
    "chars": 1210,
    "preview": "===============================================================================\n\nDepending on your application's configu"
  },
  {
    "path": "lib/generators/templates/controllers/README",
    "chars": 440,
    "preview": "===============================================================================\n\nSome setup you must do manually if you "
  },
  {
    "path": "lib/generators/templates/controllers/confirmations_controller.rb",
    "chars": 676,
    "preview": "# frozen_string_literal: true\n\nclass <%= @scope_prefix %>ConfirmationsController < Devise::ConfirmationsController\n  # G"
  },
  {
    "path": "lib/generators/templates/controllers/omniauth_callbacks_controller.rb",
    "chars": 680,
    "preview": "# frozen_string_literal: true\n\nclass <%= @scope_prefix %>OmniauthCallbacksController < Devise::OmniauthCallbacksControll"
  },
  {
    "path": "lib/generators/templates/controllers/passwords_controller.rb",
    "chars": 663,
    "preview": "# frozen_string_literal: true\n\nclass <%= @scope_prefix %>PasswordsController < Devise::PasswordsController\n  # GET /reso"
  },
  {
    "path": "lib/generators/templates/controllers/registrations_controller.rb",
    "chars": 1450,
    "preview": "# frozen_string_literal: true\n\nclass <%= @scope_prefix %>RegistrationsController < Devise::RegistrationsController\n  # b"
  },
  {
    "path": "lib/generators/templates/controllers/sessions_controller.rb",
    "chars": 556,
    "preview": "# frozen_string_literal: true\n\nclass <%= @scope_prefix %>SessionsController < Devise::SessionsController\n  # before_acti"
  },
  {
    "path": "lib/generators/templates/controllers/unlocks_controller.rb",
    "chars": 595,
    "preview": "# frozen_string_literal: true\n\nclass <%= @scope_prefix %>UnlocksController < Devise::UnlocksController\n  # GET /resource"
  },
  {
    "path": "lib/generators/templates/devise.rb",
    "chars": 15538,
    "preview": "# frozen_string_literal: true\n\n# Assuming you have not yet modified this file, each configuration option below\n# is set "
  },
  {
    "path": "lib/generators/templates/markerb/confirmation_instructions.markerb",
    "chars": 163,
    "preview": "Welcome <%= @email %>!\n\nYou can confirm your account through the link below:\n\n[Confirm my account](<%= confirmation_url("
  },
  {
    "path": "lib/generators/templates/markerb/email_changed.markerb",
    "chars": 289,
    "preview": "Hello <%= @email %>!\n\n<% if @resource.try(:unconfirmed_email?) %>\nWe're contacting you to notify you that your email is "
  },
  {
    "path": "lib/generators/templates/markerb/password_change.markerb",
    "chars": 103,
    "preview": "Hello <%= @resource.email %>!\n\nWe're contacting you to notify you that your password has been changed.\n"
  },
  {
    "path": "lib/generators/templates/markerb/reset_password_instructions.markerb",
    "chars": 354,
    "preview": "Hello <%= @resource.email %>!\n\nSomeone has requested a link to change your password, and you can do this through the lin"
  },
  {
    "path": "lib/generators/templates/markerb/unlock_instructions.markerb",
    "chars": 240,
    "preview": "Hello <%= @resource.email %>!\n\nYour account has been locked due to an excessive number of unsuccessful sign in attempts."
  },
  {
    "path": "lib/generators/templates/simple_form_for/confirmations/new.html.erb",
    "chars": 677,
    "preview": "<h2>Resend confirmation instructions</h2>\n\n<%= simple_form_for(resource, as: resource_name, url: confirmation_path(resou"
  },
  {
    "path": "lib/generators/templates/simple_form_for/passwords/edit.html.erb",
    "chars": 935,
    "preview": "<h2>Change your password</h2>\n\n<%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html:"
  },
  {
    "path": "lib/generators/templates/simple_form_for/passwords/new.html.erb",
    "chars": 518,
    "preview": "<h2>Forgot your password?</h2>\n\n<%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html"
  },
  {
    "path": "lib/generators/templates/simple_form_for/registrations/edit.html.erb",
    "chars": 1343,
    "preview": "<h2>Edit <%= resource_name.to_s.humanize %></h2>\n\n<%= simple_form_for(resource, as: resource_name, url: registration_pat"
  },
  {
    "path": "lib/generators/templates/simple_form_for/registrations/new.html.erb",
    "chars": 815,
    "preview": "<h2>Sign up</h2>\n\n<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>\n  <%"
  },
  {
    "path": "lib/generators/templates/simple_form_for/sessions/new.html.erb",
    "chars": 624,
    "preview": "<h2>Log in</h2>\n\n<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>\n  <div cla"
  },
  {
    "path": "lib/generators/templates/simple_form_for/unlocks/new.html.erb",
    "chars": 548,
    "preview": "<h2>Resend unlock instructions</h2>\n\n<%= simple_form_for(resource, as: resource_name, url: unlock_path(resource_name), h"
  },
  {
    "path": "test/controllers/custom_registrations_controller_test.rb",
    "chars": 1499,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass CustomRegistrationsControllerTest < Devise::ControllerTestCa"
  },
  {
    "path": "test/controllers/custom_strategy_test.rb",
    "chars": 1885,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\nrequire 'ostruct'\nrequire 'warden/strategies/base'\nrequire 'devise/"
  },
  {
    "path": "test/controllers/helper_methods_test.rb",
    "chars": 636,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass ApiController < ActionController::Metal\n  include Devise::Co"
  },
  {
    "path": "test/controllers/helpers_test.rb",
    "chars": 12828,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\nrequire 'ostruct'\n\nclass ControllerAuthenticatableTest < Devise::Co"
  },
  {
    "path": "test/controllers/inherited_controller_i18n_messages_test.rb",
    "chars": 1318,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass SessionsInheritedController < Devise::SessionsController\n  d"
  },
  {
    "path": "test/controllers/internal_helpers_test.rb",
    "chars": 4738,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass MyController < DeviseController\nend\n\nclass HelpersTest < Dev"
  },
  {
    "path": "test/controllers/load_hooks_controller_test.rb",
    "chars": 537,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass LoadHooksControllerTest < Devise::ControllerTestCase\n  setup"
  },
  {
    "path": "test/controllers/passwords_controller_test.rb",
    "chars": 1250,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass PasswordsControllerTest < Devise::ControllerTestCase\n  tests"
  },
  {
    "path": "test/controllers/sessions_controller_test.rb",
    "chars": 3339,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass SessionsControllerTest < Devise::ControllerTestCase\n  tests "
  },
  {
    "path": "test/controllers/url_helpers_test.rb",
    "chars": 2401,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass RoutesTest < Devise::ControllerTestCase\n  tests ApplicationC"
  },
  {
    "path": "test/delegator_test.rb",
    "chars": 661,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass DelegatorTest < ActiveSupport::TestCase\n  def delegator\n    "
  },
  {
    "path": "test/devise_test.rb",
    "chars": 3507,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nmodule Devise\n  def self.yield_and_restore\n    @@warden_configured"
  },
  {
    "path": "test/failure_app_test.rb",
    "chars": 18642,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\nrequire 'ostruct'\n\nclass FailureTest < ActiveSupport::TestCase\n  cl"
  },
  {
    "path": "test/generators/active_record_generator_test.rb",
    "chars": 4206,
    "preview": "# frozen_string_literal: true\n\nrequire \"test_helper\"\n\nif DEVISE_ORM == :active_record\n  require \"generators/active_recor"
  },
  {
    "path": "test/generators/controllers_generator_test.rb",
    "chars": 1912,
    "preview": "# frozen_string_literal: true\n\nrequire \"test_helper\"\n\nclass ControllersGeneratorTest < Rails::Generators::TestCase\n  tes"
  },
  {
    "path": "test/generators/devise_generator_test.rb",
    "chars": 1123,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nrequire \"generators/devise/devise_generator\"\n\nclass DeviseGenerato"
  },
  {
    "path": "test/generators/install_generator_test.rb",
    "chars": 1055,
    "preview": "# frozen_string_literal: true\n\nrequire \"test_helper\"\n\nclass InstallGeneratorTest < Rails::Generators::TestCase\n  tests D"
  },
  {
    "path": "test/generators/mongoid_generator_test.rb",
    "chars": 653,
    "preview": "# frozen_string_literal: true\n\nrequire \"test_helper\"\n\nif DEVISE_ORM == :mongoid\n  require \"generators/mongoid/devise_gen"
  },
  {
    "path": "test/generators/views_generator_test.rb",
    "chars": 4892,
    "preview": "# frozen_string_literal: true\n\nrequire \"test_helper\"\n\nclass ViewsGeneratorTest < Rails::Generators::TestCase\n  tests Dev"
  },
  {
    "path": "test/helpers/devise_helper_test.rb",
    "chars": 1311,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass DeviseHelperTest < Devise::IntegrationTest\n  setup do\n    mo"
  },
  {
    "path": "test/integration/authenticatable_test.rb",
    "chars": 21739,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass AuthenticationSanityTest < Devise::IntegrationTest\n  test 's"
  },
  {
    "path": "test/integration/confirmable_test.rb",
    "chars": 14951,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass ConfirmationTest < Devise::IntegrationTest\n\n  def visit_user"
  },
  {
    "path": "test/integration/database_authenticatable_test.rb",
    "chars": 3282,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass DatabaseAuthenticationTest < Devise::IntegrationTest\n  test "
  },
  {
    "path": "test/integration/http_authenticatable_test.rb",
    "chars": 4124,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass HttpAuthenticationTest < Devise::IntegrationTest\n  test 'sig"
  },
  {
    "path": "test/integration/lockable_test.rb",
    "chars": 7647,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass LockTest < Devise::IntegrationTest\n\n  def visit_user_unlock_"
  },
  {
    "path": "test/integration/mounted_engine_test.rb",
    "chars": 1780,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nmodule MyMountableEngine\n  class Engine < ::Rails::Engine\n    isol"
  },
  {
    "path": "test/integration/omniauthable_test.rb",
    "chars": 5403,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\n\nclass OmniauthableIntegrationTest < Devise::IntegrationTest\n  FAC"
  },
  {
    "path": "test/integration/recoverable_test.rb",
    "chars": 13410,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass PasswordTest < Devise::IntegrationTest\n\n  def visit_new_pass"
  },
  {
    "path": "test/integration/registerable_test.rb",
    "chars": 14490,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass RegistrationTest < Devise::IntegrationTest\n\n  test 'a guest "
  },
  {
    "path": "test/integration/rememberable_test.rb",
    "chars": 6466,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass RememberMeTest < Devise::IntegrationTest\n  def create_user_a"
  },
  {
    "path": "test/integration/timeoutable_test.rb",
    "chars": 5252,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass SessionTimeoutTest < Devise::IntegrationTest\n\n  def last_req"
  },
  {
    "path": "test/integration/trackable_test.rb",
    "chars": 2553,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass TrackableHooksTest < Devise::IntegrationTest\n  test \"trackab"
  },
  {
    "path": "test/mailers/confirmation_instructions_test.rb",
    "chars": 3245,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass ConfirmationInstructionsTest < ActionMailer::TestCase\n\n  def"
  },
  {
    "path": "test/mailers/email_changed_test.rb",
    "chars": 3511,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass EmailChangedTest < ActionMailer::TestCase\n  def setup\n    se"
  },
  {
    "path": "test/mailers/mailer_test.rb",
    "chars": 1301,
    "preview": "# frozen_string_literal: true\n\nrequire \"test_helper\"\n\nclass MailerTest < ActionMailer::TestCase\n  test \"pass given block"
  },
  {
    "path": "test/mailers/reset_password_instructions_test.rb",
    "chars": 2742,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass ResetPasswordInstructionsTest < ActionMailer::TestCase\n  def"
  },
  {
    "path": "test/mailers/unlock_instructions_test.rb",
    "chars": 2478,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass UnlockInstructionsTest < ActionMailer::TestCase\n\n  def setup"
  },
  {
    "path": "test/mapping_test.rb",
    "chars": 4762,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass FakeRequest < Struct.new(:path_info, :params)\nend\n\nclass Map"
  },
  {
    "path": "test/models/authenticatable_test.rb",
    "chars": 2262,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass AuthenticatableTest < ActiveSupport::TestCase\n  test 'requir"
  },
  {
    "path": "test/models/confirmable_test.rb",
    "chars": 19372,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass ConfirmableTest < ActiveSupport::TestCase\n\n  def setup\n    s"
  },
  {
    "path": "test/models/database_authenticatable_test.rb",
    "chars": 11113,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\nrequire 'test_models'\nrequire 'digest/sha1'\n\nclass DatabaseAuthenti"
  },
  {
    "path": "test/models/lockable_test.rb",
    "chars": 12400,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass LockableTest < ActiveSupport::TestCase\n  def setup\n    setup"
  },
  {
    "path": "test/models/omniauthable_test.rb",
    "chars": 256,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass OmniauthableTest < ActiveSupport::TestCase\n  test 'required_"
  },
  {
    "path": "test/models/recoverable_test.rb",
    "chars": 8978,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass RecoverableTest < ActiveSupport::TestCase\n\n  def setup\n    s"
  },
  {
    "path": "test/models/registerable_test.rb",
    "chars": 256,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass RegisterableTest < ActiveSupport::TestCase\n  test 'required_"
  },
  {
    "path": "test/models/rememberable_test.rb",
    "chars": 5739,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass RememberableTest < ActiveSupport::TestCase\n  def resource_cl"
  },
  {
    "path": "test/models/serializable_test.rb",
    "chars": 1447,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass SerializableTest < ActiveSupport::TestCase\n  setup do\n    @u"
  },
  {
    "path": "test/models/timeoutable_test.rb",
    "chars": 1482,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass TimeoutableTest < ActiveSupport::TestCase\n\n  test 'should be"
  },
  {
    "path": "test/models/trackable_test.rb",
    "chars": 2201,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass TrackableTest < ActiveSupport::TestCase\n  test 'required_fie"
  },
  {
    "path": "test/models/validatable_test.rb",
    "chars": 4157,
    "preview": "# encoding: UTF-8\n# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass ValidatableTest < ActiveSupport::TestCase\n"
  },
  {
    "path": "test/models_test.rb",
    "chars": 4781,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\nrequire 'test_models'\n\nclass ActiveRecordTest < ActiveSupport::Test"
  },
  {
    "path": "test/omniauth/config_test.rb",
    "chars": 1890,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass OmniAuthConfigTest < ActiveSupport::TestCase\n  class MyStrat"
  },
  {
    "path": "test/omniauth/url_helpers_test.rb",
    "chars": 1807,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass OmniAuthRoutesTest < ActionController::TestCase\n  tests Appl"
  },
  {
    "path": "test/orm/active_record.rb",
    "chars": 541,
    "preview": "# frozen_string_literal: true\n\nActiveRecord::Migration.verbose = false\nActiveRecord::Base.logger = Logger.new(nil)\nActiv"
  },
  {
    "path": "test/orm/mongoid.rb",
    "chars": 275,
    "preview": "# frozen_string_literal: true\n\nrequire 'mongoid/version'\n\nMongoid.configure do |config|\n  config.load!('test/support/mon"
  },
  {
    "path": "test/parameter_sanitizer_test.rb",
    "chars": 3248,
    "preview": "# frozen_string_literal: true\n\nrequire 'test_helper'\nrequire 'devise/parameter_sanitizer'\n\nclass ParameterSanitizerTest "
  },
  {
    "path": "test/rails_app/Rakefile",
    "chars": 249,
    "preview": "# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistrano.rake, and they wil"
  },
  {
    "path": "test/rails_app/app/active_record/admin.rb",
    "chars": 129,
    "preview": "# frozen_string_literal: true\n\nrequire 'shared_admin'\n\nclass Admin < ActiveRecord::Base\n  include Shim\n  include SharedA"
  },
  {
    "path": "test/rails_app/app/active_record/shim.rb",
    "chars": 47,
    "preview": "# frozen_string_literal: true\n\nmodule Shim\nend\n"
  },
  {
    "path": "test/rails_app/app/active_record/user.rb",
    "chars": 395,
    "preview": "# frozen_string_literal: true\n\nrequire 'shared_user'\n\nclass User < ActiveRecord::Base\n  include Shim\n  include SharedUse"
  },
  {
    "path": "test/rails_app/app/active_record/user_on_engine.rb",
    "chars": 194,
    "preview": "# frozen_string_literal: true\n\nrequire 'shared_user_without_omniauth'\n\nclass UserOnEngine < ActiveRecord::Base\n  self.ta"
  },
  {
    "path": "test/rails_app/app/active_record/user_on_main_app.rb",
    "chars": 195,
    "preview": "# frozen_string_literal: true\n\nrequire 'shared_user_without_omniauth'\n\nclass UserOnMainApp < ActiveRecord::Base\n  self.t"
  },
  {
    "path": "test/rails_app/app/active_record/user_with_validations.rb",
    "chars": 206,
    "preview": "# frozen_string_literal: true\n\nrequire 'shared_user'\n\nclass UserWithValidations < ActiveRecord::Base\n  self.table_name ="
  },
  {
    "path": "test/rails_app/app/active_record/user_without_email.rb",
    "chars": 193,
    "preview": "# frozen_string_literal: true\n\nrequire \"shared_user_without_email\"\n\nclass UserWithoutEmail < ActiveRecord::Base\n  self.t"
  },
  {
    "path": "test/rails_app/app/controllers/admins/sessions_controller.rb",
    "chars": 197,
    "preview": "# frozen_string_literal: true\n\nclass Admins::SessionsController < Devise::SessionsController\n  def new\n    flash[:specia"
  },
  {
    "path": "test/rails_app/app/controllers/admins_controller.rb",
    "chars": 138,
    "preview": "# frozen_string_literal: true\n\nclass AdminsController < ApplicationController\n  before_action :authenticate_admin!\n\n  de"
  },
  {
    "path": "test/rails_app/app/controllers/application_controller.rb",
    "chars": 683,
    "preview": "# frozen_string_literal: true\n\n# Filters added to this controller apply to all controllers in the application.\n# Likewis"
  },
  {
    "path": "test/rails_app/app/controllers/application_with_fake_engine.rb",
    "chars": 624,
    "preview": "# frozen_string_literal: true\n\nclass ApplicationWithFakeEngine < ApplicationController\n  private\n\n  helper_method :fake_"
  },
  {
    "path": "test/rails_app/app/controllers/custom/registrations_controller.rb",
    "chars": 553,
    "preview": "# frozen_string_literal: true\n\nclass Custom::RegistrationsController < Devise::RegistrationsController\n  def new\n    sup"
  },
  {
    "path": "test/rails_app/app/controllers/home_controller.rb",
    "chars": 355,
    "preview": "# frozen_string_literal: true\n\nclass HomeController < ApplicationController\n  def index\n  end\n\n  def private\n  end\n\n  de"
  }
]

// ... and 72 more files (download for full content)

About this extraction

This page contains the full source code of the heartcombo/devise GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 272 files (656.7 KB), approximately 168.8k tokens, and a symbol index with 1041 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!