Spec-Zone.ru › Ruby on Rails 8.1

module ActiveRecord::SignedId::ClassMethods

Открытые методы экземпляра

find_signed (signed_id, purpose: nil, on_rotation: nil) Показать исходный код
# File activerecord/lib/active_record/signed_id.rb, line 68
def find_signed(signed_id, purpose: nil, on_rotation: nil)
  raise UnknownPrimaryKey.new(self) if primary_key.nil?

  options = { on_rotation: on_rotation }.compact
  if id = signed_id_verifier.verified(signed_id, purpose: combine_signed_id_purposes(purpose), **options)
    find_by primary_key => id
  end
end

Позволяет найти запись по подписанному идентификатору, который безопасно публиковать, не опасаясь подделки. Это особенно полезно для таких задач, как сброс пароля или подтверждение адреса электронной почты: вы хотите, чтобы обладатель подписанного идентификатора мог взаимодействовать с соответствующей записью, но обычно только в течение определённого периода времени.

Период действия подписанного идентификатора задаётся при его создании с помощью метода экземпляра signed_id(expires_in: 15.minutes). Если до попытки поиска по подписанному идентификатору срок действия истёк, идентификатор становится недействительным, и возвращается nil.

Использование подписанного идентификатора можно дополнительно ограничить, указав назначение. Это полезно, если у вас есть общая базовая модель, например User, для которой могут создаваться подписанные идентификаторы для разных целей, таких как сброс пароля или подтверждение адреса электронной почты. Назначение, заданное при создании идентификатора, должно совпадать с назначением, указанным при поиске. Если они не совпадают, снова возвращается nil.

Примеры

signed_id = User.first.signed_id expires_in: 15.minutes, purpose: :password_reset

User.find_signed signed_id # => nil, since the purpose does not match

travel 16.minutes
User.find_signed signed_id, purpose: :password_reset # => nil, since the signed id has expired

travel_back
User.find_signed signed_id, purpose: :password_reset # => User.first
find_signed! (signed_id, purpose: nil, on_rotation: nil) Показать исходный код
# File activerecord/lib/active_record/signed_id.rb, line 89
def find_signed!(signed_id, purpose: nil, on_rotation: nil)
  options = { on_rotation: on_rotation }.compact
  if id = signed_id_verifier.verify(signed_id, purpose: combine_signed_id_purposes(purpose), **options)
    find(id)
  end
end

Работает как find_signed, но вызывает исключение ActiveSupport::MessageVerifier::InvalidSignature, если срок действия signed_id истёк, назначение не совпадает, идентификатор относится к другой записи или был подделан. Также вызывает исключение ActiveRecord::RecordNotFound, если по действительному подписанному идентификатору не удаётся найти запись.

Примеры

User.find_signed! "bad data" # => ActiveSupport::MessageVerifier::InvalidSignature

signed_id = User.first.signed_id
User.first.destroy
User.find_signed! signed_id # => ActiveRecord::RecordNotFound
signed_id_verifier () Показать исходный код
# File activerecord/lib/active_record/signed_id.rb, line 96
def signed_id_verifier
  if signed_id_verifier_secret
    @signed_id_verifier ||= begin
      secret = signed_id_verifier_secret
      secret = secret.call if secret.respond_to?(:call)

      if secret.nil?
        raise ArgumentError, "You must set ActiveRecord::Base.signed_id_verifier_secret to use signed IDs"
      end

      ActiveSupport::MessageVerifier.new secret, digest: "SHA256", serializer: JSON, url_safe: true
    end
  else
    return _signed_id_verifier if _signed_id_verifier

    if ActiveRecord.message_verifiers.nil?
      raise "You must set ActiveRecord.message_verifiers to use signed IDs"
    end

    ActiveRecord.message_verifiers["active_record/signed_id"]
  end
end
signed_id_verifier= (verifier) Показать исходный код
# File activerecord/lib/active_record/signed_id.rb, line 122
def signed_id_verifier=(verifier)
  if signed_id_verifier_secret
    @signed_id_verifier = verifier
  else
    self._signed_id_verifier = verifier
  end
end

Позволяет передать пользовательский верификатор для подписанных идентификаторов. Это также позволяет использовать разные верификаторы для разных классов. Это полезно и при необходимости сменить ключи: пользовательский верификатор можно заранее подготовить к этому. Подробности см. в документации ActiveSupport::MessageVerifier.

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API