Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

Commit 040c7a7

Browse files
Merge pull request #102 from mena-devs/user-email-validation
User email validation improvements
2 parents 705fe86 + dc108b5 commit 040c7a7

File tree

6 files changed

+94
-53
lines changed

6 files changed

+94
-53
lines changed

app/models/user.rb

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@ class User < ApplicationRecord
4242
:recoverable, :rememberable, :trackable, :validatable,
4343
:confirmable, :omniauthable, omniauth_providers: [:slack]
4444

45-
validates :email, uniqueness: true
46-
validates :email, format: {
47-
with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i,
48-
on: :create }
45+
validates :email, uniqueness: true, email: true
4946

5047
before_validation :generate_unique_user_id, on: :create
5148

@@ -61,9 +58,9 @@ class User < ApplicationRecord
6158

6259
scope :news_subscribers, -> { joins(:profile).where('profiles.receive_emails IS TRUE') }
6360
scope :job_alert_subscribers, -> { joins(:profile).where('profiles.receive_job_alerts IS TRUE') }
64-
61+
6562
scope :verified, -> { where("confirmed_at IS NOT NULL")}
66-
63+
6764
scope :admins, -> { where("admin is TRUE")}
6865

6966
scope :today, -> { where("created_at >= ?", 1.day.ago)}
@@ -189,7 +186,7 @@ def self.update_user_from_slack(user_info)
189186

190187
return user.save
191188
end
192-
189+
193190
return false
194191
end
195192

app/validators/email_validator.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,34 @@
11
class EmailValidator < ActiveModel::EachValidator
22
def validate_each(record, attribute, value)
3-
record.errors[attribute] << (options[:message] || "must be a valid email address") unless email_valid?(value)
3+
record.errors[attribute] << email_invalid_error_message unless email_valid?(value)\
4+
&& handle_contains_number_of_dots(value)\
5+
&& handle_last_character_is_not_dot(value)
6+
end
7+
8+
private
9+
10+
def email_invalid_error_message
11+
# options[:message] || I18n.t('errors.messages.email')
12+
(options[:message] || 'must be a valid email address')
413
end
514

615
def email_valid?(email_address)
716
return true if email_address.blank?
817

918
email_address =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
1019
end
20+
21+
def handle_contains_number_of_dots(email_address)
22+
return true if email_address.blank?
23+
24+
email_handle = email_address.split('@')
25+
email_handle[0].count('.') < 3 if email_handle && !email_handle.blank?
26+
end
27+
28+
def handle_last_character_is_not_dot(email_address)
29+
return true if email_address.blank?
30+
31+
email_handle = email_address.split('@')
32+
email_handle[0][-1] != '.' if email_handle && !email_handle.blank?
33+
end
1134
end

spec/models/user_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
end
5151

5252
it { should validate_uniqueness_of :email }
53-
53+
5454
describe '#email' do
5555
it { should_not allow_value("blah").for(:email) }
5656
it { should allow_value("[email protected]").for(:email) }

spec/requests/registrations_spec.rb

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@
2727
end
2828
end
2929

30-
describe "Fails" do
31-
it "should fail registration because email already exists" do
30+
describe "Fails registration" do
31+
before(:each) do
32+
visit new_user_registration_path
33+
end
34+
35+
it "email already exists" do
3236
fill_in 'Email', with: existing_user.email
3337
fill_in 'Password', with: 'password'
3438
fill_in 'Password confirmation', with: 'password'
@@ -39,10 +43,10 @@
3943
expect(page).to have_content("Email has already been taken")
4044
end
4145

42-
it "should fail registration because passwords do not match" do
46+
it "passwords do not match" do
4347
fill_in 'Email', with: '[email protected]'
44-
fill_in 'Password', with: 'password'
45-
fill_in 'Password confirmation', with: 'passwordz'
48+
fill_in 'Password', with: 'password'
49+
fill_in 'Password confirmation', with: 'passwordz'
4650

4751
click_on('Join us')
4852

@@ -51,15 +55,37 @@
5155
end
5256

5357

54-
it "should fail registration because email address is incorrect" do
58+
it "email address is incorrect" do
5559
fill_in 'Email', with: 'mars-example.com'
56-
fill_in 'Password', with: 'password'
57-
fill_in 'Password confirmation', with: 'password'
60+
fill_in 'Password', with: 'password'
61+
fill_in 'Password confirmation', with: 'password'
62+
63+
click_on('Join us')
64+
65+
expect(page).to have_content("2 errors prohibited this user from being saved")
66+
expect(page).to have_content("must be a valid email address")
67+
end
68+
69+
it "email address contains uncommon number of characters" do
70+
fill_in 'Email', with: '[email protected]'
71+
fill_in 'Password', with: 'password'
72+
fill_in 'Password confirmation', with: 'password'
73+
74+
click_on('Join us')
75+
76+
expect(page).to have_content("1 error prohibited this user from being saved")
77+
expect(page).to have_content("must be a valid email address")
78+
end
79+
80+
it "email address handle ends with a dot" do
81+
fill_in 'Email', with: '[email protected]'
82+
fill_in 'Password', with: 'password'
83+
fill_in 'Password confirmation', with: 'password'
5884

5985
click_on('Join us')
6086

6187
expect(page).to have_content("1 error prohibited this user from being saved")
62-
expect(page).to have_content("Email is invalid")
88+
expect(page).to have_content("must be a valid email address")
6389
end
6490
end
6591
end

spec/requests/users_spec.rb

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
expect(page).to have_content('Password')
3838
end
3939
end
40-
40+
4141
# /users/password/new
4242
describe "GET /users/password/new" do
4343
before do
@@ -70,7 +70,7 @@
7070
describe "GET /users/password/edit" do
7171
it "should not allow reset of password if the password is not matching" do
7272
visit edit_user_password_path(reset_password_token: user.reset_password_token)
73-
73+
7474
expect(page).to have_content('Change your password')
7575
expect(page).to have_content('Type your new password')
7676
expect(page).to have_content('Password')
@@ -84,7 +84,7 @@
8484

8585
it "should not allow reset password if the token is not valid" do
8686
visit edit_user_password_path(reset_password_token: user.reset_password_token)
87-
87+
8888
expect(page).to have_content('Change your password')
8989
expect(page).to have_content('Type your new password')
9090
expect(page).to have_content('Password')
@@ -105,7 +105,7 @@
105105
user.save
106106

107107
visit edit_user_password_path(reset_password_token: reset_password_token)
108-
108+
109109
expect(page).to have_content('Change your password')
110110
expect(page).to have_content('Type your new password')
111111
expect(page).to have_content('Password')
@@ -115,42 +115,12 @@
115115
fill_in 'Password confirmation', with: 'OpenSource'
116116

117117
click_on('Change my password')
118-
118+
119119
expect(page).to have_content("We are MENA Devs")
120120
expect(page).to have_content("one of the largest active online communities in the MENA region")
121121
end
122122
end
123123

124-
describe "GET /users/sign_in" do
125-
before do
126-
visit new_user_session_path
127-
128-
expect(page).to have_content('Login with your email and password')
129-
expect(page).to have_content('Email')
130-
expect(page).to have_content('Password')
131-
end
132-
133-
it "should login successfully using email and password" do
134-
fill_in 'Email', with: user.email
135-
fill_in 'Password', with: 'password'
136-
137-
click_on('Log in')
138-
139-
expect(page).to have_content("My Account")
140-
expect(page).to have_content("Logout")
141-
end
142-
143-
it "should not allow login if email does not exist" do
144-
fill_in 'Email', with: '[email protected]'
145-
fill_in 'Password', with: 'password'
146-
147-
click_on('Log in')
148-
149-
expect(page).to have_content('Email')
150-
expect(page).to have_content('Password')
151-
end
152-
end
153-
154124
describe "GET /directory/users" do
155125
before do
156126
create(:profile, user: open_profile_member, privacy_level: 2)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require 'rails_helper'
2+
3+
RSpec.describe EmailValidator, type: :model do
4+
describe "Email validations" do
5+
let(:user) { create(:user) }
6+
7+
it 'email_valid?' do
8+
user.email = 'random-email'
9+
10+
expect(user.valid?).to be_falsey
11+
end
12+
13+
it 'handle_contains_number_of_dots' do
14+
user.email = '[email protected]'
15+
16+
expect(user.valid?).to be_falsey
17+
end
18+
19+
it 'handle_last_character_is_not_dot' do
20+
user.email = '[email protected]'
21+
22+
expect(user.valid?).to be_falsey
23+
end
24+
end
25+
end

0 commit comments

Comments
 (0)