feat(email.validator): define a strict email validator, validates Champs::EmailChamp.value only on validation context
Co-authored-by: Paul Chavard <github@paul.chavard.net>
This commit is contained in:
parent
429c7f43fc
commit
25f92a7760
3 changed files with 67 additions and 0 deletions
|
@ -1,2 +1,3 @@
|
||||||
class Champs::EmailChamp < Champs::TextChamp
|
class Champs::EmailChamp < Champs::TextChamp
|
||||||
|
validates :value, format: { with: StrictEmailValidator::REGEXP }, if: :validate_champ_value?
|
||||||
end
|
end
|
||||||
|
|
31
app/validators/strict_email_validator.rb
Normal file
31
app/validators/strict_email_validator.rb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
class StrictEmailValidator < ActiveModel::EachValidator
|
||||||
|
# default devise email is : /\A[^@\s]+@[^@\s]+\z/
|
||||||
|
# saying that it's quite permissive
|
||||||
|
# but we want more, we want to ensure it's a domain with extension
|
||||||
|
# so we append \.[A-Za-z]{2,}
|
||||||
|
REGEXP = /\A[^@\s]+@[^@\s\.]+\.[^@\s]{2,}\z/
|
||||||
|
|
||||||
|
def validate_each(record, attribute, value)
|
||||||
|
if value.present? && !REGEXP.match?(value)
|
||||||
|
record.errors.add(attribute, :format)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.elligible_to_new_validation?(record)
|
||||||
|
return false if !strict_validation_enabled?
|
||||||
|
return false if (record.created_at || Time.now) < date_since_strict_email_validation
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.strict_validation_enabled?
|
||||||
|
ENV.key?('STRICT_EMAIL_VALIDATION_STARTS_AT')
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.date_since_strict_email_validation
|
||||||
|
DateTime.parse(ENV['STRICT_EMAIL_VALIDATION_STARTS_AT'])
|
||||||
|
rescue
|
||||||
|
DateTime.new(1789, 5, 5, 0, 0) # french revolution, ds was not yet launched
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
35
spec/models/champs/email_champ_spec.rb
Normal file
35
spec/models/champs/email_champ_spec.rb
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
describe Champs::EmailChamp do
|
||||||
|
describe 'validation' do
|
||||||
|
let(:now) { Time.zone.now }
|
||||||
|
let(:before) { now + 1.day }
|
||||||
|
let(:after) { now + 1.day }
|
||||||
|
subject { build(:champ_email, value: value).valid?(:validate_champ_value) }
|
||||||
|
|
||||||
|
context 'when value is username' do
|
||||||
|
let(:value) { 'username' }
|
||||||
|
# what we allowed but it was a mistake
|
||||||
|
it { is_expected.to be_truthy }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when value does not contain extension' do
|
||||||
|
let(:value) { 'username@mailserver' }
|
||||||
|
# what we allowed but it was a mistake
|
||||||
|
it { is_expected.to be_truthy }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when value include an alias' do
|
||||||
|
let(:value) { 'username+alias@mailserver.fr' }
|
||||||
|
it { is_expected.to be_truthy }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when value includes accents' do
|
||||||
|
let(:value) { 'tech@démarches.gouv.fr' }
|
||||||
|
it { is_expected.to be_truthy }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when value is the classic standard user@domain.ext' do
|
||||||
|
let(:value) { 'username@mailserver.domain' }
|
||||||
|
it { is_expected.to be_truthy }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue