fix: account email validation during signup (#11307)

- Refactor email validation logic to be a service
- Use the service for both email/pass signup and Google SSO
- fix account email validation during signup
- Use `blocked_domain` setting for both email/pass signup and Google
Sign In [`BLOCKED_DOMAIN` via GlobalConfig]
- add specs for `account_builder`
- add specs for the new service

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
This commit is contained in:
Vishnu Narayanan
2025-05-21 09:15:39 +05:30
committed by GitHub
parent a07f2a7c1b
commit df7401f71c
6 changed files with 215 additions and 53 deletions

View File

@@ -32,14 +32,7 @@ class AccountBuilder
end
def validate_email
raise InvalidEmail.new({ domain_blocked: domain_blocked }) if domain_blocked?
address = ValidEmail2::Address.new(@email)
if address.valid? && !address.disposable?
true
else
raise InvalidEmail.new({ valid: address.valid?, disposable: address.disposable? })
end
Account::SignUpEmailValidationService.new(@email).perform
end
def validate_user
@@ -81,21 +74,4 @@ class AccountBuilder
@user.confirm if @confirmed
@user.save!
end
def domain_blocked?
domain = @email.split('@').last
blocked_domains.each do |blocked_domain|
return true if domain.match?(blocked_domain)
end
false
end
def blocked_domains
domains = GlobalConfigService.load('BLOCKED_EMAIL_DOMAINS', '')
return [] if domains.blank?
domains.split("\n").map(&:strip)
end
end

View File

@@ -21,7 +21,7 @@ class DeviseOverrides::OmniauthCallbacksController < DeviseTokenAuth::OmniauthCa
def sign_up_user
return redirect_to login_page_url(error: 'no-account-found') unless account_signup_allowed?
return redirect_to login_page_url(error: 'business-account-only') unless validate_business_account?
return redirect_to login_page_url(error: 'business-account-only') unless validate_signup_email_is_business_domain?
create_account_for_user
token = @resource.send(:set_reset_password_token)
@@ -53,9 +53,11 @@ class DeviseOverrides::OmniauthCallbacksController < DeviseTokenAuth::OmniauthCa
).first
end
def validate_business_account?
# return true if the user is a business account, false if it is a gmail account
auth_hash['info']['email'].downcase.exclude?('@gmail.com')
def validate_signup_email_is_business_domain?
# return true if the user is a business account, false if it is a blocked domain account
Account::SignUpEmailValidationService.new(auth_hash['info']['email']).perform
rescue CustomExceptions::Account::InvalidEmail
false
end
def create_account_for_user

View File

@@ -0,0 +1,36 @@
# frozen_string_literal: true
class Account::SignUpEmailValidationService
include CustomExceptions::Account
attr_reader :email
def initialize(email)
@email = email
end
def perform
address = ValidEmail2::Address.new(email)
raise InvalidEmail.new({ valid: false, disposable: nil }) unless address.valid?
raise InvalidEmail.new({ domain_blocked: true }) if domain_blocked?
raise InvalidEmail.new({ valid: true, disposable: true }) if address.disposable?
true
end
private
def domain_blocked?
domain = email.split('@').last&.downcase
blocked_domains.any? { |blocked_domain| domain.match?(blocked_domain.downcase) }
end
def blocked_domains
domains = GlobalConfigService.load('BLOCKED_EMAIL_DOMAINS', '')
return [] if domains.blank?
domains.split("\n").map(&:strip)
end
end