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

Locking down user group info #116

Open
wants to merge 16 commits into
base: main
Choose a base branch
from

Conversation

burkkyy
Copy link
Collaborator

@burkkyy burkkyy commented Oct 14, 2024

resolves #106

Implementation

  • If current user is a System admin then that user gets a user edit page with all 8 fields, otherwise servered a different form that is more restrictive
  • At the user api endpoint, the user controller uses the user policy to check if the user if an admin.

Screenshots

idp111
figure 1 profile/edit as a regular user

admin
figure 2 profile/edit as a system_admin

Testing Instructions

  1. Run the test suite via dev test (or dev test_api)
  2. Boot the app via dev up
  3. Log in to the app at http://localhost:8080 (as non system_admin)
  4. Go to http://localhost:8080/profile/edit
  5. Ensure certain fields are locked
  6. Go back to http://localhost:8080/profile/edit as system_admin
  7. Ensure you can now alter certain fields

@burkkyy burkkyy self-assigned this Oct 14, 2024
@burkkyy burkkyy changed the title Issue 106/lock down user group info Locking down user group info Oct 14, 2024
Copy link
Member

@klondikemarlen klondikemarlen left a comment

Choose a reason for hiding this comment

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

Overall looks great! Also good job on the testing instructions!

Only firm request is to switch from disabled to readonly + lock icon, do to readability concerns. See web/src/pages/ProfilePage.vue for an example.

Copy link
Collaborator Author

@burkkyy burkkyy left a comment

Choose a reason for hiding this comment

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

Self reviewed.

Made changes suggested from PR comments.

@burkkyy burkkyy requested a review from klondikemarlen January 6, 2025 21:55
Copy link
Member

@klondikemarlen klondikemarlen left a comment

Choose a reason for hiding this comment

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

While overall this looks good, I suggest breaking the profile edit and user edit forms into two forms based on role, see comments.

In general, I would expect admins to only be able to edit the extra fields when acting through the admin interface, rather than through their profile page.

Comment on lines +92 to +93
:readonly="isNil(groupMembershipAttributes.departmentId)"
:append-inner-icon="isNil(groupMembershipAttributes.departmentId) ? 'mdi-lock' : ''"
Copy link
Member

Choose a reason for hiding this comment

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

So ... this is a case where I would want to use disabled.
Conceptually, the field only activates once you fill the parent.

I see "locking" a field as something you would do when displaying a never editable field (e.g. email) in the middle of a bunch of editable fields (e.g. first name, last name)

Copy link
Member

Choose a reason for hiding this comment

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

My previous request #116 (comment), is a bit confusing in contrast.

In that version, you where showing a field to a user for display purposes, but making it hard for them to read, via disabled, so I recommended the "locked" instead of "disabled" view. As that is easier to ready in a display context.

In this version, the field is only temporarily inaccessible until you fill in parent values; as such, it makes sense to make the field hard to read/easy to ignore, until the parent is filled in. At which point the field becomes "non-disabled" and easy to read, drawing the eye, and encouraging the user to then act on it.

Copy link
Member

Choose a reason for hiding this comment

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

The fact the the UI now shows a different view to the User and Admin makes it possible to make use of this kind of UI (UX?) enhancement.

v-bind="cancelButtonOptions"
text="Cancel"
/>
<!-- TODO: add ability to request update of yukon government directory information during save -->
Copy link
Member

Choose a reason for hiding this comment

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

Interestingly enough, I just built this in WRAP, and I wish I had put it in the "read" view rather than the "edit" view.
https://yg-wrap-uat.azurewebsites.net/profile
image
https://yg-wrap-uat.azurewebsites.net/profile/edit
image

I probably should have put the "Sync with Directory" button where the "Edit" button is, and moved the "Edit" to the bottom right of the "read" view.

Comment on lines +218 to +221
if (!isValid.value) {
snack.notify("Please fill out all required fields", { color: "error" })
return
}
Copy link
Member

Choose a reason for hiding this comment

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

Interesting, I've been using form.value?.validate(), lately, and I'm thinking I just forgot that form v-model was a thing? I'll have to double check, since this version is a lot cleaner!

Comment on lines +78 to +79
readonly
append-inner-icon="mdi-lock"
Copy link
Member

Choose a reason for hiding this comment

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

As these fields are non-editable, do they even belong in an edit form? Maybe they do, like email in this form
image

Or maybe they don't, since the user can read them on the "read" view of the page (I'm assuming there is a read view?)

>
Cancel
</v-btn>
text="Cancel"
Copy link
Member

Choose a reason for hiding this comment

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

Huh. I didn't know this was a thing.

import { required } from "@/utils/validators"

import { GroupMembership } from "@/api/users-api"
Copy link
Member

Choose a reason for hiding this comment

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

Yay!

Comment on lines +27 to +33
<AdminUserEditForm
v-if="isSystemAdmin"
class="mt-10"
:user-id="currentUser.id"
:cancel-button-options="{ to: { name: 'ProfilePage' } }"
@saved="refresh"
/>
Copy link
Member

@klondikemarlen klondikemarlen Feb 21, 2025

Choose a reason for hiding this comment

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

I don't think the profile is the correct place for an Admin edit interface.

I would expect all users to have the same field editability for their profile, and if the admin wants to edit a user's more restricted or complex details, they would go to the user admin interface; even if that user is them.

Comment on lines +34 to +42
const attributes: Path[] = ["email", "firstName", "lastName", "position"]

if (this.user.isSystemAdmin) {
attributes.push({
groupMembershipAttributes: ["departmentId", "divisionId", "branchId", "unitId"],
},
]
})
}

return attributes
Copy link
Member

Choose a reason for hiding this comment

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

Looks good!

Comment on lines +32 to +40
<AdminUserEditForm
v-if="isSystemAdmin"
class="mt-10"
:user-id="user.id"
:cancel-button-options="{ to: { name: 'UsersPage' } }"
@saved="refresh"
/>
<UserEditForm
v-else
Copy link
Member

Choose a reason for hiding this comment

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

This page is already the user admin page, so I'd expect only the edit form here to be the "admin" one.

Only Admins should be able to access the "All Users" page, and only the all user's page grants you access to this UserEditPage.

See web/src/components/base-layout/KebabMenu.vue

<v-list-item
  v-if="isSystemAdmin"
  title="All Users"
  :to="{ name: 'UsersPage' }"
  prepend-icon="mdi-account-group"
/>

You could definitely argue that this should be called the AdminUserEditPage, and I'd would probably agree.
Normally, there might be a "read" view for all users that was publicly accessible, and the "Edit" button would only be shown to admins.

Comment on lines +4 to +6
import usersApi, { RoleTypes, type User, type UserUpdate } from "@/api/users-api"

export { type User, type UserUpdate }
export { RoleTypes, type User, type UserUpdate }
Copy link
Member

Choose a reason for hiding this comment

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

Consider adding type RoleTypes as this will play better with the Typescript + Vitest. (vitest is what we will likely be using for testing, once we do more of that)

Copy link
Member

@klondikemarlen klondikemarlen left a comment

Choose a reason for hiding this comment

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

It's looking better! I've requested some more changes, mostly around aligning UI concepts.

The original ticket description is .... not right; and that's on me. I probably didn't do much research, and just guessed at what needed to be done.

@klondikemarlen
Copy link
Member

It might be worth splitting the ProfileEdit, and UserEdit out into a "read-only" and "edit" version, as seen through the WRAP project.
e.g.

Read view Organization
https://yg-wrap-uat.azurewebsites.net/administration/organizations/1/categories
image

Edit view organization
https://yg-wrap-uat.azurewebsites.net/administration/organizations/1/edit
image

This lets you make the read view be make more readable and the code less complex.
And it can also do the same for the edit view, as you might be able to drop some fields that are read only.

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.

Lock Down User Group Info
2 participants