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

Account page using design system #2377

merged 35 commits into from
Oct 3, 2023

Conversation

mike29736
Copy link
Contributor

@mike29736 mike29736 commented Sep 26, 2023

https://trello.com/c/CTftWKa2/259-update-the-own-account-page-to-use-the-design-system

What

This pull request introduces the new Account page at /account. It includes 4 or 5 cards (depending on user role) that link to various account-related "sub-pages".

Summary (in commit-order)

  • Move "Change your email or password" page from /users to /account
  • Introduce the new Account page and make "Change your email or password" its first sub-page
  • Build a temporary "Manage permissions" page and make it the second Account sub-page
  • Move "2SV setup" page from /users to /account and make that an Account sub-page, too
  • Build "Role and organisation" Account sub-page (the first one that wasn't copy-pasted or otherwise relocated)
  • Build "Your account access log" Account sub-page
  • Prevent users from editing their details through /users/<id>/edit and instead redirecting them /account

Route changes

  • Moves /users/<id>/edit_email_or_password to /account/email_password
  • Moves /users/<id>/update_email to /account/email_password/update_email
  • Moves /users/<id>/update_password to /account/email_password/update_password
  • Moves /users/two_step_verification to /account/two_step_verification
  • Copies /users/<id>/resend_email_change to /account/email_password/resend_email_change
  • Copies /users/<id>/cancel_email_change to /account/email_passwords/cancel_email_change
  • Copies /users/<id>/event_logs to /account/activity
  • Adds /account/manage_permissions
  • Adds /account/role_organisation, /account/role_organisation/update_organisation and /account/role_organisation/update_role

Things I haven't done:

  1. swapped the "2SV setup" link for a Users#reset_two_step_verification-like action (or probably more possible, for a link to a new page dedicated to that action), as Joseph suggested when we spoke earlier in the week, but I have let them know
  2. improved existing content or probably even maintained the level it was at -- see: headings on "Change your email or password", breadcrumb names, the cards on the Account page that have no description

Account page (view for a GOV.UK Admin who doesn't have 2SV setup yet)

Screenshot from 2023-09-29 13-40-31

Account page (view for a normal user who already has 2SV setup)

Screenshot from 2023-09-29 14-31-48

Breadcrumbs

Screenshot from 2023-09-29 14-26-57

Manage permissions page (view for a GOV.UK Admin)

Screenshot from 2023-09-29 13-42-10

Manage permissions page (view for a publishing manager)

Screenshot from 2023-09-29 13-43-12

Role and organisation page (view for a GOV.UK Admin)

Screenshot from 2023-09-29 13-41-33

Role and organisation page (view for a user who isn't a GOV.UK Admin)

Screenshot from 2023-09-29 14-27-50

@chrisroos chrisroos self-assigned this Sep 27, 2023
Copy link
Contributor

@chrisroos chrisroos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks good to me, @mike29736!

I'm not approving it yet because I know you're making other changes.

app/controllers/users_controller.rb Show resolved Hide resolved
app/models/user.rb Outdated Show resolved Hide resolved
app/policies/user_policy.rb Show resolved Hide resolved
config/routes.rb Show resolved Hide resolved
config/routes.rb Show resolved Hide resolved
app/controllers/account/email_passwords_controller.rb Outdated Show resolved Hide resolved
app/views/accounts/show.html.erb Outdated Show resolved Hide resolved
@mike29736 mike29736 force-pushed the account-page-design-system branch 2 times, most recently from cfbe5e3 to e5d4d39 Compare September 29, 2023 16:37
@chrisroos chrisroos force-pushed the account-page-design-system branch 4 times, most recently from c0fe369 to b7566ea Compare October 3, 2023 13:28
This partial was being shared between two pages that I want to decouple.

In the version inlined into `Users#edit_email_or_password`, I've swapped
references to `@user` for `current_user`, because in that view a user
can only ever change their own email and password.
Adding some IDs to make the anchor links work
I'm planning on moving this view to another controller. I don't believe
we're currently aiming to localise Signon so it seems cleaner to just
remove locales entries instead of updating them
I kept reading these aliases of `#edit?` as aliases of
`#edit_email_or_password?`, purely based on their location. Maybe it's
just me!
We're making a new Account page. The new page will link to a handful of
sub-pages that each handle a specific account-related task.

This existing page will be used for changing your email address or
password, so I've moved it into the /account namespace to hopefully make
the user journey feel more cohesive.
The ("Change your email or password") page that uses this endpoint has
already moved to the /account namespace because it's becoming a sub-page
of the new Account page.

I'm undecided on the naming/RESTful design of this resource, so I'm
waiting to take some cues from the upcoming design review in this area.
For the time being I'm keeping it as I found it, but moving it into the
same controller as the page that uses it.
The ("Change your email or password") page that uses this endpoint has
already moved to the /account namespace because it's becoming a sub-page
of the new Account page.

I'm undecided on the naming/RESTful design of this resource, so I'm
waiting to take some cues from the upcoming design review in this area.
For the time being I'm keeping it as I found it, but moving it into the
same controller as the page that uses it.
Until now, Users#resend_email_change was used in two distinct scenarios:

1. Admins performing the action for other users' accounts
2. Users (of all roles) performing the action for their own account

It seems as though the `if @user.normal?` conditional was actually
breaking this distinction: in the case of admin users in scenario 2,
they'd only ever see the flash notice intended for scenario 1.

Scenario 2 is now exclusively performed from the "Change your email or
password" page. That page has already moved to the /account namespace
because it's becoming a sub-page of the new Account page. That page now
has its own dedicated `#resend_email_change` endpoint.

Scenario 1 is still performed from Users#edit.

Similarly to the approach with the actions that I've just
lifted-and-shifted from UsersController to
Account::EmailPasswordsController, for the time being I'm keeping the
naming/RESTful design as I found it and planning to rethink that after
the upcoming design review.
Until now, Users#cancel_email_change was used in two distinct scenarios:

1. Admins performing the action for other users' accounts
2. Users (of all roles) performing the action for their own account

Scenario 2 is now exclusively performed from the "Change your email or
password" page. That page has already moved to the /account namespace
because it's becoming a sub-page of the new Account page.

(Scenario 1 is still performed from Users#edit.)

Similarly to the approach with the actions that I've just
lifted-and-shifted from UsersController to
Account::EmailPasswordsController, for the time being I'm keeping the
naming/RESTful design as I found it and planning to rethink that after
the upcoming design review.

I'm struggling to fully understand the UserPolicy (!) but I think it was
safe to remove the remaining references to `allow_self_only`, since
Users#cancel_email_change was the last UsersController action left that
was used in the ways described by both of the scenarios listed above ^
We were only doing this for one of the actions in this controller, which
was resulting in an inconsistent experience for users.

Since there are soon going to be multiple routes into the "Change your
email or password" page (i.e. the page that uses this endpoint), it
might make sense to redirect back to the page that the user visited
*before* that one.  That's not what `redirect_back_or_to` was doing in
this case, though, it was redirecting back to the "Change your email or
password" page itself. Either way, it should be consistent.
I've included tests to confirm that this is working (most useful for
`#update_email` where we've switched from using `new_email` to using
`current_user.unconfirmed_email`)
That "sub-page" is the "Change your email or password" page, which is
linked to from a card component.

I'm planning to add 4 more cards to this page in later commits. Like
this first one, they'll link to a standalone sub-page each allowing
users to make changes to a different aspect of their account.

In this commit I've also removed an integration test instead of updating
it to reflect my changes, because the important stuff to cover is now
covered by the AccountTest.
This "Edit your account" title might need a rethink, but it's consistent
with the pre-existing page title and heading
Again, I've taken the breadcrumb name from the page's title/heading.

I'm no breadcrumb theorist... we also link to some of these pages directly
from the dashboard. It's OK for breadcrumbs to not reflect the actual
route that the user's taken, right?
Instead of redirecting to the Dashboard, Account page-related actions
now redirect to the Account page on success.

The page that these actions are performed from can be accessed from
either the Dashboard or the Account page, but:

1. (I think) we can't tell which route the user took to get here
2. the Account page is now their canonical home

I can't say I really know where these actions would be best redirecting
back to in terms of the user experience. How they fit with a typical
user's expectations might depend on the specific action they're
performing, too.
This is going to be linked to from the new Account page (for users who
are allowed to changing their own permissions).

There's an entire new permissions management area being developed as we
speak, so it doesn't make sense to put a lot of additional effort into
this version of it.

As a working placeholder, I've copied the permissions management section
of `Users#edit` and I've tried to keep the changes to a minimum.

Some things just didn't make sense in the new (current_user's account)
context. For example, I've tried to remove confusing references to the
user that's having their permissions changed -- in this case that's just
the current_user, changing their own permissions.
mike29736 and others added 14 commits October 3, 2023 15:04
As with the other Account sub-page's endpoints, I'm not 100% sure on the
ideal place to redirect to but the Account page now makes more sense
than the Dashboard
I'm planning on moving the parent :two_step_verification resource and
want to make small, incremental changes in case we need to pinpoint the
introduction of anything unexpected!

Because the `path` and `controller` are explicitly set on this resource
declaration, I think the only side effect this change could have caused
is to the naming of the Rails-generated URL helper methods (e.g.
`two_step_verification_session_path`). I've prevented that from
happening by prefixing the resource name ("two_step_verification_" +
"session").
I'm planning to make this page another sub-page of the new Account page.

For consistency with the Account page and the other Account sub-pages,
I've changed this page's URL to live under /account instead of /users.

Since this page is already only ever used by the current_user to
configure their own account and since the controller already lives in
the fairly neutral `Devise` namespace, it's only the URL that needs
changing to make this an "account" page instead of a "user" one.

And since the affected part of the URL isn't factored into its
Rails-generated URL helper method names, no redirects or links need
updating to complete this change, either.
I'm planning to make the 2SV setup page an Account sub-page. Without any
better ideas, I'd like the wording of the link from the Account page to
be consistent with the page's own existing title and heading.

The wording of the link on the Dashboard and the (title and heading of
the) 2SV page weren't exactly identical before this change, but the
difference seemed arbitrary enough not to worry about.
Give the link a different name depending on whether the user has 2SV
setup already or not
Consistent with the other Account sub-pages, instead of redirecting to
the Dashboard, redirect to the Account page on success.
This provides some functionality that was lost in the switch from
Users#edit to the new Account page.

For Admin and Superadmin users it allows making changes, but for users
with other roles it's read-only.

Since this is another Account sub-page and another mixed bag of a page,
for consistency I've mostly followed the approaches taken by the "Change
your email or password" page.

---

I've let one of the new helper methods be tested through the integration
test only, because I didn't manage to figure out the correct test setup
required for a helper method that's calling a Pundit method.
This provides another bit of functionality that was lost in the switch
from Users#edit to the new Account page. It's pretty much identical to
the Users#event_logs page except for living under /account
This matches the behaviour of the users edit page, where only Super
Admin users can update their and other users' roles (implemented in
`UserPolicy#assign_role?`[1]).

[1]: https://github.com/alphagov/signon/blob/1faf579e720605006b693ad6ca56d6aa29fe2852/app/policies/user_policy.rb#L56
So that users don't have two different ways of editing their own details
(account page and users edit page).

I've implemented this redirect in `#load_and_authorize_user` (instead of
in the action itself) because in a future commit I want to update the
`UserPolicy` to prevent users editing their own accounts through this
controller.
@chrisroos chrisroos force-pushed the account-page-design-system branch 2 times, most recently from af342f0 to a743532 Compare October 3, 2023 14:32
Users should edit their own details using their account page
functionality. This commit ensures that no one can continue using the
/users pages to edit their own account.

In the UserPolicy test for superadmins and admins, I have to skip the
`create` action because these roles should continue to be able to create
new users.

This includes a fix for a bug in the _form_fields partial. The partial
was previously checking whether the signed in user can mandate_2sv for
themselves instead of checking whether the signed in user can
mandate_2sv for the user they're editing. The change to UserPolicy in
this commit highlighted the bug because users can no longer edit their
details (including mandate_2sv) through the users controller.

I've had to update two tests in users_controller_test so that we're
mimicking a user editing another user, instead of the user editing
themselves.
We're already using the `policy` helper method elsewhere so let's use
that consistently. This also avoids us having to pass the `current_user`
in.
@chrisroos chrisroos force-pushed the account-page-design-system branch from a743532 to 22c3626 Compare October 3, 2023 14:38
Copy link
Contributor

@chrisroos chrisroos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks good to me, @mike29736!

I've added a couple of small commits to the branch:

  • Ensure only superadmins can edit their role
  • Redirect users to /account if they attempt to edit their own account using /users/<id>/edit

@chrisroos chrisroos merged commit 621d729 into main Oct 3, 2023
6 checks passed
@chrisroos chrisroos deleted the account-page-design-system branch October 3, 2023 15:21
floehopper added a commit that referenced this pull request Nov 9, 2023
It's a bit hard to follow the git history of this controller, because it
seems to have begun its life as a non-admin controller with actions
allowing users to change their own user, but then in this commit [1] a
bunch of functionality from an admin controller was merged into it.

When we moved the users index page to use the Design System, we removed
some actions from that page [2,3].

More recently we've split out a lot (all?) of the non-admin
functionality into controllers under the `Account` namespace [4].

I'm pretty sure the redirects to `root_path` date back to a time when
the action was called in the context of a user updating their own user.
However, these three actions (`unlock_access`, `resend_email_change` &
`cancel_email_change`) are now only every called in the context of the
page rendered by `UsersController#edit`, so it doesn't make any sense to
me to redirect to the `root_path`. Instead I've changed them to redirect
to the `users_path` which seems consistent with the `update` action.

The redirects using `redirect_back_or_to` seem to relate to a time when
the action was called in multiple contexts: either non-admin vs admin;
or "user index" page vs "edit user" page. The idea is to redirect back
to the page the user came from so the the user interaction makes sense
in both contexts. Note that the path passed to this
`redirect_back_or_to` method is only a fallback if the previous page
cannot be determined.

I've tried to standardize on using the "users index" page (i.e.
`users_path`) as the success path and the "edit user" page (i.e.
`edit_user_path`) as the failure path (i.e. the page where the form
errors are typically displayed). This feels like it gives a better user
experience and makes the code less suprising.

[1]: b730700
[2]: 62eb2f6
[3]: 2197050
[4]: #2377
floehopper added a commit that referenced this pull request Nov 9, 2023
It's a bit hard to follow the git history of this controller, because it
seems to have begun its life as a non-admin controller with actions
allowing users to change their own user, but then in this commit [1] a
bunch of functionality from an admin controller was merged into it.

When we moved the users index page to use the Design System, we removed
some actions from that page [2,3].

More recently we've split out a lot (all?) of the non-admin
functionality into controllers under the `Account` namespace [4].

I'm pretty sure the redirects to `root_path` date back to a time when
the action was called in the context of a user updating their own user.
However, these three actions (`unlock_access`, `resend_email_change` &
`cancel_email_change`) are now only every called in the context of the
page rendered by `UsersController#edit`, so it doesn't make any sense to
me to redirect to the `root_path`. Instead I've changed them to redirect
to the `users_path` which seems consistent with the `update` action.

The redirects using `redirect_back_or_to` seem to relate to a time when
the action was called in multiple contexts: either non-admin vs admin;
or "user index" page vs "edit user" page. The idea is to redirect back
to the page the user came from so the the user interaction makes sense
in both contexts. Note that the path passed to this
`redirect_back_or_to` method is only a fallback if the previous page
cannot be determined.

I've tried to standardize on using the "users index" page (i.e.
`users_path`) as the success path and the "edit user" page (i.e.
`edit_user_path`) as the failure path (i.e. the page where the form
errors are typically displayed). This feels like it gives a better user
experience and makes the code less suprising.

[1]: b730700
[2]: 62eb2f6
[3]: 2197050
[4]: #2377
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants