You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The change from #1602 is causing rails database migrations to fail if custom_access_token_attributes are configured and table doesn't exist
Expected behavior
Rails migrations should not fail if specific table columns used by doorkeeper are not present.
Actual behavior
Migrations fails if doorkeeper is configured with custom_access_token_attributes and any of database/table/column don't exist.
If I comment out the custom_access_token_attributes config, migrations work as expected.
(database doesn't exist)
$ rails db:create
rails aborted!
ActiveRecord::NoDatabaseError: We could not find your database: main_database_dev_master. Which can be found in the database configuration file located at config/database.yml.
To resolve this issue:
- Did you create the database for this app, or delete it? You may need to create your database.
- Has the database name changed? Check your database.yml config has the correct database name.
To create your database, run:
bin/rails db:create
/app-core/config/initializers/doorkeeper.rb:3:in `<main>'
/app-core/config/environment.rb:7:in `<main>'
(database exists but is empty)
** Invoke db:create (first_time)
** Invoke db:load_config (first_time)
** Invoke environment (first_time)
** Execute environment
rails aborted!
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "oauth_access_tokens" does not exist
LINE 9: WHERE a.attrelid = '"oauth_access_tokens"'::regclass
^
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:19:in `exec'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:19:in `block (2 levels) in query'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.4.2/lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.4.2/lib/active_support/dependencies/interlock.rb:41:in `permit_concurrent_loads'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:18:in `block in query'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.4.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.4.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.4.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.4.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/abstract_adapter.rb:765:in `block in log'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.4.2/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/abstract_adapter.rb:756:in `log'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:17:in `query'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/postgresql_adapter.rb:916:in `column_definitions'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/abstract/schema_statements.rb:116:in `columns'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/schema_cache.rb:117:in `block in columns'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/schema_cache.rb:116:in `fetch'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/schema_cache.rb:116:in `columns'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/schema_cache.rb:125:in `block in columns_hash'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/schema_cache.rb:124:in `fetch'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/connection_adapters/schema_cache.rb:124:in `columns_hash'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/model_schema.rb:580:in `load_schema!'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/attributes.rb:264:in `load_schema!'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/encryption/encryptable_record.rb:122:in `load_schema!'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/model_schema.rb:566:in `block in load_schema'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/model_schema.rb:563:in `synchronize'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/model_schema.rb:563:in `load_schema'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/model_schema.rb:429:in `attribute_types'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4.2/lib/active_record/attribute_methods.rb:183:in `has_attribute?'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/doorkeeper-5.6.5/lib/doorkeeper/config/validations.rb:60:in `block (2 levels) in validate_custom_access_token_attributes'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/doorkeeper-5.6.5/lib/doorkeeper/config/validations.rb:59:in `each'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/doorkeeper-5.6.5/lib/doorkeeper/config/validations.rb:59:in `block in validate_custom_access_token_attributes'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/doorkeeper-5.6.5/lib/doorkeeper/config/validations.rb:58:in `each'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/doorkeeper-5.6.5/lib/doorkeeper/config/validations.rb:58:in `validate_custom_access_token_attributes'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/doorkeeper-5.6.5/lib/doorkeeper/config/validations.rb:14:in `validate!'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/doorkeeper-5.6.5/lib/doorkeeper/config/abstract_builder.rb:23:in `build'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/doorkeeper-5.6.5/lib/doorkeeper.rb:121:in `configure'
/app-core/config/initializers/doorkeeper.rb:3:in `<main>'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/engine.rb:667:in `load'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/engine.rb:667:in `block in load_config_initializer'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.4.2/lib/active_support/notifications.rb:208:in `instrument'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/engine.rb:666:in `load_config_initializer'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/engine.rb:620:in `block (2 levels) in <class:Engine>'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/engine.rb:619:in `each'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/engine.rb:619:in `block in <class:Engine>'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/initializable.rb:32:in `instance_exec'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/initializable.rb:32:in `run'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/initializable.rb:61:in `block in run_initializers'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:228:in `block in tsort_each'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:422:in `block (2 levels) in each_strongly_connected_component_from'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:431:in `each_strongly_connected_component_from'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:421:in `block in each_strongly_connected_component_from'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/initializable.rb:50:in `each'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/initializable.rb:50:in `tsort_each_child'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:415:in `call'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:415:in `each_strongly_connected_component_from'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:349:in `block in each_strongly_connected_component'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:347:in `each'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:347:in `call'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:347:in `each_strongly_connected_component'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:226:in `tsort_each'
/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:205:in `tsort_each'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/initializable.rb:60:in `run_initializers'
/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4.2/lib/rails/application.rb:372:in `initialize!'
/app-core/config/environment.rb:7:in `<main>'
System configuration
Doorkeeper initializer:
# config/initializers/doorkeeper.rb# frozen_string_literal: trueDoorkeeper.configuredo# Change the ORM that doorkeeper will use (needs plugins)orm:active_record# This block will be called to check whether the resource owner is authenticated or not.# oidc --> This callback needs to returns a falsey value if the current user can't be determined:resource_owner_authenticatordoifcurrent_usercurrent_userelsewarden.authenticate!(scope: :user)nilendend# If you didn't skip applications controller from Doorkeeper routes in your application routes.rb# file then you need to declare this block in order to restrict access to the web interface for# adding oauth authorized applications. In other case it will return 403 Forbidden response# every time somebody will try to access the admin web interface.## admin_authenticator do# # Put your admin authentication logic here.# # Example implementation:## if current_user# head :forbidden unless current_user.admin?# else# redirect_to sign_in_url# end# end# admin_authenticator do# current_user || warden.authenticate!(scope: :user)# end# If you are planning to use Doorkeeper in Rails 5 API-only application, then you might# want to use API mode that will skip all the views management and change the way how# Doorkeeper responds to a requests.## api_only# Enforce token request content type to application/x-www-form-urlencoded.# It is not enabled by default to not break prior versions of the gem.## enforce_content_type# Authorization Code expiration time (default 10 minutes).## authorization_code_expires_in 10.minutes# Access token expiration time (default 2 hours).# If you want to disable expiration, set this to nil.## access_token_expires_in 2.hours# Assign custom TTL for access tokens. Will be used instead of access_token_expires_in# option if defined. `context` has the following properties available## `client` - the OAuth client application (see Doorkeeper::OAuth::Client)# `grant_type` - the grant type of the request (see Doorkeeper::OAuth)# `scopes` - the requested scopes (see Doorkeeper::OAuth::Scopes)## custom_access_token_expires_in do |context|# context.client.application.additional_settings.implicit_oauth_expiration# end# Use a custom class for generating the access token.# See https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator## access_token_generator '::Doorkeeper::JWT'# The controller Doorkeeper::ApplicationController inherits from.# Defaults to ActionController::Base.# See https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller#base_controller"CustomDoorkeeper::BaseController"base_metal_controller"CustomDoorkeeper::MetalController"# Reuse access token for the same resource owner within an application (disabled by default).## This option protects your application from creating new tokens before old valid one becomes# expired so your database doesn't bloat. Keep in mind that when this option is `on` Doorkeeper# doesn't updates existing token expiration time, it will create a new token instead.# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383## You can not enable this option together with +hash_token_secrets+.## reuse_access_token# Set a limit for token_reuse if using reuse_access_token option## This option limits token_reusability to some extent.# If not set then access_token will be reused unless it expires.# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189## This option should be a percentage(i.e. (0,100])## token_reuse_limit 100# Hash access and refresh tokens before persisting them.# This will disable the possibility to use +reuse_access_token+# since plain values can no longer be retrieved.## Note: If you are already a user of doorkeeper and have existing tokens# in your installation, they will be invalid without enabling the additional# setting `fallback_to_plain_secrets` below.## hash_token_secrets# By default, token secrets will be hashed using the# +Doorkeeper::Hashing::SHA256+ strategy.## If you wish to use another hashing implementation, you can override# this strategy as follows:## hash_token_secrets using: '::Doorkeeper::Hashing::MyCustomHashImpl'## Keep in mind that changing the hashing function will invalidate all existing# secrets, if there are any.# Hash application secrets before persisting them.## hash_application_secrets## By default, applications will be hashed# with the +Doorkeeper::SecretStoring::SHA256+ strategy.## If you wish to use bcrypt for application secret hashing, uncomment# this line instead:## hash_application_secrets using: '::Doorkeeper::SecretStoring::BCrypt'# When the above option is enabled,# and a hashed token or secret is not found,# you can allow to fall back to another strategy.# For users upgrading doorkeeper and wishing to enable hashing,# you will probably want to enable the fallback to plain tokens.## This will ensure that old access tokens and secrets# will remain valid even if the hashing above is enabled.## fallback_to_plain_secrets# Issue access tokens with refresh token (disabled by default), you may also# pass a block which accepts `context` to customize when to give a refresh# token or not. Similar to `custom_access_token_expires_in`, `context` has# the properties:## `client` - the OAuth client application (see Doorkeeper::OAuth::Client)# `grant_type` - the grant type of the request (see Doorkeeper::OAuth)# `scopes` - the requested scopes (see Doorkeeper::OAuth::Scopes)#use_refresh_token# Provide support for an owner to be assigned to each registered application (disabled by default)# Optional parameter confirmation: true (default false) if you want to enforce ownership of# a registered application# Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support#enable_application_ownerconfirmation: true# Define access token scopes for your provider# For more information go to# https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes#default_scopes:openidoptional_scopes:email,:full_name# Define scopes_by_grant_type to restrict only certain scopes for grant_type# By default, all the scopes will be available for all the grant types.## Keys to this hash should be the name of grant_type and# values should be the array of scopes for that grant type.# Note: scopes should be from configured_scopes(i.e. deafult or optional)## scopes_by_grant_type password: [:write], client_credentials: [:update]# Forbids creating/updating applications with arbitrary scopes that are# not in configuration, i.e. `default_scopes` or `optional_scopes`.# (disabled by default)#enforce_configured_scopes# Change the way client credentials are retrieved from the request object.# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then# falls back to the `:client_id` and `:client_secret` params from the `params` object.# Check out https://github.com/doorkeeper-gem/doorkeeper/wiki/Changing-how-clients-are-authenticated# for more information on customization## client_credentials :from_basic, :from_params# Change the way access token is authenticated from the request object.# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then# falls back to the `:access_token` or `:bearer_token` params from the `params` object.# Check out https://github.com/doorkeeper-gem/doorkeeper/wiki/Changing-how-clients-are-authenticated# for more information on customization## access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param# Change the native redirect uri for client apps# When clients register with the following redirect uri, they won't be redirected to any server and# the authorizationcode will be displayed within the provider# The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL# (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)## native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'# Forces the usage of the HTTPS protocol in non-native redirect uris (enabled# by default in non-development environments). OAuth2 delegates security in# communication to the HTTPS protocol so it is wise to keep this enabled.## Callable objects such as proc, lambda, block or any object that responds to# #call can be used in order to allow conditional checks (to allow non-SSL# redirects to localhost for example).#force_ssl_in_redirect_uri{ !(Rails.env.development? || Rails.env.test?)}## force_ssl_in_redirect_uri { |uri| uri.host != 'localhost' }# Specify what redirect URI's you want to block during Application creation.# Any redirect URI is whitelisted by default.## You can use this option in order to forbid URI's with 'javascript' scheme# for example.## forbid_redirect_uri { |uri| uri.scheme.to_s.downcase == 'javascript' }# Specify how authorization errors should be handled.# By default, doorkeeper renders json errors when access token# is invalid, expired, revoked or has invalid scopes.## If you want to render error response yourself (i.e. rescue exceptions),# set handle_auth_errors to `:raise` and rescue Doorkeeper::Errors::InvalidToken# or following specific errors:## Doorkeeper::Errors::TokenForbidden, Doorkeeper::Errors::TokenExpired,# Doorkeeper::Errors::TokenRevoked, Doorkeeper::Errors::TokenUnknown## handle_auth_errors :raise# Customize token introspection response.# Allows to add your own fields to default one that are required by the OAuth spec# for the introspection response. It could be `sub`, `aud` and so on.# This configuration option can be a proc, lambda or any Ruby object responds# to `.call` method and result of it's invocation must be a Hash.## custom_introspection_response do |token, context|# {# "sub": "Z5O3upPC88QrAjx00dis",# "aud": "https://protected.example.net/resource",# "username": User.find(token.resource_owner_id).username# }# end## or## custom_introspection_response CustomIntrospectionResponder# Specify what grant flows are enabled in array of Strings. The valid# strings and the flows they enable are:## "authorization_code" => Authorization Code Grant Flow# "implicit" => Implicit Grant Flow# "password" => Resource Owner Password Credentials Grant Flow# "client_credentials" => Client Credentials Grant Flow## If not specified, Doorkeeper enables authorization_code and# client_credentials.## implicit and password grant flows have risks that you should understand# before enabling:# http://tools.ietf.org/html/rfc6819#section-4.4.2# http://tools.ietf.org/html/rfc6819#section-4.4.3#grant_flows%w(authorization_codeimplicit_oidc)# Hook into the strategies' request & response life-cycle in case your# application needs advanced customization or logging:## before_successful_strategy_response do |request|# puts "BEFORE HOOK FIRED! #{request}"# end## after_successful_strategy_response do |request, response|# puts "AFTER HOOK FIRED! #{request}, #{response}"# end# Hook into Authorization flow in order to implement Single Sign Out# or add any other functionality.## before_successful_authorization do |controller|# Rails.logger.info(params.inspect)# end## after_successful_authorization do |controller|# controller.session[:logout_urls] <<# Doorkeeper::Application# .find_by(controller.request.params.slice(:redirect_uri))# .logout_uri# end# Under some circumstances you might want to have applications auto-approved,# so that the user skips the authorization step.# For example if dealing with a trusted application.## skip_authorization do |resource_owner, client|# client.superapp? or resource_owner.admin?# end# UNCOMMENT WHEN POC IS STABLE.skip_authorizationdofalseend# WWW-Authenticate Realm (default "Doorkeeper").## realm "Doorkeeper"custom_access_token_attributes%i(act_as)end
Steps to reproduce
The change from #1602 is causing rails database migrations to fail if
custom_access_token_attributes
are configured and table doesn't existExpected behavior
Rails migrations should not fail if specific table columns used by doorkeeper are not present.
Actual behavior
Migrations fails if doorkeeper is configured with
custom_access_token_attributes
and any of database/table/column don't exist.If I comment out the
custom_access_token_attributes
config, migrations work as expected.(database exists but is empty)
System configuration
Doorkeeper initializer:
Ruby version:
ruby 3.1.2p20
Gemfile.lock:
Gemfile.lock content
The text was updated successfully, but these errors were encountered: