diff --git a/CHANGELOG.md b/CHANGELOG.md index fe1f3f3280..022ca96f02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +- Add Functionality Allowing Super Admins to Confirm/Unconfirm User Emails [#3535](https://github.com/DMPRoadmap/roadmap/pull/3535) - Updated seeds.rb file for identifier_schemes to include context value and removed logo_url and idenitifier_prefix for Shibboleth (as it was causing issues with SSO). [#3525](https://github.com/DMPRoadmap/roadmap/pull/3525) - Adjustments to style of select tags and plan download layout [#3509](https://github.com/DMPRoadmap/roadmap/pull/3509) - Fix failing eslint workflow / upgrade `actions/checkout` & `actions/setup-node` to v3 [#3503](https://github.com/DMPRoadmap/roadmap/pull/3503) diff --git a/app/controllers/super_admin/users_controller.rb b/app/controllers/super_admin/users_controller.rb index c4b96141b7..3b98ce978c 100644 --- a/app/controllers/super_admin/users_controller.rb +++ b/app/controllers/super_admin/users_controller.rb @@ -38,6 +38,7 @@ def update # Remove the extraneous Org Selector hidden fields attrs = remove_org_selection_params(params_in: attrs) + attrs = handle_confirmed_at_param(attrs) if @user.update(attrs) # If its a new Org create it @@ -125,7 +126,8 @@ def user_params :org_id, :org_name, :org_crosswalk, :department_id, :language_id, - :other_organisation) + :other_organisation, + :confirmed_at) end def merge_accounts @@ -136,5 +138,25 @@ def merge_accounts flash.now[:alert] = failure_message(@user, _('merge')) end end + + def handle_confirmed_at_param(attrs) + # NOTE: The :confirmed_at param is controlled by a check_box in the form + # `app/views/super_admin/users/_email_confirmation_status.html.erb`. + # When the checkbox is checked, Rails submits the string '1' (indicating "confirmed"). + # When unchecked, it submits the string '0' (indicating "unconfirmed"). + + # if an unconfirmed email is now being confirmed + if !@user.confirmed? && attrs[:confirmed_at] == '1' + attrs[:confirmed_at] = Time.current + # elsif a confirmed email is now being unconfirmed and the user is not a super admin + elsif @user.confirmed? && attrs[:confirmed_at] == '0' && !@user.can_super_admin? + attrs[:confirmed_at] = nil + else + # else delete the param + # (keeps value nil for unconfirmed user and maintains previous Time value for confirmed user) + attrs.delete(:confirmed_at) + end + attrs + end end end diff --git a/app/views/super_admin/users/_email_confirmation_status.html.erb b/app/views/super_admin/users/_email_confirmation_status.html.erb new file mode 100644 index 0000000000..2641962229 --- /dev/null +++ b/app/views/super_admin/users/_email_confirmation_status.html.erb @@ -0,0 +1,12 @@ +
+ <%= f.label(:confirmed_at, _('Email status: '), class: 'control-label') %> + <%= @user.confirmed? ? _("Confirmed.") : _("Unconfirmed.") %> +
+ <% is_checkbox_disabled = @user.can_super_admin? && @user.confirmed_at.present? %> + <%= f.check_box(:confirmed_at, { checked: @user.confirmed?, + disabled: is_checkbox_disabled, + style: 'vertical-align: middle; + margin-top: -2px;' }) %> + <% checkbox_helper_text = @user.confirmed? ? _('(Uncheck to unconfirm email)') : _('(Check to confirm email)') %> + <%= content_tag(:small, checkbox_helper_text) unless is_checkbox_disabled %> +
diff --git a/app/views/super_admin/users/edit.html.erb b/app/views/super_admin/users/edit.html.erb index d4dc76902b..e58da75449 100644 --- a/app/views/super_admin/users/edit.html.erb +++ b/app/views/super_admin/users/edit.html.erb @@ -57,6 +57,8 @@ <% end %> + <%= render 'email_confirmation_status', f: f %> +
<%= f.button(_('Save'), class: 'btn btn-secondary', type: "submit", id: "personal_details_registration_form_submit") %> diff --git a/spec/controllers/super_admin/users_controller_spec.rb b/spec/controllers/super_admin/users_controller_spec.rb new file mode 100644 index 0000000000..5d3232eb76 --- /dev/null +++ b/spec/controllers/super_admin/users_controller_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe SuperAdmin::UsersController, type: :controller do + let(:super_admin) { create(:user, :super_admin) } + let(:user) { create(:user, confirmed_at: nil) } + + before do + sign_in super_admin + end + + describe 'PUT #update' do + context 'when confirming an unconfirmed user' do + it 'sets confirmed_at to the current time' do + put :update, params: { id: user.id, user: { confirmed_at: '1' } } + user.reload + expect(user.confirmed_at).to be_a(Time) + end + end + + context 'when unconfirming a confirmed user' do + before do + user.update(confirmed_at: Time.current) + end + + it 'sets confirmed_at to nil' do + put :update, params: { id: user.id, user: { confirmed_at: '0' } } + user.reload + expect(user.confirmed_at).to be_nil + end + end + + context 'when update will not affect confirmation status' do + it 'does not update confirmed_at value for an already confirmed user' do + # (usec: 0) removes mircoseconds to better enable comparison + user.update(confirmed_at: Time.current.change(usec: 0)) + original_confirmed_at = user.confirmed_at + put :update, params: { id: user.id, user: { firstname: 'NewName', confirmed_at: '1' } } + user.reload + expect(user.confirmed_at).to eq(original_confirmed_at) + end + end + + context 'when attempting to set a super_admin to unconfirmed' do + it 'does not update confirmed_at value to nil' do + put :update, params: { id: super_admin.id, user: { confirmed_at: '0' } } + super_admin.reload + expect(super_admin.confirmed_at).not_to be_nil + end + end + end +end