module Doorkeeper::Orm::ActiveRecord::Mixins::Application

Public Instance Methods

as_json(options = {}) click to toggle source

Represents client as set of it’s attributes in JSON format. This is the right way how we want to override ActiveRecord to_json.

Respects privacy settings and serializes minimum set of attributes for public/private clients and full set for authorized owners.

@return [Hash] entity attributes for JSON

Calls superclass method
# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 75
def as_json(options = {})
  # if application belongs to some owner we need to check if it's the same as
  # the one passed in the options or check if we render the client as an owner
  if (respond_to?(:owner) && owner && owner == options[:current_resource_owner]) ||
     options[:as_owner]
    # Owners can see all the client attributes, fallback to ActiveModel serialization
    super
  else
    # if application has no owner or it's owner doesn't match one from the options
    # we render only minimum set of attributes that could be exposed to a public
    only = extract_serializable_attributes(options)
    super(options.merge(only: only))
  end
end
authorized_for_resource_owner?(resource_owner) click to toggle source
# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 90
def authorized_for_resource_owner?(resource_owner)
  Doorkeeper.configuration.authorize_resource_owner_for_client.call(self, resource_owner)
end
plaintext_secret() click to toggle source

We keep a volatile copy of the raw secret for initial communication The stored refresh_token may be mapped and not available in cleartext.

Some strategies allow restoring stored secrets (e.g. symmetric encryption) while hashing strategies do not, so you cannot rely on this value returning a present value for persisted tokens.

# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 59
def plaintext_secret
  if secret_strategy.allows_restoring_secrets?
    secret_strategy.restore_secret(self, :secret)
  else
    @raw_secret
  end
end
read_attribute_for_serialization(key) click to toggle source

We need to hook into this method to allow serializing plan-text secrets when secrets hashing enabled.

@param key [String] attribute name

Calls superclass method
# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 99
def read_attribute_for_serialization(key)
  return super unless key.to_s == "secret"

  plaintext_secret || secret
end
renew_secret() click to toggle source

Generates a new secret for this application, intended to be used for rotating the secret or in case of compromise.

@return [String] new transformed secret value

# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 48
def renew_secret
  @raw_secret = secret_generator.generate
  secret_strategy.store_secret(self, :secret, @raw_secret)
end

Private Instance Methods

client_serializable_attributes() click to toggle source

Collection of attributes that could be serialized for public. Override this method if you need additional attributes to be serialized.

@return [Array<String>] collection of serializable attributes

NOTE: ‘serializable_attributes` method already taken by Rails >= 6

# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 175
def client_serializable_attributes
  attributes = %w[id name created_at]
  attributes << "uid" unless confidential?
  attributes
end
enforce_scopes?() click to toggle source
# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 137
def enforce_scopes?
  Doorkeeper.config.enforce_configured_scopes?
end
extract_serializable_attributes(options = {}) click to toggle source

Helper method to extract collection of serializable attribute names considering serialization options (like ‘only`, `except` and so on).

@param options [Hash] serialization options

@return [Array<String>]

collection of attributes to be serialized using #as_json
# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 154
def extract_serializable_attributes(options = {})
  opts = options.try(:dup) || {}
  only = Array.wrap(opts[:only]).map(&:to_s)

  only = if only.blank?
           client_serializable_attributes
         else
           only & client_serializable_attributes
         end

  only -= Array.wrap(opts[:except]).map(&:to_s) if opts.key?(:except)
  only.uniq
end
generate_secret() click to toggle source
# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 122
def generate_secret
  return if secret.present? || !secret_required?

  renew_secret
end
generate_uid() click to toggle source
# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 118
def generate_uid
  self.uid = Doorkeeper::OAuth::Helpers::UniqueToken.generate if uid.blank?
end
scopes_match_configured() click to toggle source
# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 128
def scopes_match_configured
  if scopes.present? && !Doorkeeper::OAuth::Helpers::ScopeChecker.valid?(
    scope_str: scopes.to_s,
    server_scopes: Doorkeeper.config.scopes,
  )
    errors.add(:scopes, :not_match_configured)
  end
end
secret_generator() click to toggle source
# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 107
def secret_generator
  generator_name = Doorkeeper.config.application_secret_generator
  generator = generator_name.constantize

  return generator if generator.respond_to?(:generate)

  raise Errors::UnableToGenerateToken, "#{generator} does not respond to `.generate`."
rescue NameError
  raise Errors::TokenGeneratorNotFound, "#{generator_name} not found"
end
secret_required?() click to toggle source
# File lib/doorkeeper/orm/active_record/mixins/application.rb, line 141
def secret_required?
  confidential? ||
    !self.class.columns.detect { |column| column.name == "secret" }&.null
end