Repository: rails/rails
File: activerecord/test/cases/signed_id_test.rb (Ruby)

Code before:
    end
  end

  test "find signed record with bang with purpose" do
    assert_equal @account, Account.find_signed!(@account.signed_id(purpose: :v1), purpose: :v1)
  end

  test "find signed record with bang with purpose raises" do
    assert_raises(ActiveSupport::MessageVerifier::InvalidSignature) do
      Account.find_signed!(@account.signed_id(purpose: :v1))
    end

    assert_raises(ActiveSupport::MessageVerifier::InvalidSignature) do
      Account.find_signed!(@account.signed_id(purpose: :v1), purpose: :v2)
    end
  end

  test "deprecation warning for setting signed_id_verifier_secret" do
    assert_deprecated(ActiveRecord.deprecator) do
      ActiveRecord::Base.signed_id_verifier_secret = "new secret"
    end
  ensure
    ActiveRecord.deprecator.silence do
      ActiveRecord::Base.signed_id_verifier_secret = nil
    end
  end

  test "custom verifier is set for model and its sub-models" do
    old_verifier = Account.signed_id_verifier
    Account.signed_id_verifier = ActiveSupport::MessageVerifier.new("sekret")
    assert_not_equal ActiveRecord::Base.signed_id_verifier, Account.signed_id_verifier
    assert_equal Account.signed_id_verifier, SubAccount.signed_id_verifier
    assert_equal @account, Account.find_signed(@account.signed_id)
  ensure
    Account.signed_id_verifier = old_verifier
  end

  test "custom verifier is set only for the model (not for sub-models) when secret is set" do
    ActiveRecord.deprecator.silence do
      Account.signed_id_verifier_secret = "new secret"
    end

    Account.signed_id_verifier = ActiveSupport::MessageVerifier.new("sekret")
    assert_not_equal ActiveRecord::Base.signed_id_verifier, Account.signed_id_verifier
    assert_not_equal Account.signed_id_verifier, SubAccount.signed_id_verifier
    assert_equal @account, Account.find_signed(@account.signed_id)
  ensure
    ActiveRecord.deprecator.silence do
      Account.signed_id_verifier_secret = nil
      Account.instance_variable_set :@signed_id_verifier, nil
    end

Review comment (security):
This was changed to `Account.signed_id_verifier_secret = -> { nil }` further below in the diff, but that means we're not testing a possible case which is important for backward compatibility.  We should keep this as `ActiveRecord::Base.signed_id_verifier_secret = -> { nil }`.

Code after:
  end

  test "find signed record with bang with purpose" do
    assert_equal @account, Account.find_signed!(@account.signed_id(purpose: :v1), purpose: :v1)
  end

  test "find signed record with bang with purpose raises" do
    assert_raises(ActiveSupport::MessageVerifier::InvalidSignature) do
      Account.find_signed!(@account.signed_id(purpose: :v1))
    end

    assert_raises(ActiveSupport::MessageVerifier::InvalidSignature) do
      Account.find_signed!(@account.signed_id(purpose: :v1), purpose: :v2)
    end
  end

  test "deprecation warning for setting signed_id_verifier_secret" do
    assert_deprecated(ActiveRecord.deprecator) do
      ActiveRecord::Base.signed_id_verifier_secret = "new secret"
    end
  ensure
    ActiveRecord.deprecator.silence do
      ActiveRecord::Base.signed_id_verifier_secret = nil
    end
  end

  test "fail to work when signed_id_verifier_secret lambda is nil" do
    @original_secret = ActiveRecord::Base.signed_id_verifier_secret

    ActiveRecord.deprecator.silence do
      ActiveRecord::Base.signed_id_verifier_secret = -> { nil }
    end

    assert_raises(ArgumentError) do
      model.signed_id
    end
  ensure
    ActiveRecord.deprecator.silence do
      ActiveRecord::Base.signed_id_verifier_secret = @original_secret
    end
  end

  test "signed_id_verifier is ActiveRecord.message_verifiers['active_record/signed_id'] by default" do
    assert_same ActiveRecord.message_verifiers["active_record/signed_id"], model_class.signed_id_verifier
  end

  test "signed_id raises when ActiveRecord.message_verifiers has not been set" do
    ActiveRecord.message_verifiers = nil

    assert_raises(match: /to use signed IDs/) do
      model.signed_id