Skip to content

Commit f9191e5

Browse files
committed
Implement email confirmations
1 parent b96fa1f commit f9191e5

15 files changed

+127
-3
lines changed

Gemfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ group :development, :test do
7070
gem 'simplecov'
7171
end
7272

73+
group :development do
74+
gem 'letter_opener', '~> 1.6'
75+
end
76+
7377
group :test do
7478
gem 'json-schema', '~> 2.7.0'
7579
end

Gemfile.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ GEM
139139
jwt (2.1.0)
140140
launchy (2.4.3)
141141
addressable (~> 2.3)
142+
letter_opener (1.6.0)
143+
launchy (~> 2.2)
142144
little-plugger (1.1.4)
143145
logging (2.2.2)
144146
little-plugger (~> 1.1)
@@ -376,6 +378,7 @@ DEPENDENCIES
376378
jquery-rails (~> 3.1.2)
377379
json-schema (~> 2.7.0)
378380
launchy
381+
letter_opener (~> 1.6)
379382
logstasher (~> 0.9.0)
380383
mimemagic (~> 0.3.0)
381384
mimic (~> 0.4.3)

app/controllers/users_controller.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def create
3030
set_user_fields
3131

3232
if @user.errors.empty? && @user.save
33+
UserMailer.email_confirmation(@user).deliver_now
3334
if @bare_layout
3435
render text: '<div class="success" style="font-size: 14pt; margin: 10pt;">User account created.</div>', layout: true
3536
else
@@ -77,6 +78,20 @@ def update
7778
end
7879
end
7980

81+
def confirm_email
82+
token = VerificationToken.email.find_by!(user_id: params[:user_id], token: params[:id])
83+
User.find(params[:user_id]).update!(email_verified: true)
84+
redirect_to root_url, notice: 'Your email address has been verified!'
85+
end
86+
87+
def send_verification_email
88+
user = User.find(params[:user_id])
89+
raise 'Access denied' if user != current_user && !current_user.admin?
90+
raise 'Already verified' if user.email_verified?
91+
UserMailer.email_confirmation(user).deliver_now
92+
redirect_to root_path, notice: "Verification email sent to #{user.email}."
93+
end
94+
8095
private
8196

8297
def set_email

app/mailers/user_mailer.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class UserMailer < ActionMailer::Base
2+
def email_confirmation(user)
3+
@user = user
4+
token = user.verification_tokens.email.create!
5+
@url = base_url + confirm_email_path(@user.id, token.token)
6+
mail(from: SiteSetting.value('emails')['from'], to: user.email, subject: "Confirm your TestMyCode Account email address")
7+
end
8+
9+
10+
private
11+
12+
def base_url
13+
@base_url ||= begin
14+
settings = SiteSetting.value('emails')
15+
settings['baseurl'].sub(/\/+$/, '')
16+
end
17+
end
18+
end

app/models/user.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class User < ActiveRecord::Base
2626
has_many :organizations, through: :teacherships
2727
has_many :assistantships, dependent: :destroy
2828
has_many :assisted_courses, through: :assistantships, source: :course
29+
has_many :verification_tokens
2930

3031
validates :login, presence: true,
3132
uniqueness: { case_sensitive: false },

app/models/verification_token.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class VerificationToken < ActiveRecord::Base
2+
# This class does not use single table inheritance
3+
self.inheritance_column = :_type_disabled
4+
5+
belongs_to :user
6+
7+
enum type: [:email]
8+
9+
validates :type, presence: true
10+
validates :user, presence: true
11+
12+
default_scope { where(created_at: ((Time.current - 1.week)..Time.current)) }
13+
14+
before_create :generate_token
15+
16+
private
17+
18+
def generate_token
19+
self.token = SecureRandom.urlsafe_base64.to_s
20+
end
21+
end

app/views/layouts/landing.html.erb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
</div>
2929
<div id="everything">
3030
<div class="container container-fluid well-large" id="content-area">
31+
<% unless flash.empty? %>
32+
<br>
33+
<%= bootstrap_flash %>
34+
<% end %>
3135
<%= yield %>
3236
<br>
3337
<br>

app/views/participants/show.html.erb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
</section>
1919
</div>
2020

21+
<% unless @user.email_verified? %>
22+
<div class="alert alert-warning" role="alert">
23+
Your email address is not verified yet. <%= link_to 'Resend verification email', send_verification_email_path(@user), method: :post %>.
24+
</div>
25+
<% end %>
26+
2127
<section>
2228
<br>
2329
<h2>Points</h2>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5+
</head>
6+
<body>
7+
<p>Hey there!</p>
8+
9+
<p>Please click the following link to confirm that <b><%= @user.email %></b> is your email address for the TestMyCode account "<%= @user.login %>".</p>
10+
11+
<a href="<%= @url %>"><%= @url %></a>
12+
13+
<p>If this email doesn't make any sense, just ignore this message.</p>
14+
</body>
15+
</html>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Hey there!
2+
3+
Please click the following link to confirm that <%= @user.email %> is your email address for the TestMyCode account "<%= @user.login %>"
4+
5+
<%= @url %>
6+
7+
If this email doesn't make any sense, just ignore this message

0 commit comments

Comments
 (0)