Show "Resend Confirmation email" option on users profile when email not confirmed (#20831)

* Show reconfirmation option on users profile

* spec
This commit is contained in:
Philip How 2024-04-03 14:53:53 +01:00 committed by GitHub
parent e22e6284e4
commit 0d873a4554
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 126 additions and 12 deletions

View file

@ -312,6 +312,33 @@ module Admin
end
end
def send_email_confirmation
@user = User.find(params[:id])
if @user.send_confirmation_instructions
respond_to do |format|
message = I18n.t("admin.users_controller.confirm_sent")
format.html do
flash[:success] = message
redirect_back(fallback_location: admin_user_path(params[:id]))
end
format.js { render json: { result: message }, content_type: "application/json" }
end
else
message = I18n.t("admin.users_controller.email_fail")
respond_to do |format|
format.html do
flash[:danger] = message
redirect_back(fallback_location: admin_user_path(params[:id]))
end
format.js { render json: { error: message }, content_type: "application/json", status: :service_unavailable }
end
end
end
def verify_email_ownership
if VerificationMailer.with(user_id: params[:id]).account_ownership_verification_email.deliver_now
respond_to do |format|

View file

@ -1,14 +1,26 @@
<%= form_with url: verify_email_ownership_admin_user_path(@user), local: true, class: "crayons-card mb-4 p-3 m:p-4 s:pl-4 m:pl-7 pr-4 flex flex-col s:flex-row justify-between gap-4 s:items-center" do |f| %>
<% unless @last_email_verification_date %>
<div>
<h2 class="crayons-subtitle-1"><%= t("views.admin.users.emails.not_verified.subtitle") %></h2>
<p class="color-secondary"><%= t("views.admin.users.emails.not_verified.desc", user: @user.name) %></p>
</div>
<%= f.button t("views.admin.users.emails.verify"), class: "c-btn c-btn--secondary whitespace-nowrap" %>
<div class="crayons-card mb-4 p-3 m:p-4 s:pl-4 m:pl-7 pr-4">
<% unless @user.confirmed? %>
<%= form_with url: send_email_confirmation_admin_user_path(@user), local: true, class: "flex flex-col s:flex-row justify-between gap-4 s:items-center" do |f| %>
<div>
<h2 class="crayons-subtitle-1"><%= t("views.admin.users.emails.not_confirmed.subtitle") %></h2>
<p class="color-secondary"><%= t("views.admin.users.emails.not_confirmed.desc", user: @user.name) %></p>
</div>
<%= f.button t("views.admin.users.emails.confirm"), class: "c-btn c-btn--secondary whitespace-nowrap" %>
<% end %>
<% else %>
<p>
<%= t("views.admin.users.emails.verified_html", time: tag.time(l(@last_email_verification_date, format: :email_verified), datetime: @last_email_verification_date.strftime("%Y-%m-%dT%H:%M:%S%z"), class: "fw-medium whitespace-nowrap")) %>
</p>
<%= f.button t("views.admin.users.emails.reverify"), class: "c-btn c-btn--secondary whitespace-nowrap" %>
<%= form_with url: verify_email_ownership_admin_user_path(@user), local: true, class: "flex flex-col s:flex-row justify-between gap-4 s:items-center" do |f| %>
<% unless @last_email_verification_date %>
<div>
<h2 class="crayons-subtitle-1"><%= t("views.admin.users.emails.not_verified.subtitle") %></h2>
<p class="color-secondary"><%= t("views.admin.users.emails.not_verified.desc", user: @user.name) %></p>
</div>
<%= f.button t("views.admin.users.emails.verify"), class: "c-btn c-btn--secondary whitespace-nowrap" %>
<% else %>
<p>
<%= t("views.admin.users.emails.verified_html", time: tag.time(l(@last_email_verification_date, format: :email_verified), datetime: @last_email_verification_date.strftime("%Y-%m-%dT%H:%M:%S%z"), class: "fw-medium whitespace-nowrap")) %>
</p>
<%= f.button t("views.admin.users.emails.reverify"), class: "c-btn c-btn--secondary whitespace-nowrap" %>
<% end %>
<% end %>
<% end %>
<% end %>
</div>

View file

@ -128,6 +128,7 @@ en:
exported: Data exported to the %{receiver}. The job will complete momentarily.
email_fail: Email failed to send!
email_sent: Email sent!
confirm_sent: Confirmation email sent!
verify_sent: Verification email sent!
full_delete_html: '@%{user} (email: %{email}, user_id: %{id}) has been fully deleted. If this is a GDPR delete, delete them from Mailchimp & Google Analytics and confirm on %{the_page}.'
no_email: no email

View file

@ -128,6 +128,7 @@ fr:
exported: Données exportées vers le %{receiver}. Le travail sera terminé dans un instant.
email_fail: L'envoi de l'e-mail a échoué !
email_sent: Courriel envoyé !
confirm_sent: Courriel de Confirmation Envoyé!
verify_sent: E-mail de vérification envoyé !
full_delete_html: "@%{user} (email: %{email}, user_id: %{id}) a été entièrement supprimé. S'il s'agit d'une suppression GDPR, supprimez-les de Mailchimp & Google Analytics et confirmez sur %{the_page}."
no_email: Aucun e-mail

View file

@ -208,6 +208,7 @@ en:
note_placeholder: "Note text"
submit: Unpublish all posts
emails:
confirm: Resend confirmation
empty1: No previous emails found for %{user}.
empty2: Any emails sent to %{email} will be found here.
previous: Previous emails (%{num})
@ -218,6 +219,9 @@ en:
body: Body
body_placeholder: What do you want to say?
send_submit: Send email
not_confirmed:
subtitle: Email not confirmed
desc: "%{user}'s email hasn't been confirmed yet."
not_verified:
subtitle: Email not verified
desc: "%{user}'s email hasn't been verified yet."

View file

@ -221,6 +221,9 @@ fr:
not_verified:
subtitle: Email not verified
desc: "%{user}'s email hasn't been verified yet."
not_confirmed:
subtitle: E-mail non confirmé
desc: "L'e-mail de %{user} n'a pas encore été confirmé."
verify: Verify email address
verified_html: Last verified on %{time}
reverify: Reverify

View file

@ -56,6 +56,7 @@ namespace :admin do
delete "remove_identity"
post "send_email"
post "verify_email_ownership"
post "send_email_confirmation"
patch "unlock_access"
post "unpublish_all_articles"
end

View file

@ -212,6 +212,71 @@ RSpec.describe "/admin/member_manager/users" do
end
end
describe "POST /admin/member_manager/users/:id/send_email_confirmation" do
let(:user) { create(:user) }
let(:message_delivery) { instance_double(ActionMailer::MessageDelivery) }
before do
allow(ForemInstance).to receive(:smtp_enabled?).and_return(true)
end
context "when interacting via a browser" do
it "returns not found for non-existing users" do
expect do
post send_email_confirmation_admin_user_path(9999)
end.to raise_error(ActiveRecord::RecordNotFound)
end
it "fails sending the confirmation email if an error occurs" do
allow(User).to receive(:find).with(user.id.to_s).and_return(user)
allow(user).to receive(:send_confirmation_instructions).and_return(false)
post send_email_confirmation_admin_user_path(user)
expect(response).to redirect_to(admin_user_path(user))
expect(flash[:danger]).to include("failed")
end
it "sends the confirmation email successfully" do
allow(User).to receive(:find).with(user.id.to_s).and_return(user)
allow(user).to receive(:send_confirmation_instructions).and_return(true)
post send_email_confirmation_admin_user_path(user)
expect(response).to redirect_to(admin_user_path(user))
expect(flash[:success]).to include("sent")
end
end
context "when interacting via AJAX" do
it "returns not found for non-existing users" do
expect do
post send_email_confirmation_admin_user_path(9999), xhr: true
end.to raise_error(ActiveRecord::RecordNotFound)
end
it "fails sending the confirmation email if an error occurs" do
allow(User).to receive(:find).with(user.id.to_s).and_return(user)
allow(user).to receive(:send_confirmation_instructions).and_return(false)
post send_email_confirmation_admin_user_path(user), xhr: true
expect(response).to have_http_status(:service_unavailable)
expect(response.parsed_body["error"]).to include("failed")
end
it "sends the confirmation email successfully" do
allow(User).to receive(:find).with(user.id.to_s).and_return(user)
allow(user).to receive(:send_confirmation_instructions).and_return(true)
post send_email_confirmation_admin_user_path(user), xhr: true
expect(response).to have_http_status(:ok)
expect(response.parsed_body["result"]).to include("sent")
end
end
end
describe "POST /admin/member_manager/users/:id/verify_email_ownership" do
let(:mailer) { double }
let(:message_delivery) { double }