janko / rodauth-rails

Rails integration for Rodauth authentication framework
https://github.com/jeremyevans/rodauth
MIT License
565 stars 40 forks source link

rodauth attempts to connect to database during eager loading #244

Closed thedumbtechguy closed 7 months ago

thedumbtechguy commented 8 months ago

Hello

So I ran into this issue after pulling a fresh copy of my repo. I have a dockerized dev setup so I always need to setup the database again before I can continue. So either your database server is off, or you have not yet created the database can reproduce this issue.

When I execute any rails commands, e.g. rails db:create or rails c, it raises ActiveRecord::ConnectionNotEstablished(if the server is dead. other errors if the db is not create) because rodauth-rails is attempting to fetch some metadata from the database.

You can only get past it by commenting out configure RodauthAccount and include Rodauth::Rails.model calls.

The problem occurs because the rodauth files are autoloaded by rails, and during this, the calls above are evaluated. During both of these, there is an attempt to introspect the database leading to the failure.

Full Stack Trace ``` /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/postgresql_adapter.rb:87:in `rescue in new_client': connection to server at "127.0.0.1", port 5432 failed: FATAL: could not open file "global/pg_filenode.map": Operation not permitted (ActiveRecord::ConnectionNotEstablished) from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/postgresql_adapter.rb:77:in `new_client' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/postgresql_adapter.rb:37:in `postgresql_connection' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:656:in `public_send' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:656:in `new_connection' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:700:in `checkout_new_connection' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:679:in `try_to_checkout_new_connection' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:640:in `acquire_connection' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:341:in `checkout' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:181:in `connection' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_adapters/abstract/connection_handler.rb:211:in `retrieve_connection' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_handling.rb:313:in `retrieve_connection' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.7.2/lib/active_record/connection_handling.rb:280:in `connection' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/sequel-activerecord_connection-1.3.1/lib/sequel/extensions/activerecord_connection.rb:178:in `activerecord_connection' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/sequel-activerecord_connection-1.3.1/lib/sequel/extensions/activerecord_connection.rb:165:in `activerecord_lock' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/sequel-activerecord_connection-1.3.1/lib/sequel/extensions/activerecord_connection.rb:37:in `synchronize' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/sequel-activerecord_connection-1.3.1/lib/sequel/extensions/activerecord_connection/postgres.rb:7:in `synchronize' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/sequel-5.74.0/lib/sequel/database/transactions.rb:197:in `transaction' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/sequel-activerecord_connection-1.3.1/lib/sequel/extensions/activerecord_connection/postgres.rb:28:in `transaction' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/sequel-5.74.0/lib/sequel/database/query.rb:206:in `table_exists?' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rodauth-2.32.0/lib/rodauth/features/base.rb:431:in `post_configure' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rodauth-2.32.0/lib/rodauth/features/email_base.rb:22:in `post_configure' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rodauth-2.32.0/lib/rodauth/features/internal_request.rb:383:in `post_configure' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rodauth-2.32.0/lib/rodauth/features/path_class_methods.rb:6:in `post_configure' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rodauth-2.32.0/lib/rodauth.rb:64:in `configure' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/roda-3.74.0/lib/roda.rb:300:in `plugin' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rodauth-rails-1.12.0/lib/rodauth/rails/app.rb:33:in `configure' from /Users/me/code/plutonium/my_app/app/misc/rodauth_app.rb:5:in `' from /Users/me/code/plutonium/my_app/app/misc/rodauth_app.rb:3:in `
' from :37:in `require' from :37:in `require' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.12/lib/zeitwerk/kernel.rb:30:in `require' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.0.7.2/lib/active_support/inflector/methods.rb:278:in `const_get' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.0.7.2/lib/active_support/inflector/methods.rb:278:in `constantize' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.0.7.2/lib/active_support/core_ext/string/inflections.rb:74:in `constantize' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rodauth-rails-1.12.0/lib/rodauth/rails.rb:98:in `app' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rodauth-rails-1.12.0/lib/rodauth/rails.rb:57:in `model' from /Users/me/code/plutonium/my_app/app/models/user.rb:17:in `' from /Users/me/code/plutonium/my_app/app/models/user.rb:16:in `
' from :37:in `require' from :37:in `require' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.12/lib/zeitwerk/kernel.rb:30:in `require' from /Users/me/code/plutonium/my_app/spec/factories/user.auto.rb:8:in `block in
' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/factory_bot-6.2.1/lib/factory_bot/syntax/default.rb:37:in `instance_eval' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/factory_bot-6.2.1/lib/factory_bot/syntax/default.rb:37:in `run' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/factory_bot-6.2.1/lib/factory_bot/syntax/default.rb:7:in `define' from /Users/me/code/plutonium/my_app/spec/factories/user.auto.rb:6:in `
' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/factory_bot-6.2.1/lib/factory_bot/find_definitions.rb:20:in `load' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/factory_bot-6.2.1/lib/factory_bot/find_definitions.rb:20:in `block (2 levels) in find_definitions' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/factory_bot-6.2.1/lib/factory_bot/find_definitions.rb:19:in `each' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/factory_bot-6.2.1/lib/factory_bot/find_definitions.rb:19:in `block in find_definitions' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/factory_bot-6.2.1/lib/factory_bot/find_definitions.rb:15:in `each' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/factory_bot-6.2.1/lib/factory_bot/find_definitions.rb:15:in `find_definitions' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/factory_bot_rails-6.2.0/lib/factory_bot_rails/railtie.rb:22:in `block in ' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.0.7.2/lib/active_support/lazy_load_hooks.rb:92:in `block in execute_hook' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.0.7.2/lib/active_support/lazy_load_hooks.rb:85:in `with_execution_control' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.0.7.2/lib/active_support/lazy_load_hooks.rb:90:in `execute_hook' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.0.7.2/lib/active_support/lazy_load_hooks.rb:76:in `block in run_load_hooks' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.0.7.2/lib/active_support/lazy_load_hooks.rb:75:in `each' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.0.7.2/lib/active_support/lazy_load_hooks.rb:75:in `run_load_hooks' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/application/finisher.rb:87:in `block in ' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/initializable.rb:32:in `instance_exec' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/initializable.rb:32:in `run' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/initializable.rb:61:in `block in run_initializers' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/3.2.0/tsort.rb:228:in `block in tsort_each' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/3.2.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/3.2.0/tsort.rb:431:in `each_strongly_connected_component_from' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/3.2.0/tsort.rb:349:in `block in each_strongly_connected_component' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/3.2.0/tsort.rb:347:in `each' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/3.2.0/tsort.rb:347:in `call' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/3.2.0/tsort.rb:347:in `each_strongly_connected_component' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/3.2.0/tsort.rb:226:in `tsort_each' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/3.2.0/tsort.rb:205:in `tsort_each' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/initializable.rb:60:in `run_initializers' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/application.rb:372:in `initialize!' from /Users/me/code/plutonium/my_app/config/environment.rb:7:in `
' from :37:in `require' from :37:in `require' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.12/lib/zeitwerk/kernel.rb:38:in `require' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/application.rb:348:in `require_environment!' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/command/actions.rb:28:in `require_environment!' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/command/actions.rb:15:in `require_application_and_environment!' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/commands/console/console_command.rb:105:in `perform' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/thor-1.3.0/lib/thor/command.rb:28:in `run' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/thor-1.3.0/lib/thor/invocation.rb:127:in `invoke_command' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/thor-1.3.0/lib/thor.rb:527:in `dispatch' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/command/base.rb:87:in `perform' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/command.rb:48:in `invoke' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.7.2/lib/rails/commands.rb:18:in `
' from :37:in `require' from :37:in `require' from /Users/me/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require' from bin/rails:4:in `
' ```
janko commented 7 months ago

Thank you for the detailed report. This is caused by Rodauth checking the accounts table schema whether the primary key is an integer, so that it can convert account IDs in tokens. You can have Rodauth skip this query by adding the following to your Rodauth configuration:

convert_token_id_to_integer? true

I will also add this to the default configuration generated by rodauth:install when UUIDs are not used.

thedumbtechguy commented 7 months ago

That worked! Thank you very much.