Skip to content
Snippets Groups Projects
Commit 967c8058 authored by John Ma's avatar John Ma Committed by Jesus Federico
Browse files

Fixed #267 Email verification feature (#268)

* <Implemented basic welcome email upon signup>

* <Added config option to enable>

* <Added verification link routing>

* <Added views for verify/resend and reconfigured routes>

* <Finished Verification System minus Rspec changes>

* <Fixed code style>

* <Modified dome rspec tests>

* <Switched sample env back to default>

* <Added test cases to increase code coverage>

* <Added test_helper>

* <Minor code changes>

* <Added requested changes>

* <Added requested changes>

* <see if this fixes migration>

* <see if this fixes migration>

* <fixed migrations>

* Delete .rake_tasks~

* Update _confirm_button.html.erb

* Update _resend_button.html.erb

* Update verify_email.html.erb

* Update verify_email.text.erb

* <Fixed bugs>

* <Added validation of verification link and fixed some code style>

* <Disabled updating email for omniauth>
parent daaf305c
No related branches found
No related tags found
No related merge requests found
Showing
with 284 additions and 7 deletions
...@@ -4,5 +4,12 @@ ...@@ -4,5 +4,12 @@
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require_relative 'config/application' require_relative 'config/application'
require 'rake/testtask'
Rake::TestTask.new do |t|
t.libs << "test"
t.test_files = FileList['test/test*.rb']
t.verbose = true
end
Rails.application.load_tasks Rails.application.load_tasks
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
class RoomsController < ApplicationController class RoomsController < ApplicationController
before_action :validate_accepted_terms, unless: -> { !Rails.configuration.terms } before_action :validate_accepted_terms, unless: -> { !Rails.configuration.terms }
before_action :validate_verified_email, unless: -> { !Rails.configuration.enable_email_verification }
before_action :find_room, except: :create before_action :find_room, except: :create
before_action :verify_room_ownership, except: [:create, :show, :join, :logout] before_action :verify_room_ownership, except: [:create, :show, :join, :logout]
...@@ -184,4 +185,10 @@ class RoomsController < ApplicationController ...@@ -184,4 +185,10 @@ class RoomsController < ApplicationController
redirect_to terms_path unless current_user.accepted_terms redirect_to terms_path unless current_user.accepted_terms
end end
end end
def validate_verified_email
if current_user
redirect_to resend_path unless current_user.email_verified
end
end
end end
...@@ -28,7 +28,10 @@ class UsersController < ApplicationController ...@@ -28,7 +28,10 @@ class UsersController < ApplicationController
@user = User.new(user_params) @user = User.new(user_params)
@user.provider = "greenlight" @user.provider = "greenlight"
if @user.save if Rails.configuration.enable_email_verification && @user.save
UserMailer.verify_email(@user, verification_link(@user)).deliver
login(@user)
elsif @user.save
login(@user) login(@user)
else else
# Handle error on user creation. # Handle error on user creation.
...@@ -81,6 +84,9 @@ class UsersController < ApplicationController ...@@ -81,6 +84,9 @@ class UsersController < ApplicationController
errors.each { |k, v| @user.errors.add(k, v) } errors.each { |k, v| @user.errors.add(k, v) }
render :edit, params: { settings: params[:settings] } render :edit, params: { settings: params[:settings] }
end end
elsif user_params[:email] != @user.email && @user.update_attributes(user_params)
@user.update_attributes(email_verified: false)
redirect_to edit_user_path(@user), notice: I18n.t("info_update_success")
elsif @user.update_attributes(user_params) elsif @user.update_attributes(user_params)
redirect_to edit_user_path(@user), notice: I18n.t("info_update_success") redirect_to edit_user_path(@user), notice: I18n.t("info_update_success")
else else
...@@ -97,18 +103,50 @@ class UsersController < ApplicationController ...@@ -97,18 +103,50 @@ class UsersController < ApplicationController
redirect_to root_path redirect_to root_path
end end
# GET /terms # GET | POST /terms
def terms def terms
redirect_to '/404' unless Rails.configuration.terms redirect_to '/404' unless Rails.configuration.terms
if params[:accept] == "true" if params[:accept] == "true"
current_user.update_attributes(accepted_terms: true) current_user.update_attributes(accepted_terms: true)
redirect_to current_user.main_room if current_user login(current_user)
end
end
# GET | POST /u/verify/confirm
def confirm
if !current_user || current_user.uid != params[:user_uid]
redirect_to '/404'
elsif current_user.email_verified
login(current_user)
elsif params[:email_verified] == "true"
current_user.update_attributes(email_verified: true)
login(current_user)
else
render 'verify'
end
end
# GET /u/verify/resend
def resend
if !current_user
redirect_to '/404'
elsif current_user.email_verified
login(current_user)
elsif params[:email_verified] == "false"
UserMailer.verify_email(current_user, verification_link(current_user)).deliver
render 'verify'
else
render 'verify'
end end
end end
private private
def verification_link(user)
request.base_url + confirm_path(user.uid)
end
def find_user def find_user
@user = User.find_by!(uid: params[:user_uid]) @user = User.find_by!(uid: params[:user_uid])
end end
......
...@@ -21,14 +21,23 @@ module SessionsHelper ...@@ -21,14 +21,23 @@ module SessionsHelper
def login(user) def login(user)
session[:user_id] = user.id session[:user_id] = user.id
# If there are not terms, or the user has accepted them, go to their room. # If there are not terms, or the user has accepted them, check for email verification
if !Rails.configuration.terms || user.accepted_terms if !Rails.configuration.terms || user.accepted_terms
redirect_to user.main_room check_email_verified(user)
else else
redirect_to terms_path redirect_to terms_path
end end
end end
# If email verification is disabled, or the user has verified, go to their room
def check_email_verified(user)
if !Rails.configuration.enable_email_verification || user.email_verified
redirect_to user.main_room
else
redirect_to resend_path
end
end
# Logs current user out of GreenLight. # Logs current user out of GreenLight.
def logout def logout
session.delete(:user_id) if current_user session.delete(:user_id) if current_user
......
# frozen_string_literal: true
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
#
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
#
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
class UserMailer < ApplicationMailer
default from: 'notifications@example.com'
def verify_email(user, url)
@user = user
@url = url
mail(to: @user.email, subject: 'Welcome to BigBlueButton!')
end
end
...@@ -51,6 +51,7 @@ class User < ApplicationRecord ...@@ -51,6 +51,7 @@ class User < ApplicationRecord
u.username = auth_username(auth) unless u.username u.username = auth_username(auth) unless u.username
u.email = auth_email(auth) u.email = auth_email(auth)
u.image = auth_image(auth) u.image = auth_image(auth)
u.email_verified = true
u.save! u.save!
end end
end end
......
<% <%
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. # BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
#
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). # Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
#
# This program is free software; you can redistribute it and/or modify it under the # This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software # terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later # Foundation; either version 3.0 of the License, or (at your option) any later
...@@ -9,6 +11,7 @@ ...@@ -9,6 +11,7 @@
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY # BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. # PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. # with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%> %>
......
<% <%
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. # BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
#
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). # Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
#
# This program is free software; you can redistribute it and/or modify it under the # This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software # terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later # Foundation; either version 3.0 of the License, or (at your option) any later
...@@ -9,6 +11,7 @@ ...@@ -9,6 +11,7 @@
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY # BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. # PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. # with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%> %>
......
<%
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>
<div class="btn-list text-right pt-8">
<%= button_to t("verify.accept"), confirm_path, params: { user_uid: params[:user_uid], email_verified: true }, class: "btn btn-primary btn-space" %>
</div>
<%
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>
<div class="btn-list text-right pt-8">
<%= button_to t("verify.resend"), resend_path, params: { email_verified: false }, class: "btn btn-primary btn-space" %>
</div>
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
<div class="col-6"> <div class="col-6">
<%= f.label t("email"), class: "form-label" %> <%= f.label t("email"), class: "form-label" %>
<div class="input-icon"> <div class="input-icon">
<%= f.text_field :email, class: "form-control #{form_is_invalid?(@user, :email)}", placeholder: t("email") %> <%= f.text_field :email, class: "form-control #{form_is_invalid?(@user, :email)}", placeholder: t("email"), readonly: !current_user.greenlight_account? %>
</div> </div>
</div> </div>
</div> </div>
......
<%
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
#
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
#
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<h1>Welcome to Greenlight!, <%= @user.name %></h1>
<p>
You have successfully signed up for Greenlight,
your username is: <%= @user.email %>.<br>
</p>
<p>
To verify your account, just follow this link: <%= link_to 'verify your email', @url %>.
</p>
<p>Thanks for joining and have a great day!</p>
</body>
</html>
<%
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
#
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
#
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>
Welcome to Greenlight, <%= @user.name %>
===============================================
You have successfully signed up for Greenlight,
your username is: <%= @user.email %>.
To verify your account, just follow this link: <%= link_to 'verify your email', @url %>.
Thanks for joining and have a great day!
<%
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>
<div class="container pt-5">
<div class="col-md-8 offset-2">
<div class="card">
<div class="card-header">
<h3 class="card-title"><%= t("verify.title") %></h3>
</div>
<div class="card-body">
<p> Your account has not been verified yet. </p>
<% if Rails.configuration.enable_email_verification && params[:user_uid] == current_user.uid %>
<%= render "/shared/components/confirm_button" %>
<% else %>
<%= render "/shared/components/resend_button" %>
<% end %>
</form>
</div>
</div>
</div>
</div>
...@@ -68,6 +68,9 @@ module Greenlight ...@@ -68,6 +68,9 @@ module Greenlight
config.bigbluebutton_endpoint += "api/" unless config.bigbluebutton_endpoint.ends_with?('api/') config.bigbluebutton_endpoint += "api/" unless config.bigbluebutton_endpoint.ends_with?('api/')
end end
# Determine if GreenLight should enable email verification
config.enable_email_verification = (ENV['GREENLIGHT_MAIL_NOTIFICATIONS'] == "true")
# Determine if GreenLight should allow non-omniauth signup/login. # Determine if GreenLight should allow non-omniauth signup/login.
config.allow_user_signup = (ENV['ALLOW_GREENLIGHT_ACCOUNTS'] == "true") config.allow_user_signup = (ENV['ALLOW_GREENLIGHT_ACCOUNTS'] == "true")
......
...@@ -28,6 +28,19 @@ Rails.application.configure do ...@@ -28,6 +28,19 @@ Rails.application.configure do
config.cache_store = :null_store config.cache_store = :null_store
end end
# Tell Action Mailer to use smtp server
config.action_mailer.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
address: ENV['SMTP_SERVER'],
port: ENV["SMTP_PORT"],
domain: ENV['SMTP_DOMAIN'],
user_name: ENV['SMTP_USERNAME'],
password: ENV['SMTP_PASSWORD'],
authentication: ENV['SMTP_AUTH'],
enable_starttls_auto: ENV['SMTP_STARTTLS_AUTO'],
}
# Don't care if the mailer can't send. # Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false config.action_mailer.raise_delivery_errors = false
......
...@@ -164,3 +164,7 @@ en: ...@@ -164,3 +164,7 @@ en:
This deployment is using a pre-configured testing server, you should replace this with your own. This deployment is using a pre-configured testing server, you should replace this with your own.
For details, see the %{href}. For details, see the %{href}.
update: Update update: Update
verify:
title: Verify your email
resend: Resend verification email
accept: Verify
...@@ -31,6 +31,12 @@ Rails.application.routes.draw do ...@@ -31,6 +31,12 @@ Rails.application.routes.draw do
# User resources. # User resources.
scope '/u' do scope '/u' do
# Verification Routes
scope '/verify' do
match '/resend', to: 'users#resend', via: [:get, :post], as: :resend
match '/confirm/:user_uid', to: 'users#confirm', via: [:get, :post], as: :confirm
end
# Handles login of greenlight provider accounts. # Handles login of greenlight provider accounts.
post '/login', to: 'sessions#create', as: :create_session post '/login', to: 'sessions#create', as: :create_session
......
# frozen_string_literal: true
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
#
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
#
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
class AddEmailVerifiedToUser < ActiveRecord::Migration[5.0]
def change
add_column :users, :email_verified, :boolean, default: false
end
end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180504131705) do ActiveRecord::Schema.define(version: 20180920193451) do
create_table "rooms", force: :cascade do |t| create_table "rooms", force: :cascade do |t|
t.integer "user_id" t.integer "user_id"
...@@ -42,6 +42,7 @@ ActiveRecord::Schema.define(version: 20180504131705) do ...@@ -42,6 +42,7 @@ ActiveRecord::Schema.define(version: 20180504131705) do
t.boolean "accepted_terms", default: false t.boolean "accepted_terms", default: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.boolean "email_verified", default: false
t.index ["password_digest"], name: "index_users_on_password_digest", unique: true t.index ["password_digest"], name: "index_users_on_password_digest", unique: true
t.index ["room_id"], name: "index_users_on_room_id" t.index ["room_id"], name: "index_users_on_room_id"
end end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment