doorkeeper-gem / doorkeeper

Doorkeeper is an OAuth 2 provider for Ruby on Rails / Grape.
https://doorkeeper.gitbook.io/guides/
MIT License
5.32k stars 1.07k forks source link

The owner association doesn't come through when subclassing Doorkeeper::Application with custom model #1455

Closed connorshea closed 3 years ago

connorshea commented 3 years ago

Steps to reproduce

# Class like this
class OauthApplication < ApplicationRecord
  include ::Doorkeeper::Orm::ActiveRecord::Mixins::Application
end

# or like this
class OauthApplication < Doorkeeper::Application
end
Doorkeeper.configure do
  application_class 'OauthApplication'
end

And then run the specs for the application.

Expected behavior

The specs should pass and not print any deprecation warnings.

Actual behavior

I get a deprecation warning about constant autoloading when running my RSpec tests, though oddly not when running the server?

DEPRECATION WARNING: Initialization autoloaded the constants ApplicationRecord and OauthApplication.

Being able to do this is deprecated. Autoloading during initialization is going
to be an error condition in future versions of Rails.

Reloading does not reboot the application, and therefore code executed during
initialization does not run again. So, if you reload ApplicationRecord, for example,
the expected changes won't be reflected in that stale Class object.

These autoloaded constants have been unloaded.

Please, check the "Autoloading and Reloading Constants" guide for solutions.
 (called from <top (required)> at /Users/connorshea/Programming/vglist/config/environment.rb:6)

(FWIW, the line at environment.rb:6 is Rails.application.initialize!)

But the main issue is that I have problems with setting or accessing the owner association on instances of OauthApplication.

12) Users API Query for data on users returns data for users when listing
      Failure/Error: let(:application) { build(:application, owner: user) }

      NoMethodError:
        undefined method `owner=' for #<OauthApplication:0x00007f82852c7db0>

If I had to make a guess, I think it might be because the models are hardcoded here?: https://github.com/doorkeeper-gem/doorkeeper/blob/b8abbe6bb8646232b9d5065c27de9e1e78e974b9/lib/doorkeeper/orm/active_record.rb#L52-L58

I would think that - since my OauthApplication model is a subclass of Doorkeeper::Application - it would also have the owner relationship on the subclass, but apparently not.

System configuration

Doorkeeper initializer:

# config/initializers/doorkeeper.rb
# frozen_string_literal: true

Doorkeeper.configure do
  # Change the ORM that doorkeeper will use (requires ORM extensions installed).
  # Check the list of supported ORMs here: https://github.com/doorkeeper-gem/doorkeeper#orms
  orm :active_record

  # This block will be called to check whether the resource owner is authenticated or not.
  resource_owner_authenticator do
    current_user || warden.authenticate!(scope: :user)
  end

  # 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
    if current_user
      head :forbidden unless current_user.admin?
    else
      redirect_to new_user_session_url
    end
  end

  application_class 'OauthApplication'

  base_controller 'ApplicationController'

  hash_application_secrets using: '::Doorkeeper::SecretStoring::BCrypt'

  enable_application_owner confirmation: true

  default_scopes :read
  optional_scopes :write

  scopes_by_grant_type(
    implicit: [:read],
    authorization_code: [:read, :write]
  )
  enforce_configured_scopes

end

Ruby version: 2.6.6

Gemfile.lock:

Gemfile.lock content ``` GEM remote: https://rubygems.org/ specs: actioncable (6.0.3.4) actionpack (= 6.0.3.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) actionmailbox (6.0.3.4) actionpack (= 6.0.3.4) activejob (= 6.0.3.4) activerecord (= 6.0.3.4) activestorage (= 6.0.3.4) activesupport (= 6.0.3.4) mail (>= 2.7.1) actionmailer (6.0.3.4) actionpack (= 6.0.3.4) actionview (= 6.0.3.4) activejob (= 6.0.3.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) actionpack (6.0.3.4) actionview (= 6.0.3.4) activesupport (= 6.0.3.4) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) actiontext (6.0.3.4) actionpack (= 6.0.3.4) activerecord (= 6.0.3.4) activestorage (= 6.0.3.4) activesupport (= 6.0.3.4) nokogiri (>= 1.8.5) actionview (6.0.3.4) activesupport (= 6.0.3.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) active_storage_validations (0.9.0) rails (>= 5.2.0) activejob (6.0.3.4) activesupport (= 6.0.3.4) globalid (>= 0.3.6) activemodel (6.0.3.4) activesupport (= 6.0.3.4) activerecord (6.0.3.4) activemodel (= 6.0.3.4) activesupport (= 6.0.3.4) activestorage (6.0.3.4) actionpack (= 6.0.3.4) activejob (= 6.0.3.4) activerecord (= 6.0.3.4) marcel (~> 0.3.1) activesupport (6.0.3.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) ast (2.4.1) aws-eventstream (1.1.0) aws-partitions (1.390.0) aws-sdk-core (3.109.2) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) aws-sdk-kms (1.39.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-s3 (1.83.2) aws-sdk-core (~> 3, >= 3.109.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) aws-sigv4 (1.2.2) aws-eventstream (~> 1, >= 1.0.2) bcrypt (3.1.16) better_errors (2.9.1) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) bindex (0.8.1) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) bootsnap (1.5.1) msgpack (~> 1.0) builder (3.2.4) bullet (6.1.0) activesupport (>= 3.0.0) uniform_notifier (~> 1.11) byebug (11.1.3) capybara (3.34.0) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (~> 1.5) xpath (~> 3.2) childprocess (3.0.0) choice (0.2.0) coderay (1.1.3) colorize (0.8.1) commander (4.5.2) highline (~> 2.0.0) concurrent-ruby (1.1.7) connection_pool (2.2.3) crass (1.0.6) database_cleaner (1.8.5) debug_inspector (0.0.3) devise (4.7.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) diff-lcs (1.4.4) docile (1.3.2) doorkeeper (5.4.0) railties (>= 5) dotenv (2.7.6) dotenv-rails (2.7.6) dotenv (= 2.7.6) railties (>= 3.2) ebnf (2.1.2) htmlentities (~> 4.3) rdf (~> 3.1) scanf (~> 1.0) sxp (~> 1.1) erubi (1.10.0) factory_bot (6.1.0) activesupport (>= 5.0.0) factory_bot_rails (6.1.0) factory_bot (~> 6.1.0) railties (>= 5.0.0) faker (2.15.1) i18n (>= 1.6, < 2) faraday (1.1.0) multipart-post (>= 1.2, < 3) ruby2_keywords ffi (1.13.1) friendly_id (5.4.1) activerecord (>= 4.0.0) fuubar (2.5.0) rspec-core (~> 3.0) ruby-progressbar (~> 1.4) globalid (0.4.2) activesupport (>= 4.2.0) graphql (1.11.6) graphql-rails_logger (1.2.2) actionpack (> 5.0) activesupport (> 5.0) railties (> 5.0) rouge (~> 3.0) hamster (3.0.0) concurrent-ruby (~> 1.0) highline (2.0.3) htmlentities (4.3.4) i18n (1.8.5) concurrent-ruby (~> 1.0) image_processing (1.12.1) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) inline_svg (1.7.1) activesupport (>= 3.0) nokogiri (>= 1.6) invisible_captcha (1.1.0) rails (>= 4.2) jbuilder (2.10.1) activesupport (>= 5.0.0) jmespath (1.4.0) kaminari (1.2.1) activesupport (>= 4.1.0) kaminari-actionview (= 1.2.1) kaminari-activerecord (= 1.2.1) kaminari-core (= 1.2.1) kaminari-actionview (1.2.1) actionview kaminari-core (= 1.2.1) kaminari-activerecord (1.2.1) activerecord kaminari-core (= 1.2.1) kaminari-core (1.2.1) launchy (2.5.0) addressable (~> 2.7) link_header (0.0.8) listen (3.3.3) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) loofah (2.8.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) marcel (0.3.3) mimemagic (~> 0.3.2) method_source (1.0.0) mimemagic (0.3.5) mini_magick (4.11.0) mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.14.2) msgpack (1.3.3) multipart-post (2.1.1) net-http-persistent (3.1.0) connection_pool (~> 2.2) nio4r (2.5.4) nokogiri (1.10.10) mini_portile2 (~> 2.4.0) orm_adapter (0.5.0) parallel (1.20.1) parlour (2.1.0) commander (~> 4.5) parser rainbow (~> 3.0) sorbet-runtime (>= 0.5) parser (2.7.2.0) ast (~> 2.4.1) pg (1.2.3) pg_search (2.3.5) activerecord (>= 5.2) activesupport (>= 5.2) polyfill (1.8.0) pry (0.13.1) coderay (~> 1.1) method_source (~> 1.0) pry-rails (0.3.9) pry (>= 0.10.4) public_suffix (4.0.6) puma (5.1.0) nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) pundit-matchers (1.6.0) rspec-rails (>= 3.0.0) rack (2.2.3) rack-cors (1.1.1) rack (>= 2.0.0) rack-proxy (0.6.5) rack rack-test (1.1.0) rack (>= 1.0, < 3) rails (6.0.3.4) actioncable (= 6.0.3.4) actionmailbox (= 6.0.3.4) actionmailer (= 6.0.3.4) actionpack (= 6.0.3.4) actiontext (= 6.0.3.4) actionview (= 6.0.3.4) activejob (= 6.0.3.4) activemodel (= 6.0.3.4) activerecord (= 6.0.3.4) activestorage (= 6.0.3.4) activesupport (= 6.0.3.4) bundler (>= 1.3.0) railties (= 6.0.3.4) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-erd (1.6.0) activerecord (>= 4.2) activesupport (>= 4.2) choice (~> 0.2.0) ruby-graphviz (~> 1.2) rails-html-sanitizer (1.3.0) loofah (~> 2.3) railties (6.0.3.4) actionpack (= 6.0.3.4) activesupport (= 6.0.3.4) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) rainbow (3.0.0) rake (13.0.1) rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) rdf (3.1.7) hamster (~> 3.0) link_header (~> 0.0, >= 0.0.8) rdf-aggregate-repo (3.1.0) rdf (~> 3.1) rdf-xsd (3.1.0) rdf (~> 3.1) regexp_parser (1.8.2) responders (3.0.1) actionpack (>= 5.0) railties (>= 5.0) rexml (3.2.4) rouge (3.25.0) rspec-core (3.10.0) rspec-support (~> 3.10.0) rspec-expectations (3.10.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) rspec-mocks (3.10.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) rspec-rails (4.0.1) actionpack (>= 4.2) activesupport (>= 4.2) railties (>= 4.2) rspec-core (~> 3.9) rspec-expectations (~> 3.9) rspec-mocks (~> 3.9) rspec-support (~> 3.9) rspec-support (3.10.0) rubocop (1.4.2) parallel (~> 1.10) parser (>= 2.7.1.5) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8) rexml rubocop-ast (>= 1.1.1) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) rubocop-ast (1.3.0) parser (>= 2.7.1.5) rubocop-performance (1.9.1) rubocop (>= 0.90.0, < 2.0) rubocop-ast (>= 0.4.0) rubocop-rails (2.8.1) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 0.87.0) rubocop-rspec (2.0.1) rubocop (~> 1.0) rubocop-ast (>= 1.1.0) ruby-graphviz (1.2.5) rexml ruby-progressbar (1.10.1) ruby-vips (2.0.17) ffi (~> 1.9) ruby2_keywords (0.0.2) rubyzip (2.3.0) safe_type (1.1.1) scanf (1.0.0) selenium-webdriver (3.142.7) childprocess (>= 0.5, < 4.0) rubyzip (>= 1.2.2) semantic_range (2.3.0) sentry-raven (3.1.1) faraday (>= 1.0) shoulda-matchers (4.4.1) activesupport (>= 4.2.0) simplecov (0.20.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) simplecov-html (0.12.3) simplecov_json_formatter (0.1.2) sorbet (0.5.6111) sorbet-static (= 0.5.6111) sorbet-coerce (0.2.7) polyfill (~> 1.8) safe_type (~> 1.1, >= 1.1.1) sorbet (>= 0.4.4704) sorbet-runtime (>= 0.4.4704) sorbet-rails (0.7.1) method_source (>= 0.9.2) parlour (~> 2.0) parser (>= 2.7) sorbet-coerce (>= 0.2.6) sorbet-runtime (>= 0.5) sorbet-runtime (0.5.6111) sorbet-static (0.5.6111-universal-darwin-14) sparql (3.1.3) builder (~> 3.2) ebnf (>= 1.1) rdf (~> 3.1, >= 3.1.2) rdf-aggregate-repo (~> 3.1) rdf-xsd (~> 3.1) sparql-client (~> 3.1) sxp (~> 1.1) sparql-client (3.1.0) net-http-persistent (~> 3.1) rdf (~> 3.1) spoom (1.0.7) colorize sorbet (~> 0.5.5) sorbet-runtime thor (>= 0.19.2) spring (2.1.1) spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) spring (>= 1.2, < 3.0) sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) sprockets-rails (3.2.2) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) sxp (1.1.0) rdf (~> 3.1) tapioca (0.4.10) parlour (>= 2.1.0) pry (>= 0.12.2) sorbet-runtime sorbet-static (>= 0.4.4471) spoom thor (>= 0.19.2) thor (1.0.1) thread_safe (0.3.6) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) tzinfo (1.2.8) thread_safe (~> 0.1) unicode-display_width (1.7.0) uniform_notifier (1.13.0) warden (1.2.9) rack (>= 2.0.9) web-console (4.1.0) actionview (>= 6.0.0) activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) webdrivers (4.4.1) nokogiri (~> 1.6) rubyzip (>= 1.3.0) selenium-webdriver (>= 3.0, < 4.0) webpacker (5.2.1) activesupport (>= 5.2) rack-proxy (>= 0.6.1) railties (>= 5.2) semantic_range (>= 2.3.0) websocket-driver (0.7.3) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) zeitwerk (2.4.2) PLATFORMS ruby DEPENDENCIES active_storage_validations (~> 0.9) addressable (~> 2.7.0) aws-sdk-s3 (~> 1.66) better_errors (~> 2.9) binding_of_caller (~> 0.8) bootsnap (>= 1.1.0) bullet (~> 6.1) byebug capybara (~> 3.34) database_cleaner (~> 1.8) devise (~> 4.7) doorkeeper (~> 5.4) dotenv-rails (~> 2.7) factory_bot_rails (~> 6.1) faker (~> 2.15) friendly_id (~> 5.4.1) fuubar (~> 2.5.0) graphql (~> 1.11.6) graphql-rails_logger (~> 1.2.2) image_processing (~> 1.12) inline_svg (~> 1.7) invisible_captcha (~> 1.1.0) jbuilder (~> 2.10) kaminari (~> 1.2) launchy (~> 2.5) listen (>= 3.0.5, < 3.4) pg (~> 1.2) pg_search (~> 2.3) pry (~> 0.13) pry-rails (~> 0.3) puma (~> 5.1) pundit (~> 2.1) pundit-matchers (~> 1.6.0) rack-cors (~> 1.1) rails (~> 6.0.3) rails-erd (~> 1.6) rspec-rails (~> 4.0) rubocop (~> 1.4) rubocop-performance (~> 1.9) rubocop-rails (~> 2.8) rubocop-rspec (~> 2.0) ruby-progressbar (~> 1.10) selenium-webdriver (~> 3.142) sentry-raven (~> 3.1) shoulda-matchers (= 4.4.1) simplecov (~> 0.20) sorbet (~> 0.5) sorbet-rails (~> 0.7) sorbet-runtime (~> 0.5) sparql (~> 3.1.3) spring (~> 2.1) spring-watcher-listen (~> 2.0.0) tapioca (~> 0.4.10) turbolinks (~> 5) web-console (~> 4.1.0) webdrivers (~> 4.4) webpacker (~> 5.2.1) RUBY VERSION ruby 2.6.2p47 BUNDLED WITH 2.1.4 ```
connorshea commented 3 years ago

FWIW, my Rails app is open source, I've created a branch exemplifying this issue here: https://github.com/connorshea/vglist/tree/doorkeeper-issue-example

Sorry for all the noise with Sorbet and such, I've tried to keep it in its own separate commit so it doesn't cause problems with trying to understand what's changing in any given commit.

nbulaj commented 3 years ago

Cloned your repo @connorshea , saw the issue. Relates to some Rails autoloading or constant resolution I think, because while debugging I found that OauthApplication isn't the same object as Doorkeeper.config.application_model (but looks like the same, weird). I saw that after model initialized (with Ownership module included) it's then initializes one more time and now without required module O_o but I still don't sure the reasons