Repository: rails/rails
File: activerecord/lib/active_record/signed_id.rb (Ruby)

Code before:
# frozen_string_literal: true

module ActiveRecord
  # = Active Record Signed Id
  module SignedId
    extend ActiveSupport::Concern

    included do
      ##
      # :singleton-method:
      # Set the secret used for the signed id verifier instance when using Active Record outside of \Rails.
      # Within \Rails, this is automatically set using the \Rails application key generator.
      class_attribute :signed_id_verifier_secret, instance_writer: false

      # :nodoc:
      class_attribute :_signed_id_verifier, instance_accessor: false, instance_predicate: false

      class << self
        alias_method :original_signed_id_verifier_secret=, :signed_id_verifier_secret=
        # :nodoc:
        def signed_id_verifier_secret=(secret)
          ActiveRecord.deprecator.warn(<<~MSG)
            ActiveRecord::Base.signed_id_verifier_secret is deprecated and will be removed in the future. The secret will be derived from 'secret_key_base' instead.
          MSG

          self.original_signed_id_verifier_secret = secret
        end
      end
    end

    module RelationMethods # :nodoc:
      def find_signed(...)
        scoping { model.find_signed(...) }
      end

      def find_signed!(...)
        scoping { model.find_signed!(...) }
      end
    end

    module ClassMethods
      # Lets you find a record based on a signed id that's safe to put into the world without risk of tampering.
      # This is particularly useful for things like password reset or email verification, where you want
      # the bearer of the signed id to be able to interact with the underlying record, but usually only within
      # a certain time period.
      #
      # You set the time period that the signed id is valid for during generation, using the instance method
      # <tt>signed_id(expires_in: 15.minutes)</tt>. If the time has elapsed before a signed find is attempted,

Review comment (security):
"The secret will be derived from 'secret_key_base' instead" isn't necessarily helpful if a user is trying to migrate.  Instead, I think we should advise them to configure `Rails.application.message_verifiers` or set `signed_id_verifier`.

Code after:
# frozen_string_literal: true

module ActiveRecord
  # = Active Record Signed Id
  module SignedId
    extend ActiveSupport::Concern

    included do
      class_attribute :_signed_id_verifier, instance_accessor: false, instance_predicate: false

      ##
      # :singleton-method:
      # Set the secret used for the signed id verifier instance when using Active Record outside of \Rails.
      # Within \Rails, this is automatically set using the \Rails application key generator.
      class_attribute :signed_id_verifier_secret, instance_writer: false
      module DeprecateSignedIdVerifierSecret
        def signed_id_verifier_secret=(secret)
          ActiveRecord.deprecator.warn(<<~MSG)
            ActiveRecord::Base.signed_id_verifier_secret is deprecated and will be removed in the future.

            If the secret is model-specific, set Model.signed_id_verifier instead.

            Otherwise, configure Rails.application.message_verifiers (or ActiveRecord.message_verifiers) with the secret.
          MSG

          super
        end
      end
      singleton_class.prepend DeprecateSignedIdVerifierSecret
    end

    module RelationMethods # :nodoc:
      def find_signed(...)
        scoping { model.find_signed(...) }
      end

      def find_signed!(...)
        scoping { model.find_signed!(...) }
      end
    end

    module ClassMethods
      # Lets you find a record based on a signed id that's safe to put into the world without risk of tampering.
      # This is particularly useful for things like password reset or email verification, where you want
      # the bearer of the signed id to be able to interact with the underlying record, but usually only within
      # a certain time period.
      #
      # You set the time period that the signed id is valid for during generation, using the instance method