From 6a21eef9cdd8af26d4d2c60ae607830dc2165735 Mon Sep 17 00:00:00 2001 From: George Byers Date: Fri, 27 Sep 2024 11:25:19 -0400 Subject: [PATCH] 1412: Email validation fixes. Accepting a more sensible email address format (#291) * Ensuring that email addresses contain TLDs in order to be considered valid. * added more conditional for the email validation. Email addresses containing spaces are not valid * Comma delimited emails are still considered valid. We should investigate this * Applying PR feedback * removing test in place of comment * Update app/app/models/cbv_flow_invitation.rb Co-authored-by: Tom Dooner * fixed rubocop linting errors --------- Co-authored-by: Tom Dooner --- app/app/models/cbv_flow_invitation.rb | 18 ++++++++++--- app/spec/models/cbv_flow_invitation_spec.rb | 29 ++++++++++++++++++++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/app/app/models/cbv_flow_invitation.rb b/app/app/models/cbv_flow_invitation.rb index 6717cbf3..c4e9cd83 100644 --- a/app/app/models/cbv_flow_invitation.rb +++ b/app/app/models/cbv_flow_invitation.rb @@ -1,5 +1,12 @@ class CbvFlowInvitation < ApplicationRecord - EMAIL_REGEX = URI::MailTo::EMAIL_REGEXP + # We're opting not to use URI::MailTo::EMAIL_REGEXP + # https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address + # + # EXCERPT: This requirement is a willful violation of RFC 5322, which defines a syntax for email addresses + # that is simultaneously too strict (before the "@" character), too vague (after the "@" character), + # and too lax (allowing comments, whitespace characters, and quoted strings in manners unfamiliar to most users) + # to be of practical use here. + EMAIL_REGEX = /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z\d\-]+\z/i # Massachusetts: 7 digits MA_AGENCY_ID_REGEX = /\A\d{7}\z/ @@ -13,6 +20,12 @@ class CbvFlowInvitation < ApplicationRecord # New York City: 2 uppercase letters, followed by 5 digits, followed by 1 uppercase letter NYC_CLIENT_ID_REGEX = /\A[A-Z]{2}\d{5}[A-Z]\z/ + # Invitation validity time zone + INVITATION_VALIDITY_TIME_ZONE = "America/New_York" + + # Paystub report range + PAYSTUB_REPORT_RANGE = 90.days + belongs_to :user has_many :cbv_flows @@ -53,9 +66,6 @@ class CbvFlowInvitation < ApplicationRecord auth_token: :string ) - INVITATION_VALIDITY_TIME_ZONE = "America/New_York" - PAYSTUB_REPORT_RANGE = 90.days - scope :unstarted, -> { left_outer_joins(:cbv_flows).where(cbv_flows: { id: nil }) } # Invitations are valid until 11:59pm Eastern Time on the (e.g.) 14th day diff --git a/app/spec/models/cbv_flow_invitation_spec.rb b/app/spec/models/cbv_flow_invitation_spec.rb index a32ebc81..c35ace05 100644 --- a/app/spec/models/cbv_flow_invitation_spec.rb +++ b/app/spec/models/cbv_flow_invitation_spec.rb @@ -2,11 +2,38 @@ RSpec.describe CbvFlowInvitation, type: :model do let(:valid_attributes) do - attributes_for(:cbv_flow_invitation, :nyc) + attributes_for(:cbv_flow_invitation, :nyc).merge(user: create(:user, site_id: "nyc")) end + let(:invalid_email_no_tld) { "johndoe@gmail" } + let(:valid_email) { "johndoe@gmail.com" } describe "validations" do context "for all invitations" do + context "validates email addresses" do + context "when email address is valid" do + valid_email_addresses = %w[johndoe@gmail.com johndoe@example.com.au johndoe@example.com,johndoe@example.com.au] + valid_email_addresses.each do |email| + it "#{email} is valid" do + invitation = CbvFlowInvitation.new(valid_attributes.merge(email_address: email)) + expect(invitation).to be_valid + end + end + end + + context "when email address is invalid" do + invalid_email_addresses = %w[johndoe@gmail johndoe@gmail..com johndoe@gmail.com..com johndoe@gmail\ .\ com] + invalid_email_addresses.each do |email| + it "determines #{email} is invalid" do + invitation = CbvFlowInvitation.new(valid_attributes.merge(email_address: email)) + expect(invitation).not_to be_valid + expect(invitation.errors[:email_address]).to include( + I18n.t('activerecord.errors.models.cbv_flow_invitation.attributes.email_address.invalid_format') + ) + end + end + end + end + it "requires email_address" do invitation = CbvFlowInvitation.new(valid_attributes.merge(email_address: nil)) expect(invitation).not_to be_valid