review(pr): some enhancement, tx @colinux

Co-Authored-By: Colin Darie <colin@darie.eu>
This commit is contained in:
mfo 2024-06-11 10:17:27 +02:00
parent 66eb3dc821
commit 8e3d45b0b1
No known key found for this signature in database
GPG key ID: 7CE3E1F5B794A8EC
4 changed files with 16 additions and 9 deletions

View file

@ -1,5 +1,5 @@
class EmailCheckerController < ApplicationController
def show
render json: EmailChecker.check(email: params[:email])
render json: EmailChecker.new.check(email: params[:email])
end
end

View file

@ -21,7 +21,11 @@ export class EmailInputController extends ApplicationController {
declare readonly inputTarget: HTMLInputElement;
async checkEmail() {
if (!this.inputTarget.value) {
if (
!this.inputTarget.value ||
this.inputTarget.value.length < 5 ||
!this.inputTarget.value.includes('@')
) {
return;
}

View file

@ -1,4 +1,7 @@
class EmailChecker
# Extracted 100 most used domain on our users table [june 2024]
# + all .gouv.fr domain on our users table
# + all .ac-xxx on our users table
KNOWN_DOMAINS = [
'gmail.com',
'hotmail.fr',
@ -612,10 +615,10 @@ class EmailChecker
'ac-toulous.fr'
].freeze
def self.check(email:)
def check(email:)
return { success: false } if email.blank?
parsed_email = Mail::Address.new(email)
parsed_email = Mail::Address.new(EmailSanitizableConcern::EmailSanitizer.sanitize(email))
return { success: false } if parsed_email.domain.blank?
return { success: true } if KNOWN_DOMAINS.any? { _1 == parsed_email.domain }
@ -628,22 +631,22 @@ class EmailChecker
private
def self.closest_domains(domain:)
def closest_domains(domain:)
KNOWN_DOMAINS.filter do |known_domain|
close_by_distance_of(domain, known_domain, distance: 1) ||
with_same_chars_and_close_by_distance_of(domain, known_domain, distance: 2)
end
end
def self.close_by_distance_of(a, b, distance:)
def close_by_distance_of(a, b, distance:)
String::Similarity.levenshtein_distance(a, b) == distance
end
def self.with_same_chars_and_close_by_distance_of(a, b, distance:)
def with_same_chars_and_close_by_distance_of(a, b, distance:)
close_by_distance_of(a, b, distance: 2) && a.chars.sort == b.chars.sort
end
def self.email_suggestions(parsed_email:, similar_domains:)
def email_suggestions(parsed_email:, similar_domains:)
similar_domains.map { Mail::Address.new("#{parsed_email.local}@#{_1}").to_s }
end
end

View file

@ -1,6 +1,6 @@
describe EmailChecker do
describe 'check' do
subject { described_class }
subject { described_class.new }
it 'works with identified use cases' do
expect(subject.check(email: nil)).to eq({ success: false })