Send a confirmation email when the user adds a secondary email address. Utilizes the Devise confirmable
capabilities. Issue #37385
This commit is contained in:
parent
b146415798
commit
f9f4672275
19 changed files with 109 additions and 89 deletions
|
@ -11,11 +11,12 @@ class ConfirmationsController < Devise::ConfirmationsController
|
|||
end
|
||||
|
||||
def after_confirmation_path_for(resource_name, resource)
|
||||
if signed_in?(resource_name)
|
||||
# incoming resource can either be a :user or an :email
|
||||
if signed_in?(:user)
|
||||
after_sign_in_path_for(resource)
|
||||
else
|
||||
flash[:notice] += " Please sign in."
|
||||
new_session_path(resource_name)
|
||||
new_session_path(:user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,10 +6,7 @@ class Profiles::EmailsController < Profiles::ApplicationController
|
|||
|
||||
def create
|
||||
@email = Emails::CreateService.new(current_user, email_params).execute
|
||||
|
||||
if @email.errors.blank?
|
||||
NotificationService.new.new_email(@email)
|
||||
else
|
||||
unless @email.errors.blank?
|
||||
flash[:alert] = @email.errors.full_messages.first
|
||||
end
|
||||
|
||||
|
|
|
@ -7,12 +7,6 @@ module Emails
|
|||
mail(to: @user.notification_email, subject: subject("Account was created for you"))
|
||||
end
|
||||
|
||||
def new_email_email(email_id)
|
||||
@email = Email.find(email_id)
|
||||
@current_user = @user = @email.user
|
||||
mail(to: @user.notification_email, subject: subject("Email was added to your account"))
|
||||
end
|
||||
|
||||
def new_ssh_key_email(key_id)
|
||||
@key = Key.find_by(id: key_id)
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@ class Email < ActiveRecord::Base
|
|||
validates :email, presence: true, uniqueness: true, email: true
|
||||
validate :unique_email, if: ->(email) { email.email_changed? }
|
||||
|
||||
devise :confirmable
|
||||
self.reconfirmable = false # currently email can't be changed, no need to reconfirm
|
||||
|
||||
def email=(value)
|
||||
write_attribute(:email, value.downcase.strip)
|
||||
end
|
||||
|
|
|
@ -31,13 +31,6 @@ class NotificationService
|
|||
end
|
||||
end
|
||||
|
||||
# Always notify user about email added to profile
|
||||
def new_email(email)
|
||||
if email.user&.can?(:receive_notifications)
|
||||
mailer.new_email_email(email.id).deliver_later
|
||||
end
|
||||
end
|
||||
|
||||
# When create an issue we should send an email to:
|
||||
#
|
||||
# * issue assignee if their notification level is not Disabled
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#content
|
||||
= email_default_heading("#{@resource.user.name}, you've added a secondary email!")
|
||||
%p Click the link below to confirm your email address (#{@resource.email})
|
||||
#cta
|
||||
= link_to 'Confirm your email address', confirmation_url(@resource, confirmation_token: @token)
|
||||
%p
|
||||
If this email was added in error, you can remove it here:
|
||||
= link_to "Emails", profile_emails_url
|
|
@ -0,0 +1,7 @@
|
|||
<%= @resource.user.name %>, you've added a secondary email!
|
||||
|
||||
You can confirm your email (<%= @resource.email %>) through the link below:
|
||||
|
||||
<%= confirmation_url(@resource, confirmation_token: @token) %>
|
||||
|
||||
If this email was added in error, you can remove it here: <%= profile_emails_url %>
|
|
@ -1,3 +1,6 @@
|
|||
- if @resource.is_a?(Email)
|
||||
= render partial: 'confirmation_instructions_secondary'
|
||||
- else
|
||||
- if @resource.unconfirmed_email.present?
|
||||
#content
|
||||
= email_default_heading(@resource.unconfirmed_email)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<% if @resource.is_a?(Email) %>
|
||||
<%= render partial: 'confirmation_instructions_secondary' %>
|
||||
<% else %>
|
||||
Welcome, <%= @resource.name %>!
|
||||
|
||||
<% if @resource.unconfirmed_email.present? %>
|
||||
|
@ -7,3 +10,4 @@ You can confirm your account through the link below:
|
|||
<% end %>
|
||||
|
||||
<%= confirmation_url(@resource, confirmation_token: @token) %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
%p
|
||||
Hi #{@user.name}!
|
||||
%p
|
||||
A new email was added to your account:
|
||||
%p
|
||||
email:
|
||||
%code= @email.email
|
||||
%p
|
||||
If this email was added in error, you can remove it here:
|
||||
= link_to "Emails", profile_emails_url
|
|
@ -1,7 +0,0 @@
|
|||
Hi <%= @user.name %>!
|
||||
|
||||
A new email was added to your account:
|
||||
|
||||
email.................. <%= @email.email %>
|
||||
|
||||
If this email was added in error, you can remove it here: <%= profile_emails_url %>
|
|
@ -47,4 +47,6 @@
|
|||
%span.label.label-info Public email
|
||||
- if email.email === current_user.notification_email
|
||||
%span.label.label-info Notification email
|
||||
- if !email.confirmed?
|
||||
%span.label.label-warning Unconfirmed
|
||||
= link_to 'Remove', profile_email_path(email), data: { confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-sm btn-warning prepend-left-10'
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: A confirmation email is now sent when adding a secondary email address
|
||||
merge_request:
|
||||
author: digitalmoksha
|
||||
type: added
|
|
@ -11,6 +11,11 @@ devise_scope :user do
|
|||
get '/users/almost_there' => 'confirmations#almost_there'
|
||||
end
|
||||
|
||||
# for secondary email confirmations
|
||||
devise_for :emails, controllers: { confirmations: :confirmations }
|
||||
devise_scope :email do
|
||||
end
|
||||
|
||||
scope(constraints: { username: Gitlab::PathRegex.root_namespace_route_regex }) do
|
||||
scope(path: 'users/:username',
|
||||
as: :user,
|
||||
|
|
34
db/migrate/20170904092148_add_email_confirmation.rb
Normal file
34
db/migrate/20170904092148_add_email_confirmation.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
|
||||
# for more information on how to write migrations for GitLab.
|
||||
|
||||
class AddEmailConfirmation < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
# Set this constant to true if this migration requires downtime.
|
||||
DOWNTIME = false
|
||||
|
||||
# When a migration requires downtime you **must** uncomment the following
|
||||
# constant and define a short and easy to understand explanation as to why the
|
||||
# migration requires downtime.
|
||||
# DOWNTIME_REASON = ''
|
||||
|
||||
# When using the methods "add_concurrent_index", "remove_concurrent_index" or
|
||||
# "add_column_with_default" you must disable the use of transactions
|
||||
# as these methods can not run in an existing transaction.
|
||||
# When using "add_concurrent_index" or "remove_concurrent_index" methods make sure
|
||||
# that either of them is the _only_ method called in the migration,
|
||||
# any other changes should go in a separate migration.
|
||||
# This ensures that upon failure _only_ the index creation or removing fails
|
||||
# and can be retried or reverted easily.
|
||||
#
|
||||
# To disable transactions uncomment the following line and remove these
|
||||
# comments:
|
||||
# disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
add_column :emails, :confirmation_token, :string
|
||||
add_column :emails, :confirmed_at, :datetime
|
||||
add_column :emails, :confirmation_sent_at, :datetime
|
||||
add_index :emails, :confirmation_token, unique: true
|
||||
end
|
||||
end
|
|
@ -329,7 +329,6 @@ module API
|
|||
email = Emails::CreateService.new(user, declared_params(include_missing: false)).execute
|
||||
|
||||
if email.errors.blank?
|
||||
NotificationService.new.new_email(email)
|
||||
present email, with: Entities::Email
|
||||
else
|
||||
render_validation_error!(email)
|
||||
|
@ -675,7 +674,6 @@ module API
|
|||
email = Emails::CreateService.new(current_user, declared_params).execute
|
||||
|
||||
if email.errors.blank?
|
||||
NotificationService.new.new_email(email)
|
||||
present email, with: Entities::Email
|
||||
else
|
||||
render_validation_error!(email)
|
||||
|
|
20
spec/controllers/profiles/emails_controller_spec.rb
Normal file
20
spec/controllers/profiles/emails_controller_spec.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Profiles::EmailsController do
|
||||
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
let(:email_params) { {email: "add_email@example.com" } }
|
||||
|
||||
it 'sends an email confirmation' do
|
||||
expect {post(:create, { email: email_params })}.to change { ActionMailer::Base.deliveries.size }
|
||||
expect(ActionMailer::Base.deliveries.last.to).to eq [email_params[:email]]
|
||||
expect(ActionMailer::Base.deliveries.last.subject).to match "Confirmation instructions"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -120,29 +120,4 @@ describe Emails::Profile do
|
|||
it { expect { Notify.new_gpg_key_email('foo') }.not_to raise_error }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'user added email' do
|
||||
let(:email) { create(:email) }
|
||||
|
||||
subject { Notify.new_email_email(email.id) }
|
||||
|
||||
it_behaves_like 'it should not have Gmail Actions links'
|
||||
it_behaves_like 'a user cannot unsubscribe through footer link'
|
||||
|
||||
it 'is sent to the new user' do
|
||||
is_expected.to deliver_to email.user.email
|
||||
end
|
||||
|
||||
it 'has the correct subject' do
|
||||
is_expected.to have_subject /^Email was added to your account$/i
|
||||
end
|
||||
|
||||
it 'contains the new email address' do
|
||||
is_expected.to have_body_text /#{email.email}/
|
||||
end
|
||||
|
||||
it 'includes a link to emails page' do
|
||||
is_expected.to have_body_text /#{profile_emails_path}/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -105,18 +105,6 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Email' do
|
||||
describe '#new_email' do
|
||||
let!(:email) { create(:email) }
|
||||
|
||||
it { expect(notification.new_email(email)).to be_truthy }
|
||||
|
||||
it 'sends email to email owner' do
|
||||
expect { notification.new_email(email) }.to change { ActionMailer::Base.deliveries.size }.by(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Notes' do
|
||||
context 'issue note' do
|
||||
let(:project) { create(:project, :private) }
|
||||
|
|
Loading…
Reference in a new issue