Add validator for qualidied domain array

- Validate that the entries contain no unicode, html tags and are not
larger than 255 characters.
This commit is contained in:
Reuben Pereira 2019-07-23 19:47:17 +00:00 committed by Mayra Cabrera
parent ab97168e4f
commit 42ecbcad10
3 changed files with 172 additions and 0 deletions

View file

@ -0,0 +1,49 @@
# frozen_string_literal: true
# QualifiedDomainArrayValidator
#
# Custom validator for URL hosts/'qualified domains' (FQDNs, ex: gitlab.com, sub.example.com).
# This does not check if the domain actually exists. It only checks if it is a
# valid domain string.
#
# Example:
#
# class ApplicationSetting < ApplicationRecord
# validates :outbound_local_requests_whitelist, qualified_domain_array: true
# end
#
class QualifiedDomainArrayValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
validate_value_present(record, attribute, value)
validate_host_length(record, attribute, value)
validate_idna_encoding(record, attribute, value)
validate_sanitization(record, attribute, value)
end
private
def validate_value_present(record, attribute, value)
return unless value.blank?
record.errors.add(attribute, _('entries cannot be blank'))
end
def validate_host_length(record, attribute, value)
return unless value&.any? { |entry| entry.size > 255 }
record.errors.add(attribute, _('entries cannot be larger than 255 characters'))
end
def validate_idna_encoding(record, attribute, value)
return if value&.all?(&:ascii_only?)
record.errors.add(attribute, _('unicode domains should use IDNA encoding'))
end
def validate_sanitization(record, attribute, value)
sanitizer = Rails::Html::FullSanitizer.new
return unless value&.any? { |str| sanitizer.sanitize(str) != str }
record.errors.add(attribute, _('entries cannot contain HTML tags'))
end
end

View file

@ -12803,6 +12803,15 @@ msgstr ""
msgid "encrypted: needs to be a :required, :optional or :migrating!"
msgstr ""
msgid "entries cannot be blank"
msgstr ""
msgid "entries cannot be larger than 255 characters"
msgstr ""
msgid "entries cannot contain HTML tags"
msgstr ""
msgid "error"
msgstr ""
@ -13308,6 +13317,9 @@ msgstr ""
msgid "triggered"
msgstr ""
msgid "unicode domains should use IDNA encoding"
msgstr ""
msgid "updated"
msgstr ""

View file

@ -0,0 +1,111 @@
# frozen_string_literal: true
require 'spec_helper'
describe QualifiedDomainArrayValidator do
class TestClass
include ActiveModel::Validations
attr_accessor :domain_array
def initialize(domain_array)
self.domain_array = domain_array
end
end
let!(:record) do
TestClass.new(['gitlab.com'])
end
subject { validator.validate(record) }
shared_examples 'cannot be blank' do
it 'returns error when attribute is blank' do
record.domain_array = []
subject
expect(record.errors).to be_present
expect(record.errors.first[1]).to eq 'entries cannot be blank'
end
end
shared_examples 'can be nil' do
it 'allows when attribute is nil' do
record.domain_array = nil
subject
expect(record.errors).to be_empty
end
end
describe 'validations' do
let(:validator) { described_class.new(attributes: [:domain_array]) }
it_behaves_like 'cannot be blank'
it 'returns error when attribute is nil' do
record.domain_array = nil
subject
expect(record.errors).to be_present
end
it 'allows when domain is valid' do
subject
expect(record.errors).to be_empty
end
it 'returns error when domain contains unicode' do
record.domain_array = ['ğitlab.com']
subject
expect(record.errors).to be_present
expect(record.errors.first[1]).to eq 'unicode domains should use IDNA encoding'
end
it 'returns error when entry is larger than 255 chars' do
record.domain_array = ['a' * 256]
subject
expect(record.errors).to be_present
expect(record.errors.first[1]).to eq 'entries cannot be larger than 255 characters'
end
it 'returns error when entry contains HTML tags' do
record.domain_array = ['gitlab.com<h1>something</h1>']
subject
expect(record.errors).to be_present
expect(record.errors.first[1]).to eq 'entries cannot contain HTML tags'
end
end
context 'when allow_nil is set to true' do
let(:validator) { described_class.new(attributes: [:domain_array], allow_nil: true) }
it_behaves_like 'can be nil'
it_behaves_like 'cannot be blank'
end
context 'when allow_blank is set to true' do
let(:validator) { described_class.new(attributes: [:domain_array], allow_blank: true) }
it_behaves_like 'can be nil'
it 'allows when attribute is blank' do
record.domain_array = []
subject
expect(record.errors).to be_empty
end
end
end