rodauth-rails 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -1
- data/README.md +68 -8
- data/lib/generators/rodauth/install_generator.rb +26 -20
- data/lib/generators/rodauth/migration/account_expiration.erb +7 -0
- data/lib/generators/rodauth/migration/active_sessions.erb +7 -0
- data/lib/generators/rodauth/migration/audit_logging.erb +16 -0
- data/lib/generators/rodauth/migration/base.erb +19 -0
- data/lib/generators/rodauth/migration/disallow_password_reuse.erb +5 -0
- data/lib/generators/rodauth/migration/email_auth.erb +7 -0
- data/lib/generators/rodauth/migration/jwt_refresh.erb +7 -0
- data/lib/generators/rodauth/migration/lockout.erb +11 -0
- data/lib/generators/rodauth/migration/otp.erb +7 -0
- data/lib/generators/rodauth/migration/password_expiration.erb +5 -0
- data/lib/generators/rodauth/migration/recovery_codes.erb +6 -0
- data/lib/generators/rodauth/migration/remember.erb +6 -0
- data/lib/generators/rodauth/migration/reset_password.erb +7 -0
- data/lib/generators/rodauth/migration/single_session.erb +5 -0
- data/lib/generators/rodauth/migration/sms_codes.erb +8 -0
- data/lib/generators/rodauth/migration/verify_account.erb +7 -0
- data/lib/generators/rodauth/migration/verify_login_change.erb +7 -0
- data/lib/generators/rodauth/migration/webauthn.erb +12 -0
- data/lib/generators/rodauth/migration_generator.rb +32 -0
- data/lib/generators/rodauth/migration_helpers.rb +69 -0
- data/lib/generators/rodauth/templates/app/lib/rodauth_app.rb +4 -0
- data/lib/generators/rodauth/templates/config/initializers/sequel.rb +1 -5
- data/lib/generators/rodauth/templates/db/migrate/create_rodauth.rb +2 -176
- data/lib/rodauth/rails/railtie.rb +6 -0
- data/lib/rodauth/rails/tasks.rake +32 -0
- data/lib/rodauth/rails/version.rb +1 -1
- metadata +23 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: f0d00b7ad2f6198fff3a5cc3c720c6f30d9296898e3fd764ddf7408e36232a6d
         | 
| 4 | 
            +
              data.tar.gz: 9ba008116fc5521c98ed62dda5b1f6b2eccd733d06ccb0a2c5b9b4db8df94539
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 848873e599cfb8dc8a5d274ac5fec5987cf4c895c77757a4b21529ddcd9a635ba8086c037f55c55ef097ae926549234e5abebb97a5300f0ead6118927d737d91
         | 
| 7 | 
            +
              data.tar.gz: aa75fb48217e79c40000cf1f226f36a65fdffdcb764233572ae45341b7ab9dd2f1d8f8470e593d8260495962b1b5c352e62d0d5e71fed0cb96891da93a0f344c
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,4 +1,14 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            ## 0.5.0 (2020-11-16)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * Support more Active Record adapters in `rodauth:install` generator (@janko)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * Add `rodauth:migration` generator for creating tables of specified features (@janko)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * Use UUIDs for primary keys if so configured in Rails generators (@janko)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            * Add `rodauth:routes` rake task for printing routes handled by Rodauth middleware (@janko)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            ## 0.4.2 (2020-11-08)
         | 
| 2 12 |  | 
| 3 13 | 
             
            * Drop support for Ruby 2.2 (@janko)
         | 
| 4 14 |  | 
    
        data/README.md
    CHANGED
    
    | @@ -54,7 +54,6 @@ class CreateRodauth < ActiveRecord::Migration | |
| 54 54 | 
             
                create_table :account_verification_keys do |t| ... end
         | 
| 55 55 | 
             
                create_table :account_login_change_keys do |t| ... end
         | 
| 56 56 | 
             
                create_table :account_remember_keys do |t| ... end
         | 
| 57 | 
            -
                # ...
         | 
| 58 57 | 
             
              end
         | 
| 59 58 | 
             
            end
         | 
| 60 59 | 
             
            ```
         | 
| @@ -88,7 +87,7 @@ ActiveRecord connection. | |
| 88 87 | 
             
            require "sequel/core"
         | 
| 89 88 |  | 
| 90 89 | 
             
            # initialize Sequel and have it reuse Active Record's database connection
         | 
| 91 | 
            -
            DB = Sequel. | 
| 90 | 
            +
            DB = Sequel.connect("postgresql://", extensions: :activerecord_connection)
         | 
| 92 91 | 
             
            ```
         | 
| 93 92 |  | 
| 94 93 | 
             
            ### Rodauth app
         | 
| @@ -121,7 +120,7 @@ class RodauthController < ApplicationController | |
| 121 120 | 
             
            end
         | 
| 122 121 | 
             
            ```
         | 
| 123 122 |  | 
| 124 | 
            -
            ### Account  | 
| 123 | 
            +
            ### Account model
         | 
| 125 124 |  | 
| 126 125 | 
             
            Rodauth stores user accounts in the `accounts` table, so the generator will
         | 
| 127 126 | 
             
            also create an `Account` model for custom use.
         | 
| @@ -134,8 +133,30 @@ end | |
| 134 133 |  | 
| 135 134 | 
             
            ## Getting started
         | 
| 136 135 |  | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 136 | 
            +
            First, let's see what routes our Rodauth middleware will handle:
         | 
| 137 | 
            +
             | 
| 138 | 
            +
            ```sh
         | 
| 139 | 
            +
            $ rails rodauth:routes
         | 
| 140 | 
            +
            ```
         | 
| 141 | 
            +
            ```
         | 
| 142 | 
            +
            Routes handled by RodauthApp:
         | 
| 143 | 
            +
             | 
| 144 | 
            +
              /login                   rodauth.login_path
         | 
| 145 | 
            +
              /create-account          rodauth.create_account_path
         | 
| 146 | 
            +
              /verify-account-resend   rodauth.verify_account_resend_path
         | 
| 147 | 
            +
              /verify-account          rodauth.verify_account_path
         | 
| 148 | 
            +
              /change-password         rodauth.change_password_path
         | 
| 149 | 
            +
              /change-login            rodauth.change_login_path
         | 
| 150 | 
            +
              /logout                  rodauth.logout_path
         | 
| 151 | 
            +
              /remember                rodauth.remember_path
         | 
| 152 | 
            +
              /reset-password-request  rodauth.reset_password_request_path
         | 
| 153 | 
            +
              /reset-password          rodauth.reset_password_path
         | 
| 154 | 
            +
              /verify-login-change     rodauth.verify_login_change_path
         | 
| 155 | 
            +
              /close-account           rodauth.close_account_path
         | 
| 156 | 
            +
            ```
         | 
| 157 | 
            +
             | 
| 158 | 
            +
            We can use this information to add some basic authentication navigation links
         | 
| 159 | 
            +
            to our home page:
         | 
| 139 160 |  | 
| 140 161 | 
             
            ```erb
         | 
| 141 162 | 
             
            <ul>
         | 
| @@ -265,7 +286,7 @@ $ rails generate rodauth:views --all | |
| 265 286 | 
             
            ```
         | 
| 266 287 |  | 
| 267 288 | 
             
            You can also tell the generator to create views into another directory (in this
         | 
| 268 | 
            -
            case  | 
| 289 | 
            +
            case make sure to rename the Rodauth controller accordingly).
         | 
| 269 290 |  | 
| 270 291 | 
             
            ```sh
         | 
| 271 292 | 
             
            # generates views into app/views/authentication
         | 
| @@ -300,8 +321,8 @@ end | |
| 300 321 |  | 
| 301 322 | 
             
            ### Mailer
         | 
| 302 323 |  | 
| 303 | 
            -
            Rodauth may send emails as part of | 
| 304 | 
            -
            can be customized:
         | 
| 324 | 
            +
            Depending on the features you've enabled, Rodauth may send emails as part of
         | 
| 325 | 
            +
            the authentication flow. Most email settings can be customized:
         | 
| 305 326 |  | 
| 306 327 | 
             
            ```rb
         | 
| 307 328 | 
             
            # app/lib/rodauth_app.rb
         | 
| @@ -385,6 +406,25 @@ class RodauthApp < Rodauth::Rails::App | |
| 385 406 | 
             
            end
         | 
| 386 407 | 
             
            ```
         | 
| 387 408 |  | 
| 409 | 
            +
            ### Migrations
         | 
| 410 | 
            +
             | 
| 411 | 
            +
            The install generator will have created some default tables, but you can use
         | 
| 412 | 
            +
            the migration generator to create tables for any additional Rodauth features:
         | 
| 413 | 
            +
             | 
| 414 | 
            +
            ```
         | 
| 415 | 
            +
            $ rails generate rodauth:migration otp sms_codes recovery_codes
         | 
| 416 | 
            +
            ```
         | 
| 417 | 
            +
            ```rb
         | 
| 418 | 
            +
            # db/migration/*_create_rodauth_otp_sms_codes_recovery_codes.rb
         | 
| 419 | 
            +
            class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
         | 
| 420 | 
            +
              def change
         | 
| 421 | 
            +
                create_table :account_otp_keys do |t| ... end
         | 
| 422 | 
            +
                create_table :account_sms_codes do |t| ... end
         | 
| 423 | 
            +
                create_table :account_recovery_codes do |t| ... end
         | 
| 424 | 
            +
              end
         | 
| 425 | 
            +
            end
         | 
| 426 | 
            +
            ```
         | 
| 427 | 
            +
             | 
| 388 428 | 
             
            ### JSON API
         | 
| 389 429 |  | 
| 390 430 | 
             
            JSON API support in Rodauth is provided by the [JWT feature]. First you'll need
         | 
| @@ -588,6 +628,26 @@ disables the use of database functions, though you can always turn it back on. | |
| 588 628 | 
             
            use_database_authentication_functions? true
         | 
| 589 629 | 
             
            ```
         | 
| 590 630 |  | 
| 631 | 
            +
            To create the database functions, pass the Sequel database object into the
         | 
| 632 | 
            +
            Rodauth method for creating database functions:
         | 
| 633 | 
            +
             | 
| 634 | 
            +
            ```rb
         | 
| 635 | 
            +
            # db/migrate/*_create_rodauth_database_functions.rb
         | 
| 636 | 
            +
            class CreateRodauthDatabaseFunctions < ActiveRecord::Migration
         | 
| 637 | 
            +
              def up
         | 
| 638 | 
            +
                # ...
         | 
| 639 | 
            +
                Rodauth.create_database_authentication_functions(DB)
         | 
| 640 | 
            +
                # ...
         | 
| 641 | 
            +
              end
         | 
| 642 | 
            +
             | 
| 643 | 
            +
              def down
         | 
| 644 | 
            +
                # ...
         | 
| 645 | 
            +
                Rodauth.drop_database_authentication_functions(DB)
         | 
| 646 | 
            +
                # ...
         | 
| 647 | 
            +
              end
         | 
| 648 | 
            +
            end
         | 
| 649 | 
            +
            ```
         | 
| 650 | 
            +
             | 
| 591 651 | 
             
            ### Account statuses
         | 
| 592 652 |  | 
| 593 653 | 
             
            The recommended [Rodauth migration] stores possible account status values in a
         | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            require "rails/generators/base"
         | 
| 2 2 | 
             
            require "rails/generators/active_record/migration"
         | 
| 3 | 
            -
             | 
| 3 | 
            +
            require "generators/rodauth/migration_helpers"
         | 
| 4 4 | 
             
            require "securerandom"
         | 
| 5 5 |  | 
| 6 6 | 
             
            module Rodauth
         | 
| @@ -8,6 +8,7 @@ module Rodauth | |
| 8 8 | 
             
                module Generators
         | 
| 9 9 | 
             
                  class InstallGenerator < ::Rails::Generators::Base
         | 
| 10 10 | 
             
                    include ::ActiveRecord::Generators::Migration
         | 
| 11 | 
            +
                    include MigrationHelpers
         | 
| 11 12 |  | 
| 12 13 | 
             
                    source_root "#{__dir__}/templates"
         | 
| 13 14 | 
             
                    namespace "rodauth:install"
         | 
| @@ -15,7 +16,7 @@ module Rodauth | |
| 15 16 | 
             
                    def create_rodauth_migration
         | 
| 16 17 | 
             
                      return unless defined?(ActiveRecord::Base)
         | 
| 17 18 |  | 
| 18 | 
            -
                      migration_template "db/migrate/create_rodauth.rb" | 
| 19 | 
            +
                      migration_template "db/migrate/create_rodauth.rb"
         | 
| 19 20 | 
             
                    end
         | 
| 20 21 |  | 
| 21 22 | 
             
                    def create_rodauth_initializer
         | 
| @@ -24,7 +25,6 @@ module Rodauth | |
| 24 25 |  | 
| 25 26 | 
             
                    def create_sequel_initializer
         | 
| 26 27 | 
             
                      return unless defined?(ActiveRecord::Base)
         | 
| 27 | 
            -
                      return unless %w[postgresql mysql2 sqlite3].include?(activerecord_adapter)
         | 
| 28 28 | 
             
                      return if defined?(Sequel) && !Sequel::DATABASES.empty?
         | 
| 29 29 |  | 
| 30 30 | 
             
                      template "config/initializers/sequel.rb"
         | 
| @@ -48,39 +48,45 @@ module Rodauth | |
| 48 48 |  | 
| 49 49 | 
             
                    private
         | 
| 50 50 |  | 
| 51 | 
            -
                    def  | 
| 52 | 
            -
                       | 
| 53 | 
            -
             | 
| 54 | 
            -
                       | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
                    def migration_version
         | 
| 58 | 
            -
                      if ActiveRecord.version >= Gem::Version.new("5.0")
         | 
| 59 | 
            -
                        "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
         | 
| 51 | 
            +
                    def sequel_uri_scheme
         | 
| 52 | 
            +
                      if RUBY_ENGINE == "jruby"
         | 
| 53 | 
            +
                        "jdbc:#{sequel_jdbc_subadapter}"
         | 
| 54 | 
            +
                      else
         | 
| 55 | 
            +
                        sequel_adapter
         | 
| 60 56 | 
             
                      end
         | 
| 61 57 | 
             
                    end
         | 
| 62 58 |  | 
| 63 59 | 
             
                    def sequel_adapter
         | 
| 64 60 | 
             
                      case activerecord_adapter
         | 
| 65 | 
            -
                      when " | 
| 66 | 
            -
                      when " | 
| 67 | 
            -
                      when " | 
| 61 | 
            +
                      when "sqlite3"         then "sqlite"
         | 
| 62 | 
            +
                      when "oracle_enhanced" then "oracle" # https://github.com/rsim/oracle-enhanced
         | 
| 63 | 
            +
                      when "sqlserver"       then "tinytds" # https://github.com/rails-sqlserver/activerecord-sqlserver-adapter
         | 
| 64 | 
            +
                      else
         | 
| 65 | 
            +
                        activerecord_adapter
         | 
| 68 66 | 
             
                      end
         | 
| 69 67 | 
             
                    end
         | 
| 70 68 |  | 
| 71 | 
            -
                    def  | 
| 72 | 
            -
                       | 
| 73 | 
            -
             | 
| 69 | 
            +
                    def sequel_jdbc_subadapter
         | 
| 70 | 
            +
                      case activerecord_adapter
         | 
| 71 | 
            +
                      when "sqlite3"         then "sqlite"
         | 
| 72 | 
            +
                      when "oracle_enhanced" then "oracle" # https://github.com/rsim/oracle-enhanced
         | 
| 73 | 
            +
                      when "sqlserver"       then "mssql"
         | 
| 74 74 | 
             
                      else
         | 
| 75 | 
            -
                         | 
| 75 | 
            +
                        activerecord_adapter
         | 
| 76 76 | 
             
                      end
         | 
| 77 77 | 
             
                    end
         | 
| 78 78 |  | 
| 79 79 | 
             
                    def api_only?
         | 
| 80 | 
            -
                      return  | 
| 80 | 
            +
                      return unless ::Rails.gem_version >= Gem::Version.new("5.0")
         | 
| 81 81 |  | 
| 82 82 | 
             
                      ::Rails.application.config.api_only
         | 
| 83 83 | 
             
                    end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                    def migration_features
         | 
| 86 | 
            +
                      features = [:base, :reset_password, :verify_account, :verify_login_change]
         | 
| 87 | 
            +
                      features << :remember unless api_only?
         | 
| 88 | 
            +
                      features
         | 
| 89 | 
            +
                    end
         | 
| 84 90 | 
             
                  end
         | 
| 85 91 | 
             
                end
         | 
| 86 92 | 
             
              end
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            # Used by the active sessions feature
         | 
| 2 | 
            +
            create_table :account_active_session_keys, primary_key: [:account_id, :session_id] do |t|
         | 
| 3 | 
            +
              t.references :account, foreign_key: true<%= primary_key_type(:type) %>
         | 
| 4 | 
            +
              t.string :session_id
         | 
| 5 | 
            +
              t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 6 | 
            +
              t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 7 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            # Used by the audit logging feature
         | 
| 2 | 
            +
            create_table :account_authentication_audit_logs<%= primary_key_type %> do |t|
         | 
| 3 | 
            +
              t.references :account, foreign_key: true, null: false<%= primary_key_type(:type) %>
         | 
| 4 | 
            +
              t.datetime :at, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 5 | 
            +
              t.text :message, null: false
         | 
| 6 | 
            +
            <% case activerecord_adapter -%>
         | 
| 7 | 
            +
            <% when "postgresql" -%>
         | 
| 8 | 
            +
              t.jsonb :metadata
         | 
| 9 | 
            +
            <% when "sqlite3", "mysql2" -%>
         | 
| 10 | 
            +
              t.json :metadata
         | 
| 11 | 
            +
            <% else -%>
         | 
| 12 | 
            +
              t.string :metadata
         | 
| 13 | 
            +
            <% end -%>
         | 
| 14 | 
            +
              t.index [:account_id, :at], name: "audit_account_at_idx"
         | 
| 15 | 
            +
              t.index :at, name: "audit_at_idx"
         | 
| 16 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            <% if activerecord_adapter == "postgresql" -%>
         | 
| 2 | 
            +
            enable_extension "citext"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            <% end -%>
         | 
| 5 | 
            +
            create_table :accounts<%= primary_key_type %> do |t|
         | 
| 6 | 
            +
            <% case activerecord_adapter -%>
         | 
| 7 | 
            +
            <% when "postgresql" -%>
         | 
| 8 | 
            +
              t.citext :email, null: false, index: { unique: true, where: "status IN ('verified', 'unverified')" }
         | 
| 9 | 
            +
            <% else -%>
         | 
| 10 | 
            +
              t.string :email, null: false, index: { unique: true }
         | 
| 11 | 
            +
            <% end -%>
         | 
| 12 | 
            +
              t.string :status, null: false, default: "verified"
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            # Used if storing password hashes in a separate table (default)
         | 
| 16 | 
            +
            create_table :account_password_hashes<%= primary_key_type %> do |t|
         | 
| 17 | 
            +
              t.foreign_key :accounts, column: :id
         | 
| 18 | 
            +
              t.string :password_hash, null: false
         | 
| 19 | 
            +
            end
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            # Used by the email auth feature
         | 
| 2 | 
            +
            create_table :account_email_auth_keys<%= primary_key_type %> do |t|
         | 
| 3 | 
            +
              t.foreign_key :accounts, column: :id
         | 
| 4 | 
            +
              t.string :key, null: false
         | 
| 5 | 
            +
              t.datetime :deadline, null: false
         | 
| 6 | 
            +
              t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 7 | 
            +
            end
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            # Used by the jwt refresh feature
         | 
| 2 | 
            +
            create_table :account_jwt_refresh_keys<%= primary_key_type %> do |t|
         | 
| 3 | 
            +
              t.references :account, foreign_key: true, null: false<%= primary_key_type(:type) %>
         | 
| 4 | 
            +
              t.string :key, null: false
         | 
| 5 | 
            +
              t.datetime :deadline, null: false
         | 
| 6 | 
            +
              t.index :account_id, name: "account_jwt_rk_account_id_idx"
         | 
| 7 | 
            +
            end
         | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            # Used by the lockout feature
         | 
| 2 | 
            +
            create_table :account_login_failures<%= primary_key_type %> do |t|
         | 
| 3 | 
            +
              t.foreign_key :accounts, column: :id
         | 
| 4 | 
            +
              t.integer :number, null: false, default: 1
         | 
| 5 | 
            +
            end
         | 
| 6 | 
            +
            create_table :account_lockouts<%= primary_key_type %> do |t|
         | 
| 7 | 
            +
              t.foreign_key :accounts, column: :id
         | 
| 8 | 
            +
              t.string :key, null: false
         | 
| 9 | 
            +
              t.datetime :deadline, null: false
         | 
| 10 | 
            +
              t.datetime :email_last_sent
         | 
| 11 | 
            +
            end
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            # Used by the otp feature
         | 
| 2 | 
            +
            create_table :account_otp_keys<%= primary_key_type %> do |t|
         | 
| 3 | 
            +
              t.foreign_key :accounts, column: :id
         | 
| 4 | 
            +
              t.string :key, null: false
         | 
| 5 | 
            +
              t.integer :num_failures, null: false, default: 0
         | 
| 6 | 
            +
              t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 7 | 
            +
            end
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            # Used by the password reset feature
         | 
| 2 | 
            +
            create_table :account_password_reset_keys<%= primary_key_type %> do |t|
         | 
| 3 | 
            +
              t.foreign_key :accounts, column: :id
         | 
| 4 | 
            +
              t.string :key, null: false
         | 
| 5 | 
            +
              t.datetime :deadline, null: false
         | 
| 6 | 
            +
              t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 7 | 
            +
            end
         | 
| @@ -0,0 +1,8 @@ | |
| 1 | 
            +
            # Used by the sms codes feature
         | 
| 2 | 
            +
            create_table :account_sms_codes<%= primary_key_type %> do |t|
         | 
| 3 | 
            +
              t.foreign_key :accounts, column: :id
         | 
| 4 | 
            +
              t.string :phone_number, null: false
         | 
| 5 | 
            +
              t.integer :num_failures
         | 
| 6 | 
            +
              t.string :code
         | 
| 7 | 
            +
              t.datetime :code_issued_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 8 | 
            +
            end
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            # Used by the account verification feature
         | 
| 2 | 
            +
            create_table :account_verification_keys<%= primary_key_type %> do |t|
         | 
| 3 | 
            +
              t.foreign_key :accounts, column: :id
         | 
| 4 | 
            +
              t.string :key, null: false
         | 
| 5 | 
            +
              t.datetime :requested_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 6 | 
            +
              t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 7 | 
            +
            end
         | 
| @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            # Used by the webauthn feature
         | 
| 2 | 
            +
            create_table :account_webauthn_user_ids<%= primary_key_type %> do |t|
         | 
| 3 | 
            +
              t.foreign_key :accounts, column: :id
         | 
| 4 | 
            +
              t.string :webauthn_id, null: false
         | 
| 5 | 
            +
            end
         | 
| 6 | 
            +
            create_table :account_webauthn_keys, primary_key: [:account_id, :webauthn_id] do |t|
         | 
| 7 | 
            +
              t.references :account, foreign_key: true<%= primary_key_type(:type) %>
         | 
| 8 | 
            +
              t.string :webauthn_id
         | 
| 9 | 
            +
              t.string :public_key, null: false
         | 
| 10 | 
            +
              t.integer :sign_count, null: false
         | 
| 11 | 
            +
              t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 12 | 
            +
            end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            require "rails/generators/base"
         | 
| 2 | 
            +
            require "rails/generators/active_record/migration"
         | 
| 3 | 
            +
            require "generators/rodauth/migration_helpers"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Rodauth
         | 
| 6 | 
            +
              module Rails
         | 
| 7 | 
            +
                module Generators
         | 
| 8 | 
            +
                  class MigrationGenerator < ::Rails::Generators::Base
         | 
| 9 | 
            +
                    include ::ActiveRecord::Generators::Migration
         | 
| 10 | 
            +
                    include MigrationHelpers
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    source_root "#{__dir__}/templates"
         | 
| 13 | 
            +
                    namespace "rodauth:migration"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    argument :features, optional: true, type: :array,
         | 
| 16 | 
            +
                      desc: "Rodauth features to create tables for (otp, sms_codes, single_session, account_expiration etc.)",
         | 
| 17 | 
            +
                      default: %w[]
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    def create_rodauth_migration
         | 
| 20 | 
            +
                      return unless defined?(ActiveRecord::Base)
         | 
| 21 | 
            +
                      return if features.empty?
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                      migration_template "db/migrate/create_rodauth.rb", "create_rodauth_#{features.join("_")}.rb"
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    def migration_features
         | 
| 27 | 
            +
                      features
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
| @@ -0,0 +1,69 @@ | |
| 1 | 
            +
            require "erb"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Rodauth
         | 
| 4 | 
            +
              module Rails
         | 
| 5 | 
            +
                module Generators
         | 
| 6 | 
            +
                  module MigrationHelpers
         | 
| 7 | 
            +
                    attr_reader :migration_class_name
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def migration_template(source, destination = File.basename(source))
         | 
| 10 | 
            +
                      @migration_class_name = destination.chomp(".rb").camelize
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                      super source, File.join(db_migrate_path, destination)
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    private
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    def migration_content
         | 
| 18 | 
            +
                      migration_features
         | 
| 19 | 
            +
                        .select { |feature| File.exist?("#{__dir__}/migration/#{feature}.erb") }
         | 
| 20 | 
            +
                        .map { |feature| File.read("#{__dir__}/migration/#{feature}.erb") }
         | 
| 21 | 
            +
                        .map { |content| erb_eval(content) }
         | 
| 22 | 
            +
                        .join("\n")
         | 
| 23 | 
            +
                        .indent(4)
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    def activerecord_adapter
         | 
| 27 | 
            +
                      if ActiveRecord::Base.respond_to?(:connection_db_config)
         | 
| 28 | 
            +
                        ActiveRecord::Base.connection_db_config.adapter
         | 
| 29 | 
            +
                      else
         | 
| 30 | 
            +
                        ActiveRecord::Base.connection_config.fetch(:adapter)
         | 
| 31 | 
            +
                      end
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    def migration_version
         | 
| 35 | 
            +
                      return unless ActiveRecord.version >= Gem::Version.new("5.0")
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                      "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    def db_migrate_path
         | 
| 41 | 
            +
                      return "db/migrate" unless ActiveRecord.version >= Gem::Version.new("5.0")
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                      super
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    def primary_key_type(key = :id)
         | 
| 47 | 
            +
                      generators  = ::Rails.application.config.generators
         | 
| 48 | 
            +
                      column_type = generators.options[:active_record][:primary_key_type]
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                      return unless column_type
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                      if key
         | 
| 53 | 
            +
                        ", #{key}: :#{column_type}"
         | 
| 54 | 
            +
                      else
         | 
| 55 | 
            +
                        column_type
         | 
| 56 | 
            +
                      end
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    def erb_eval(content)
         | 
| 60 | 
            +
                      if ERB.version[/\d+\.\d+\.\d+/].to_s >= "2.2.0"
         | 
| 61 | 
            +
                        ERB.new(content, trim_mode: "-").result(binding)
         | 
| 62 | 
            +
                      else
         | 
| 63 | 
            +
                        ERB.new(content, 0, "-").result(binding)
         | 
| 64 | 
            +
                      end
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
            end
         | 
| @@ -11,6 +11,10 @@ class RodauthApp < Rodauth::Rails::App | |
| 11 11 | 
             
                # http://rodauth.jeremyevans.net/documentation.html
         | 
| 12 12 |  | 
| 13 13 | 
             
                # ==> General
         | 
| 14 | 
            +
                # The secret key used for hashing public-facing tokens for various features.
         | 
| 15 | 
            +
                # Defaults to Rails `secret_key_base`, but you can use your own secret key.
         | 
| 16 | 
            +
                # hmac_secret "<%= SecureRandom.hex(64) %>"
         | 
| 17 | 
            +
             | 
| 14 18 | 
             
            <% unless api_only? -%>
         | 
| 15 19 | 
             
                # Specify the controller used for view rendering and CSRF verification.
         | 
| 16 20 | 
             
                rails_controller { RodauthController }
         | 
| @@ -1,8 +1,4 @@ | |
| 1 1 | 
             
            require "sequel/core"
         | 
| 2 2 |  | 
| 3 3 | 
             
            # initialize Sequel and have it reuse Active Record's database connection
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            DB = Sequel.connect("jdbc:<%= sequel_adapter %>://", extensions: :activerecord_connection)
         | 
| 6 | 
            -
            <% else -%>
         | 
| 7 | 
            -
            DB = Sequel.<%= sequel_adapter %>(extensions: :activerecord_connection)
         | 
| 8 | 
            -
            <% end -%>
         | 
| 4 | 
            +
            DB = Sequel.connect("<%= sequel_uri_scheme %>://", extensions: :activerecord_connection)
         | 
| @@ -1,179 +1,5 @@ | |
| 1 | 
            -
            class  | 
| 1 | 
            +
            class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
         | 
| 2 2 | 
             
              def change
         | 
| 3 | 
            -
             | 
| 4 | 
            -
                enable_extension "citext"
         | 
| 5 | 
            -
             | 
| 6 | 
            -
            <% end -%>
         | 
| 7 | 
            -
                create_table :accounts do |t|
         | 
| 8 | 
            -
            <% case activerecord_adapter -%>
         | 
| 9 | 
            -
            <% when "postgresql" -%>
         | 
| 10 | 
            -
                  t.citext :email, null: false, index: { unique: true, where: "status IN ('verified', 'unverified')" }
         | 
| 11 | 
            -
            <% else -%>
         | 
| 12 | 
            -
                  t.string :email, null: false, index: { unique: true }
         | 
| 13 | 
            -
            <% end -%>
         | 
| 14 | 
            -
                  t.string :status, null: false, default: "verified"
         | 
| 15 | 
            -
                end
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                # Used if storing password hashes in a separate table (default)
         | 
| 18 | 
            -
                create_table :account_password_hashes do |t|
         | 
| 19 | 
            -
                  t.foreign_key :accounts, column: :id
         | 
| 20 | 
            -
                  t.string :password_hash, null: false
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                # Used by the password reset feature
         | 
| 24 | 
            -
                create_table :account_password_reset_keys do |t|
         | 
| 25 | 
            -
                  t.foreign_key :accounts, column: :id
         | 
| 26 | 
            -
                  t.string :key, null: false
         | 
| 27 | 
            -
                  t.datetime :deadline, null: false
         | 
| 28 | 
            -
                  t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                # Used by the account verification feature
         | 
| 32 | 
            -
                create_table :account_verification_keys do |t|
         | 
| 33 | 
            -
                  t.foreign_key :accounts, column: :id
         | 
| 34 | 
            -
                  t.string :key, null: false
         | 
| 35 | 
            -
                  t.datetime :requested_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 36 | 
            -
                  t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 37 | 
            -
                end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                # Used by the verify login change feature
         | 
| 40 | 
            -
                create_table :account_login_change_keys do |t|
         | 
| 41 | 
            -
                  t.foreign_key :accounts, column: :id
         | 
| 42 | 
            -
                  t.string :key, null: false
         | 
| 43 | 
            -
                  t.string :login, null: false
         | 
| 44 | 
            -
                  t.datetime :deadline, null: false
         | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
            <% unless api_only? -%>
         | 
| 48 | 
            -
                # Used by the remember me feature
         | 
| 49 | 
            -
                create_table :account_remember_keys do |t|
         | 
| 50 | 
            -
                  t.foreign_key :accounts, column: :id
         | 
| 51 | 
            -
                  t.string :key, null: false
         | 
| 52 | 
            -
                  t.datetime :deadline, null: false
         | 
| 53 | 
            -
                end
         | 
| 54 | 
            -
            <% else -%>
         | 
| 55 | 
            -
                # # Used by the remember me feature
         | 
| 56 | 
            -
                # create_table :account_remember_keys do |t|
         | 
| 57 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 58 | 
            -
                #   t.string :key, null: false
         | 
| 59 | 
            -
                #   t.datetime :deadline, null: false
         | 
| 60 | 
            -
                # end
         | 
| 61 | 
            -
            <% end -%>
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                # # Used by the audit logging feature
         | 
| 64 | 
            -
                # create_table :account_authentication_audit_logs do |t|
         | 
| 65 | 
            -
                #   t.references :account, foreign_key: true, null: false
         | 
| 66 | 
            -
                #   t.datetime :at, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 67 | 
            -
                #   t.text :message, null: false
         | 
| 68 | 
            -
            <% case activerecord_adapter -%>
         | 
| 69 | 
            -
            <% when "postgresql" -%>
         | 
| 70 | 
            -
                #   t.jsonb :metadata
         | 
| 71 | 
            -
            <% when "sqlite3", "mysql2" -%>
         | 
| 72 | 
            -
                #   t.json :metadata
         | 
| 73 | 
            -
            <% else -%>
         | 
| 74 | 
            -
                #   t.string :metadata
         | 
| 75 | 
            -
            <% end -%>
         | 
| 76 | 
            -
                #   t.index [:account_id, :at], name: "audit_account_at_idx"
         | 
| 77 | 
            -
                #   t.index :at, name: "audit_at_idx"
         | 
| 78 | 
            -
                # end
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                # # Used by the jwt refresh feature
         | 
| 81 | 
            -
                # create_table :account_jwt_refresh_keys do |t|
         | 
| 82 | 
            -
                #   t.references :account, foreign_key: true, null: false
         | 
| 83 | 
            -
                #   t.string :key, null: false
         | 
| 84 | 
            -
                #   t.datetime :deadline, null: false
         | 
| 85 | 
            -
                #   t.index :account_id, name: "account_jwt_rk_account_id_idx"
         | 
| 86 | 
            -
                # end
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                # # Used by the disallow_password_reuse feature
         | 
| 89 | 
            -
                # create_table :account_previous_password_hashes do |t|
         | 
| 90 | 
            -
                #   t.references :account, foreign_key: true
         | 
| 91 | 
            -
                #   t.string :password_hash, null: false
         | 
| 92 | 
            -
                # end
         | 
| 93 | 
            -
             | 
| 94 | 
            -
                # # Used by the lockout feature
         | 
| 95 | 
            -
                # create_table :account_login_failures do |t|
         | 
| 96 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 97 | 
            -
                #   t.integer :number, null: false, default: 1
         | 
| 98 | 
            -
                # end
         | 
| 99 | 
            -
                # create_table :account_lockouts do |t|
         | 
| 100 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 101 | 
            -
                #   t.string :key, null: false
         | 
| 102 | 
            -
                #   t.datetime :deadline, null: false
         | 
| 103 | 
            -
                #   t.datetime :email_last_sent
         | 
| 104 | 
            -
                # end
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                # # Used by the email auth feature
         | 
| 107 | 
            -
                # create_table :account_email_auth_keys do |t|
         | 
| 108 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 109 | 
            -
                #   t.string :key, null: false
         | 
| 110 | 
            -
                #   t.datetime :deadline, null: false
         | 
| 111 | 
            -
                #   t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 112 | 
            -
                # end
         | 
| 113 | 
            -
             | 
| 114 | 
            -
                # # Used by the password expiration feature
         | 
| 115 | 
            -
                # create_table :account_password_change_times do |t|
         | 
| 116 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 117 | 
            -
                #   t.datetime :changed_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 118 | 
            -
                # end
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                # # Used by the account expiration feature
         | 
| 121 | 
            -
                # create_table :account_activity_times do |t|
         | 
| 122 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 123 | 
            -
                #   t.datetime :last_activity_at, null: false
         | 
| 124 | 
            -
                #   t.datetime :last_login_at, null: false
         | 
| 125 | 
            -
                #   t.datetime :expired_at
         | 
| 126 | 
            -
                # end
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                # # Used by the single session feature
         | 
| 129 | 
            -
                # create_table :account_session_keys do |t|
         | 
| 130 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 131 | 
            -
                #   t.string :key, null: false
         | 
| 132 | 
            -
                # end
         | 
| 133 | 
            -
             | 
| 134 | 
            -
                # # Used by the active sessions feature
         | 
| 135 | 
            -
                # create_table :account_active_session_keys, primary_key: [:account_id, :session_id] do |t|
         | 
| 136 | 
            -
                #   t.references :account, foreign_key: true
         | 
| 137 | 
            -
                #   t.string :session_id
         | 
| 138 | 
            -
                #   t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 139 | 
            -
                #   t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 140 | 
            -
                # end
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                # # Used by the webauthn feature
         | 
| 143 | 
            -
                # create_table :account_webauthn_user_ids do |t|
         | 
| 144 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 145 | 
            -
                #   t.string :webauthn_id, null: false
         | 
| 146 | 
            -
                # end
         | 
| 147 | 
            -
                # create_table :account_webauthn_keys, primary_key: [:account_id, :webauthn_id] do |t|
         | 
| 148 | 
            -
                #   t.references :account, foreign_key: true
         | 
| 149 | 
            -
                #   t.string :webauthn_id
         | 
| 150 | 
            -
                #   t.string :public_key, null: false
         | 
| 151 | 
            -
                #   t.integer :sign_count, null: false
         | 
| 152 | 
            -
                #   t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 153 | 
            -
                # end
         | 
| 154 | 
            -
             | 
| 155 | 
            -
                # # Used by the otp feature
         | 
| 156 | 
            -
                # create_table :account_otp_keys do |t|
         | 
| 157 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 158 | 
            -
                #   t.string :key, null: false
         | 
| 159 | 
            -
                #   t.integer :num_failures, null: false, default: 0
         | 
| 160 | 
            -
                #   t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 161 | 
            -
                # end
         | 
| 162 | 
            -
             | 
| 163 | 
            -
                # # Used by the recovery codes feature
         | 
| 164 | 
            -
                # create_table :account_recovery_codes, primary_key: [:id, :code] do |t|
         | 
| 165 | 
            -
                #   t.integer :id
         | 
| 166 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 167 | 
            -
                #   t.string :code
         | 
| 168 | 
            -
                # end
         | 
| 169 | 
            -
             | 
| 170 | 
            -
                # # Used by the sms codes feature
         | 
| 171 | 
            -
                # create_table :account_sms_codes do |t|
         | 
| 172 | 
            -
                #   t.foreign_key :accounts, column: :id
         | 
| 173 | 
            -
                #   t.string :phone_number, null: false
         | 
| 174 | 
            -
                #   t.integer :num_failures
         | 
| 175 | 
            -
                #   t.string :code
         | 
| 176 | 
            -
                #   t.datetime :code_issued_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
         | 
| 177 | 
            -
                # end
         | 
| 3 | 
            +
            <%= migration_content -%>
         | 
| 178 4 | 
             
              end
         | 
| 179 5 | 
             
            end
         | 
| @@ -1,6 +1,8 @@ | |
| 1 1 | 
             
            require "rodauth/rails/middleware"
         | 
| 2 2 | 
             
            require "rodauth/rails/controller_methods"
         | 
| 3 3 |  | 
| 4 | 
            +
            require "rails"
         | 
| 5 | 
            +
             | 
| 4 6 | 
             
            module Rodauth
         | 
| 5 7 | 
             
              module Rails
         | 
| 6 8 | 
             
                class Railtie < ::Rails::Railtie
         | 
| @@ -18,6 +20,10 @@ module Rodauth | |
| 18 20 | 
             
                    # Rodauth uses RACK_ENV to set the default bcrypt hash cost
         | 
| 19 21 | 
             
                    ENV["RACK_ENV"] = "test" if ::Rails.env.test?
         | 
| 20 22 | 
             
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  rake_tasks do
         | 
| 25 | 
            +
                    load "rodauth/rails/tasks.rake"
         | 
| 26 | 
            +
                  end
         | 
| 21 27 | 
             
                end
         | 
| 22 28 | 
             
              end
         | 
| 23 29 | 
             
            end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            namespace :rodauth do
         | 
| 2 | 
            +
              task routes: :environment do
         | 
| 3 | 
            +
                app = Rodauth::Rails.app
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                puts "Routes handled by #{app}:"
         | 
| 6 | 
            +
                puts
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                app.opts[:rodauths].each do |rodauth_name, rodauth_class|
         | 
| 9 | 
            +
                  route_names = rodauth_class.routes
         | 
| 10 | 
            +
                    .map { |handle_method| handle_method.to_s.sub(/\Ahandle_/, "") }
         | 
| 11 | 
            +
                    .uniq
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  rodauth = rodauth_class.allocate
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  routes = route_names.map do |name|
         | 
| 16 | 
            +
                    [
         | 
| 17 | 
            +
                      rodauth.public_send(:"#{name}_path"),
         | 
| 18 | 
            +
                      "rodauth#{rodauth_name && "(:#{rodauth_name})"}.#{name}_path",
         | 
| 19 | 
            +
                    ]
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  padding = routes.map { |path, _| path.length }.max
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  route_lines = routes.map do |path, code|
         | 
| 25 | 
            +
                    "#{path.ljust(padding)}  #{code}"
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  puts "  #{route_lines.join("\n  ")}"
         | 
| 29 | 
            +
                  puts
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: rodauth-rails
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.5.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Janko Marohnić
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2020-11- | 
| 11 | 
            +
            date: 2020-11-16 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: railties
         | 
| @@ -98,6 +98,26 @@ files: | |
| 98 98 | 
             
            - README.md
         | 
| 99 99 | 
             
            - lib/generators/rodauth/install_generator.rb
         | 
| 100 100 | 
             
            - lib/generators/rodauth/mailer_generator.rb
         | 
| 101 | 
            +
            - lib/generators/rodauth/migration/account_expiration.erb
         | 
| 102 | 
            +
            - lib/generators/rodauth/migration/active_sessions.erb
         | 
| 103 | 
            +
            - lib/generators/rodauth/migration/audit_logging.erb
         | 
| 104 | 
            +
            - lib/generators/rodauth/migration/base.erb
         | 
| 105 | 
            +
            - lib/generators/rodauth/migration/disallow_password_reuse.erb
         | 
| 106 | 
            +
            - lib/generators/rodauth/migration/email_auth.erb
         | 
| 107 | 
            +
            - lib/generators/rodauth/migration/jwt_refresh.erb
         | 
| 108 | 
            +
            - lib/generators/rodauth/migration/lockout.erb
         | 
| 109 | 
            +
            - lib/generators/rodauth/migration/otp.erb
         | 
| 110 | 
            +
            - lib/generators/rodauth/migration/password_expiration.erb
         | 
| 111 | 
            +
            - lib/generators/rodauth/migration/recovery_codes.erb
         | 
| 112 | 
            +
            - lib/generators/rodauth/migration/remember.erb
         | 
| 113 | 
            +
            - lib/generators/rodauth/migration/reset_password.erb
         | 
| 114 | 
            +
            - lib/generators/rodauth/migration/single_session.erb
         | 
| 115 | 
            +
            - lib/generators/rodauth/migration/sms_codes.erb
         | 
| 116 | 
            +
            - lib/generators/rodauth/migration/verify_account.erb
         | 
| 117 | 
            +
            - lib/generators/rodauth/migration/verify_login_change.erb
         | 
| 118 | 
            +
            - lib/generators/rodauth/migration/webauthn.erb
         | 
| 119 | 
            +
            - lib/generators/rodauth/migration_generator.rb
         | 
| 120 | 
            +
            - lib/generators/rodauth/migration_helpers.rb
         | 
| 101 121 | 
             
            - lib/generators/rodauth/templates/app/controllers/rodauth_controller.rb
         | 
| 102 122 | 
             
            - lib/generators/rodauth/templates/app/lib/rodauth_app.rb
         | 
| 103 123 | 
             
            - lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb
         | 
| @@ -175,6 +195,7 @@ files: | |
| 175 195 | 
             
            - lib/rodauth/rails/feature.rb
         | 
| 176 196 | 
             
            - lib/rodauth/rails/middleware.rb
         | 
| 177 197 | 
             
            - lib/rodauth/rails/railtie.rb
         | 
| 198 | 
            +
            - lib/rodauth/rails/tasks.rake
         | 
| 178 199 | 
             
            - lib/rodauth/rails/version.rb
         | 
| 179 200 | 
             
            - rodauth-rails.gemspec
         | 
| 180 201 | 
             
            homepage: https://github.com/janko/rodauth-rails
         |