Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Account page using design system #2377

Merged
merged 35 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4322f8e
Inline partial
mike29736 Sep 19, 2023
453341e
Use the Error Summary component
mike29736 Sep 19, 2023
81c7f23
Inline string from locales
mike29736 Sep 19, 2023
e869ac3
Group `alias_method`s more clearly
mike29736 Sep 20, 2023
ad6d785
Move "Change your email or password" to /account
mike29736 Sep 19, 2023
fd5038b
Move #update_email to /account namespace
mike29736 Sep 20, 2023
9e8eb24
Move #update_password to /account namespace
mike29736 Sep 21, 2023
a3f5a79
A separate #resend_email_change for /account
mike29736 Sep 21, 2023
f39cbc2
Extract User#cancel_email_change!
mike29736 Sep 21, 2023
9b06439
A separate #cancel_email_change for /account
mike29736 Sep 21, 2023
091cfcd
Use `redirect_to` instead of `redirect_back_or_to`
mike29736 Sep 27, 2023
6dba232
Extract duplicate flash notice
mike29736 Sep 25, 2023
218f4f8
Add missing flash message
mike29736 Sep 25, 2023
18ea94e
Introduce new Account page with one sub-page
mike29736 Sep 22, 2023
240e98e
Use breadcrumbs on Change email or password page
mike29736 Sep 22, 2023
63d3fe3
Add Account page to sub-page's breadcrumbs
mike29736 Sep 22, 2023
d38344b
Point redirects to Account page, not to Dashboard
mike29736 Sep 29, 2023
76dea66
Build a temporary Manage permissions page
mike29736 Sep 29, 2023
5b4f7f5
Link to Manage permissions from Account page
mike29736 Sep 22, 2023
cc93b37
Redirect from Manage permissions to Account page
mike29736 Sep 29, 2023
134877f
Un-nest Devise routes
mike29736 Sep 22, 2023
67c279f
Move 2SV setup page to /account
mike29736 Sep 22, 2023
79c112a
Extract conditional page title/name to helper
mike29736 Sep 28, 2023
6c662c3
Link to 2SV setup page from Account page
mike29736 Sep 22, 2023
f57bbdd
Use breadcrumbs on 2SV setup page
mike29736 Sep 22, 2023
acc8ec6
Add Account page to 2SV page's breadcrumbs
mike29736 Sep 22, 2023
e1d4c39
Introduce parameter to method
mike29736 Sep 26, 2023
56b56cc
Redirect from 2SV setup page to Account page
mike29736 Sep 25, 2023
0bf6496
Introduce Role and organisation Account sub-page
mike29736 Sep 26, 2023
549dd67
Extract event logs table partial
mike29736 Sep 28, 2023
5c35d13
Introduce Your account access log Account sub-page
mike29736 Sep 28, 2023
8b1c699
Only Super Admin users can update their role
chrisroos Oct 3, 2023
acad605
Redirect users to account page for editing their own account
chrisroos Oct 3, 2023
bcde442
Prevent users editing their details on users/edit pages
chrisroos Oct 3, 2023
22c3626
Avoid using Pundit.policy in _form_fields partial
chrisroos Oct 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions app/controllers/account/activities_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Account::ActivitiesController < ApplicationController
layout "admin_layout"

before_action :authenticate_user!
before_action :authorise_user

def show
@logs = current_user.event_logs.page(params[:page]).per(100)
end

private

def authorise_user
authorize %i[account activities]
end
end
69 changes: 69 additions & 0 deletions app/controllers/account/email_passwords_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
class Account::EmailPasswordsController < ApplicationController
layout "admin_layout"

before_action :authenticate_user!
before_action :authorise_user

def show; end

def update_email
current_email = current_user.email
new_email = params[:user][:email]
if current_email == new_email.strip
flash[:alert] = "Nothing to update."
render :show
elsif current_user.update(email: new_email)
EventLog.record_email_change(current_user, current_email, new_email)
UserMailer.email_changed_notification(current_user).deliver_later
redirect_to account_path, notice: email_change_notice
else
render :show
end
end

def update_password
if current_user.update_with_password(password_params)
EventLog.record_event(current_user, EventLog::SUCCESSFUL_PASSWORD_CHANGE, ip_address: user_ip_address)
flash[:notice] = t(:updated, scope: "devise.passwords")
bypass_sign_in(current_user)
redirect_to account_path
else
EventLog.record_event(current_user, EventLog::UNSUCCESSFUL_PASSWORD_CHANGE, ip_address: user_ip_address)
render :show
end
end

def resend_email_change
current_user.resend_confirmation_instructions
if current_user.errors.empty?
redirect_to account_path, notice: email_change_notice
else
redirect_to account_email_password_path, alert: "Failed to send email change email"
end
end

def cancel_email_change
current_user.cancel_email_change!

redirect_to account_path, notice: "You have cancelled your pending email address change."
mike29736 marked this conversation as resolved.
Show resolved Hide resolved
end

private

def authorise_user
authorize %i[account email_passwords]
end

def password_params
params.require(:user).permit(
:current_password,
:password,
:password_confirmation,
)
end

def email_change_notice
"An email has been sent to #{current_user.unconfirmed_email}. "\
"Follow the link in the email to update your address."
end
end
38 changes: 38 additions & 0 deletions app/controllers/account/manage_permissions_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class Account::ManagePermissionsController < ApplicationController
include UserPermissionsControllerMethods
helper_method :applications_and_permissions

before_action :authenticate_user!
before_action :authorise_user

def show
@application_permissions = all_applications_and_permissions_for(current_user)
end

def update
updater = UserUpdate.new(current_user, user_params, current_user, user_ip_address)
if updater.call
redirect_to account_path, notice: "Your permissions have been updated."
else
@application_permissions = all_applications_and_permissions_for(current_user)
render :show
end
end

private

def authorise_user
authorize %i[account manage_permissions]
end

def user_params
UserParameterSanitiser.new(
user_params: permitted_user_params,
current_user_role: current_user.role.to_sym,
).sanitise
end

def permitted_user_params
params.fetch(:user, {}).permit(supported_permission_ids: []).to_h
end
end
37 changes: 37 additions & 0 deletions app/controllers/account/role_organisations_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
class Account::RoleOrganisationsController < ApplicationController
layout "admin_layout"

before_action :authenticate_user!
before_action :authorise_user

def show; end

def update_organisation
organisation_id = params[:user][:organisation_id]
organisation = Organisation.find(organisation_id)

if UserUpdate.new(current_user, { organisation_id: }, current_user, user_ip_address).call
redirect_to account_path, notice: "Your organisation is now #{organisation.name}"
else
flash[:alert] = "There was a problem changing your organisation."
render :show
end
end

def update_role
role = params[:user][:role]

if UserUpdate.new(current_user, { role: }, current_user, user_ip_address).call
redirect_to account_path, notice: "Your role is now #{role.humanize}"
else
flash[:alert] = "There was a problem changing your role."
render :show
end
end

private

def authorise_user
authorize %i[account role_organisations]
end
end
8 changes: 2 additions & 6 deletions app/controllers/accounts_controller.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
class AccountsController < ApplicationController
layout "admin_layout"

before_action :authenticate_user!

def show
authorize :account_page

if policy(current_user).edit?
redirect_to edit_user_path(current_user)
else
redirect_to edit_email_or_password_user_path(current_user)
end
end
end
4 changes: 2 additions & 2 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def notify_bad_request(_exception)
render plain: "Error: One or more recipients not in GOV.UK Notify team (code: 400)", status: :bad_request
end

def redirect_to_prior_flow(args = {})
redirect_to stored_location_for("2sv") || :root, args
def redirect_to_prior_flow_or_to(fallback_location, args = {})
redirect_to stored_location_for("2sv") || fallback_location, args
end
end
2 changes: 1 addition & 1 deletion app/controllers/devise/two_step_verification_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def update
if verify_code_and_update
EventLog.record_event(current_user, success_event_for(mode), ip_address: user_ip_address)
send_notification(current_user, mode)
redirect_to_prior_flow notice: I18n.t("devise.two_step_verification.messages.success.#{mode}")
redirect_to_prior_flow_or_to account_path, notice: I18n.t("devise.two_step_verification.messages.success.#{mode}")
else
EventLog.record_event(current_user, failure_event_for(mode), ip_address: user_ip_address)
flash.now[:invalid_code] = "Sorry that code didn’t work. Please try again."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def create
warden.session(:user)["need_two_step_verification"] = false
bypass_sign_in current_user
set_flash_message :notice, :success
redirect_to_prior_flow
redirect_to_prior_flow_or_to root_path
current_user.update!(second_factor_attempts_count: 0)
else
flash.now[:alert] = find_message(:attempt_failed)
Expand Down
51 changes: 6 additions & 45 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class UsersController < ApplicationController
include UserPermissionsControllerMethods

layout "admin_layout", only: %w[index edit_email_or_password event_logs require_2sv]
layout "admin_layout", only: %w[index event_logs require_2sv]

before_action :authenticate_user!, except: :show
before_action :load_and_authorize_user, except: %i[index show]
Expand Down Expand Up @@ -69,21 +69,15 @@ def unlock
def resend_email_change
@user.resend_confirmation_instructions
if @user.errors.empty?
notice = if @user.normal?
"An email has been sent to #{@user.unconfirmed_email}. Follow the link in the email to update your address."
else
"Successfully resent email change email to #{@user.unconfirmed_email}"
end
redirect_to root_path, notice:
redirect_to root_path, notice: "Successfully resent email change email to #{@user.unconfirmed_email}"
mike29736 marked this conversation as resolved.
Show resolved Hide resolved
else
redirect_to edit_user_path(@user), alert: "Failed to send email change email"
end
end

def cancel_email_change
@user.unconfirmed_email = nil
@user.confirmation_token = nil
@user.save!(validate: false)
@user.cancel_email_change!

redirect_back_or_to(root_path)
end

Expand All @@ -92,33 +86,6 @@ def event_logs
@logs = @user.event_logs.page(params[:page]).per(100) if @user
end

def update_email
current_email = @user.email
new_email = params[:user][:email]
if current_email == new_email.strip
flash[:alert] = "Nothing to update."
render :edit_email_or_password, layout: "admin_layout"
elsif @user.update(email: new_email)
EventLog.record_email_change(@user, current_email, new_email)
UserMailer.email_changed_notification(@user).deliver_later
redirect_to root_path, notice: "An email has been sent to #{new_email}. Follow the link in the email to update your address."
else
render :edit_email_or_password, layout: "admin_layout"
end
end

def update_password
if @user.update_with_password(password_params)
EventLog.record_event(@user, EventLog::SUCCESSFUL_PASSWORD_CHANGE, ip_address: user_ip_address)
flash[:notice] = t(:updated, scope: "devise.passwords")
bypass_sign_in(@user)
redirect_to root_path
else
EventLog.record_event(@user, EventLog::UNSUCCESSFUL_PASSWORD_CHANGE, ip_address: user_ip_address)
render :edit_email_or_password, layout: "admin_layout"
end
end

def reset_two_step_verification
@user.reset_2sv!(current_user)
UserMailer.two_step_reset(@user).deliver_later
Expand All @@ -132,6 +99,8 @@ def require_2sv; end

def load_and_authorize_user
@user = current_user.normal? ? current_user : User.find(params[:id])
redirect_to(account_path) and return if current_user == @user && action_name == "edit"

authorize @user
end

Expand Down Expand Up @@ -180,14 +149,6 @@ def permitted_user_params
@permitted_user_params ||= params.require(:user).permit(:user, :name, :email, :organisation_id, :require_2sv, :role, :skip_update_user_permissions, supported_permission_ids: []).to_h
end

def password_params
params.require(:user).permit(
:current_password,
:password,
:password_confirmation,
)
end

def filter_params
params.permit(
:filter, :page, :format, :"option-select-filter",
Expand Down
22 changes: 22 additions & 0 deletions app/helpers/account_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module AccountHelper
def two_step_verification_page_title
if current_user.has_2sv?
"Change your 2-step verification phone"
else
"Set up 2-step verification"
end
end

def role_organisation_page_title
if policy(%i[account role_organisations]).update_role? &&
policy(%i[account role_organisations]).update_organisation?
"Change your role or organisation"
else
"View your role and organisation"
end
end

def current_user_organisation_name
current_user.organisation&.name_with_abbreviation || "No organisation"
end
end
6 changes: 6 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ def postpone_email_change?
end
end

def cancel_email_change!
self.unconfirmed_email = nil
self.confirmation_token = nil
save!(validate: false)
end

def invited_but_not_yet_accepted?
invitation_sent_at.present? && invitation_accepted_at.nil?
end
Expand Down
5 changes: 5 additions & 0 deletions app/policies/account/activities_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Account::ActivitiesPolicy < BasePolicy
def show?
current_user.present?
end
end
9 changes: 9 additions & 0 deletions app/policies/account/email_passwords_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Account::EmailPasswordsPolicy < BasePolicy
def show?
current_user.present?
end
mike29736 marked this conversation as resolved.
Show resolved Hide resolved
alias_method :update_email?, :show?
alias_method :update_password?, :show?
alias_method :resend_email_change?, :show?
alias_method :cancel_email_change?, :show?
end
6 changes: 6 additions & 0 deletions app/policies/account/manage_permissions_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Account::ManagePermissionsPolicy < BasePolicy
def show?
!current_user.normal?
end
alias_method :update?, :show?
end
13 changes: 13 additions & 0 deletions app/policies/account/role_organisations_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Account::RoleOrganisationsPolicy < BasePolicy
def show?
current_user.present?
end

def update_organisation?
current_user.govuk_admin?
end

def update_role?
current_user.superadmin?
end
end
Loading