271 lines
7.6 KiB
Ruby
271 lines
7.6 KiB
Ruby
|
require 'spec_helper'
|
||
|
|
||
|
describe VerifyPagesDomainService do
|
||
|
using RSpec::Parameterized::TableSyntax
|
||
|
include EmailHelpers
|
||
|
|
||
|
let(:error_status) { { status: :error, message: "Couldn't verify #{domain.domain}" } }
|
||
|
|
||
|
subject(:service) { described_class.new(domain) }
|
||
|
|
||
|
describe '#execute' do
|
||
|
context 'verification code recognition (verified domain)' do
|
||
|
where(:domain_sym, :code_sym) do
|
||
|
:domain | :verification_code
|
||
|
:domain | :keyed_verification_code
|
||
|
|
||
|
:verification_domain | :verification_code
|
||
|
:verification_domain | :keyed_verification_code
|
||
|
end
|
||
|
|
||
|
with_them do
|
||
|
set(:domain) { create(:pages_domain) }
|
||
|
|
||
|
let(:domain_name) { domain.send(domain_sym) }
|
||
|
let(:verification_code) { domain.send(code_sym) }
|
||
|
|
||
|
it 'verifies and enables the domain' do
|
||
|
stub_resolver(domain_name => ['something else', verification_code])
|
||
|
|
||
|
expect(service.execute).to eq(status: :success)
|
||
|
expect(domain).to be_verified
|
||
|
expect(domain).to be_enabled
|
||
|
end
|
||
|
|
||
|
it 'verifies and enables when the code is contained partway through a TXT record' do
|
||
|
stub_resolver(domain_name => "something #{verification_code} else")
|
||
|
|
||
|
expect(service.execute).to eq(status: :success)
|
||
|
expect(domain).to be_verified
|
||
|
expect(domain).to be_enabled
|
||
|
end
|
||
|
|
||
|
it 'does not verify when the code is not present' do
|
||
|
stub_resolver(domain_name => 'something else')
|
||
|
|
||
|
expect(service.execute).to eq(error_status)
|
||
|
|
||
|
expect(domain).not_to be_verified
|
||
|
expect(domain).to be_enabled
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'verified domain' do
|
||
|
set(:domain) { create(:pages_domain) }
|
||
|
|
||
|
it 'unverifies (but does not disable) when the right code is not present' do
|
||
|
stub_resolver(domain.domain => 'something else')
|
||
|
|
||
|
expect(service.execute).to eq(error_status)
|
||
|
expect(domain).not_to be_verified
|
||
|
expect(domain).to be_enabled
|
||
|
end
|
||
|
|
||
|
it 'unverifies (but does not disable) when no records are present' do
|
||
|
stub_resolver
|
||
|
|
||
|
expect(service.execute).to eq(error_status)
|
||
|
expect(domain).not_to be_verified
|
||
|
expect(domain).to be_enabled
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'expired domain' do
|
||
|
set(:domain) { create(:pages_domain, :expired) }
|
||
|
|
||
|
it 'verifies and enables when the right code is present' do
|
||
|
stub_resolver(domain.domain => domain.keyed_verification_code)
|
||
|
|
||
|
expect(service.execute).to eq(status: :success)
|
||
|
|
||
|
expect(domain).to be_verified
|
||
|
expect(domain).to be_enabled
|
||
|
end
|
||
|
|
||
|
it 'disables when the right code is not present' do
|
||
|
error_status[:message] += '. It is now disabled.'
|
||
|
|
||
|
stub_resolver
|
||
|
|
||
|
expect(service.execute).to eq(error_status)
|
||
|
|
||
|
expect(domain).not_to be_verified
|
||
|
expect(domain).not_to be_enabled
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'timeout behaviour' do
|
||
|
let(:domain) { create(:pages_domain) }
|
||
|
|
||
|
it 'sets a timeout on the DNS query' do
|
||
|
expect(stub_resolver).to receive(:timeouts=).with(described_class::RESOLVER_TIMEOUT_SECONDS)
|
||
|
|
||
|
service.execute
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'email notifications' do
|
||
|
let(:notification_service) { instance_double('NotificationService') }
|
||
|
|
||
|
where(:factory, :verification_succeeds, :expected_notification) do
|
||
|
nil | true | nil
|
||
|
nil | false | :verification_failed
|
||
|
:reverify | true | nil
|
||
|
:reverify | false | :verification_failed
|
||
|
:unverified | true | :verification_succeeded
|
||
|
:unverified | false | nil
|
||
|
:expired | true | nil
|
||
|
:expired | false | :disabled
|
||
|
:disabled | true | :enabled
|
||
|
:disabled | false | nil
|
||
|
end
|
||
|
|
||
|
with_them do
|
||
|
let(:domain) { create(:pages_domain, *[factory].compact) }
|
||
|
|
||
|
before do
|
||
|
allow(service).to receive(:notification_service) { notification_service }
|
||
|
|
||
|
if verification_succeeds
|
||
|
stub_resolver(domain.domain => domain.verification_code)
|
||
|
else
|
||
|
stub_resolver
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it 'sends a notification if appropriate' do
|
||
|
if expected_notification
|
||
|
expect(notification_service).to receive(:"pages_domain_#{expected_notification}").with(domain)
|
||
|
end
|
||
|
|
||
|
service.execute
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'pages verification disabled' do
|
||
|
let(:domain) { create(:pages_domain, :disabled) }
|
||
|
|
||
|
before do
|
||
|
stub_application_setting(pages_domain_verification_enabled: false)
|
||
|
allow(service).to receive(:notification_service) { notification_service }
|
||
|
end
|
||
|
|
||
|
it 'skips email notifications' do
|
||
|
expect(notification_service).not_to receive(:pages_domain_enabled)
|
||
|
|
||
|
service.execute
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'pages configuration updates' do
|
||
|
context 'enabling a disabled domain' do
|
||
|
let(:domain) { create(:pages_domain, :disabled) }
|
||
|
|
||
|
it 'schedules an update' do
|
||
|
stub_resolver(domain.domain => domain.verification_code)
|
||
|
|
||
|
expect(domain).to receive(:update_daemon)
|
||
|
|
||
|
service.execute
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'verifying an enabled domain' do
|
||
|
let(:domain) { create(:pages_domain) }
|
||
|
|
||
|
it 'schedules an update' do
|
||
|
stub_resolver(domain.domain => domain.verification_code)
|
||
|
|
||
|
expect(domain).not_to receive(:update_daemon)
|
||
|
|
||
|
service.execute
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'disabling an expired domain' do
|
||
|
let(:domain) { create(:pages_domain, :expired) }
|
||
|
|
||
|
it 'schedules an update' do
|
||
|
stub_resolver
|
||
|
|
||
|
expect(domain).to receive(:update_daemon)
|
||
|
|
||
|
service.execute
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'failing to verify a disabled domain' do
|
||
|
let(:domain) { create(:pages_domain, :disabled) }
|
||
|
|
||
|
it 'does not schedule an update' do
|
||
|
stub_resolver
|
||
|
|
||
|
expect(domain).not_to receive(:update_daemon)
|
||
|
|
||
|
service.execute
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'no verification code' do
|
||
|
let(:domain) { create(:pages_domain) }
|
||
|
|
||
|
it 'returns an error' do
|
||
|
domain.verification_code = ''
|
||
|
|
||
|
disallow_resolver!
|
||
|
|
||
|
expect(service.execute).to eq(status: :error, message: "No verification code set for #{domain.domain}")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'pages domain verification is disabled' do
|
||
|
let(:domain) { create(:pages_domain, :disabled) }
|
||
|
|
||
|
before do
|
||
|
stub_application_setting(pages_domain_verification_enabled: false)
|
||
|
end
|
||
|
|
||
|
it 'extends domain validity by unconditionally reverifying' do
|
||
|
disallow_resolver!
|
||
|
|
||
|
service.execute
|
||
|
|
||
|
expect(domain).to be_verified
|
||
|
expect(domain).to be_enabled
|
||
|
end
|
||
|
|
||
|
it 'does not shorten any grace period' do
|
||
|
grace = Time.now + 1.year
|
||
|
domain.update!(enabled_until: grace)
|
||
|
disallow_resolver!
|
||
|
|
||
|
service.execute
|
||
|
|
||
|
expect(domain.enabled_until).to be_like_time(grace)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def disallow_resolver!
|
||
|
expect(Resolv::DNS).not_to receive(:open)
|
||
|
end
|
||
|
|
||
|
def stub_resolver(stubbed_lookups = {})
|
||
|
resolver = instance_double('Resolv::DNS')
|
||
|
allow(resolver).to receive(:timeouts=)
|
||
|
|
||
|
expect(Resolv::DNS).to receive(:open).and_yield(resolver)
|
||
|
|
||
|
allow(resolver).to receive(:getresources) { [] }
|
||
|
stubbed_lookups.each do |domain, records|
|
||
|
records = Array(records).map { |txt| Resolv::DNS::Resource::IN::TXT.new(txt) }
|
||
|
allow(resolver).to receive(:getresources).with(domain, Resolv::DNS::Resource::IN::TXT) { records }
|
||
|
end
|
||
|
|
||
|
resolver
|
||
|
end
|
||
|
end
|