diff --git a/app/controllers/emails_controller.rb b/app/controllers/emails_controller.rb index 8a32484b2..7f10f33f4 100644 --- a/app/controllers/emails_controller.rb +++ b/app/controllers/emails_controller.rb @@ -21,6 +21,7 @@ class EmailsController < ApplicationController if @user.errors.none? flash[:notice] = "Email updated" + UserMailer.email_change_confirmation(@user).deliver_later respond_with(@user, location: settings_url) else flash[:notice] = @user.errors.full_messages.join("; ") @@ -28,6 +29,15 @@ class EmailsController < ApplicationController end end + def verify + email_id = Danbooru::MessageVerifier.new(:email_verification_key).verify(params[:email_verification_key]) + @email_address = EmailAddress.find(email_id) + @email_address.update!(is_verified: true) + + flash[:notice] = "Email address verified" + redirect_to @email_address.user + end + private def check_privilege(user) diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 56a20b2a9..b61baf3f0 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -11,4 +11,9 @@ class UserMailer < ApplicationMailer @user = user mail to: @user.email_with_name, subject: "#{Danbooru.config.app_name} password reset request" end + + def email_change_confirmation(user) + @user = user + mail to: @user.email_with_name, subject: "Confirm your email address" + end end diff --git a/app/views/user_mailer/email_change_confirmation.html.erb b/app/views/user_mailer/email_change_confirmation.html.erb new file mode 100644 index 000000000..3fce8ad7e --- /dev/null +++ b/app/views/user_mailer/email_change_confirmation.html.erb @@ -0,0 +1,20 @@ + + +
++ You recently changed your email address on <%= Danbooru.config.app_name %>. + Click the link below to verify your new email address. +
+ ++ <%= link_to "Verify email address", verify_user_email_url(@user, email_verification_key: Danbooru::MessageVerifier.new(:email_verification_key).generate(@user.email_address.id)) %> +
+ ++ If you did not recently change your email address on <%= Danbooru.config.app_name %>, + you may delete and ignore this email. +
+ + diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 68548de9b..b100b5d56 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -27,6 +27,9 @@<% if @user.email_address.present? %> <%= @user.email_address.address %> + <% if !@user.email_address.is_verified %> + (unverified) + <% end %> <% else %> blank <% end %> diff --git a/config/routes.rb b/config/routes.rb index 501d0356f..8c6e9a25c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -245,7 +245,9 @@ Rails.application.routes.draw do end resources :users do resources :favorite_groups, controller: "favorite_groups", only: [:index], as: "favorite_groups" - resource :email, only: [:edit, :update] + resource :email, only: [:edit, :update] do + get :verify + end resource :password, only: [:edit, :update] resource :api_key, :only => [:show, :view, :update, :destroy], :controller => "maintenance/user/api_keys" do post :view diff --git a/test/functional/emails_controller_test.rb b/test/functional/emails_controller_test.rb index fea28ef72..cb22fbe78 100644 --- a/test/functional/emails_controller_test.rb +++ b/test/functional/emails_controller_test.rb @@ -3,7 +3,7 @@ require "test_helper" class EmailsControllerTest < ActionDispatch::IntegrationTest context "in all cases" do setup do - @user = create(:user, email_address: build(:email_address, { address: "bob@ogres.net" })) + @user = create(:user, email_address: build(:email_address, { address: "bob@ogres.net", is_verified: false })) end context "#edit" do @@ -20,6 +20,7 @@ class EmailsControllerTest < ActionDispatch::IntegrationTest assert_redirected_to(settings_path) assert_equal("abc@ogres.net", @user.reload.email_address.address) + assert_enqueued_email_with UserMailer, :email_change_confirmation, args: [@user] end end @@ -29,6 +30,19 @@ class EmailsControllerTest < ActionDispatch::IntegrationTest assert_response :success assert_equal("bob@ogres.net", @user.reload.email_address.address) + assert_no_emails + end + end + end + + context "#verify" do + context "with a correct verification key" do + should "mark the email address as verified" do + assert_equal(false, @user.reload.email_address.is_verified) + get_auth verify_user_email_path(@user), @user, params: { email_verification_key: Danbooru::MessageVerifier.new(:email_verification_key).generate(@user.email_address.id) } + + assert_redirected_to @user + assert_equal(true, @user.reload.email_address.is_verified) end end end diff --git a/test/mailers/previews/user_mailer_preview.rb b/test/mailers/previews/user_mailer_preview.rb index 595b47a50..4913e0a24 100644 --- a/test/mailers/previews/user_mailer_preview.rb +++ b/test/mailers/previews/user_mailer_preview.rb @@ -8,4 +8,9 @@ class UserMailerPreview < ActionMailer::Preview user = User.find(params[:id]) UserMailer.password_reset(user) end + + def email_change_confirmation + user = User.find(params[:id]) + UserMailer.email_change_confirmation(user) + end end