SS-851: Stats Module — UserId on Records, Supervisor Flow, and Code Quality #83
SS-851: Stats Module — UserId on Records, Supervisor Flow, and Code Quality #83hrandhawa13 wants to merge 3 commits into
Conversation
| const { data: userInfo } = await getApiAuthUser(); | ||
|
|
||
| authStore.setUserInfo(userInfo.value); | ||
|
|
||
| if (userInfo.value?.isAuthenticated) { | ||
| if (userInfo.value.name) { | ||
| const { data: users } = await getApiUsers({ IdirName: userInfo.value.name }); | ||
| authStore.setCurrentUser(users.value?.[0] ?? null); | ||
| } |
There was a problem hiding this comment.
getApiAuthUser endpoint can return the current user details. We can modify the UserInfo response to return the DB.User.Id, seems like that is what is not being returned from UserInfo. I'm currently working on claimsTransformer so I can add the User Id from Db in claims so we can return that in the UserInfo.
| export type OriginalGetApiUsersParams = { | ||
| Search?: string; | ||
| IsEnabled?: boolean; | ||
| IdirName?: string; |
There was a problem hiding this comment.
We are usually using IdirId instead of IdirName. We probably don't need to query by IdirName Once we implement returning User.Id in UserInfo.
See my other comment about returning DB.User.Id in UserInfo.
| const resolvedUserId = authStore.isSupervisor ? selectedUserId.value : authStore.currentUser?.id; | ||
| if (!resolvedUserId) { | ||
| errors['user'] = authStore.isSupervisor | ||
| ? 'Please select a user to submit hours for.' | ||
| : 'Unable to determine current user. Please refresh and try again.'; | ||
| } | ||
|
|
There was a problem hiding this comment.
Point for discussion: Wondering if we should add a permission, instead of checking role directly. To be consistent and flexible, if we have permissions then if in the future rules change then we do not have to change code, we just assign a permission to a different role.
cc: @BronzBierd
There was a problem hiding this comment.
Yes please stick to only checking permissions.
this way we don't increase permutations checking for role + permisssion combinations. This doesn't scale well and we have terrible examples to scare any developer.
| [Required] | ||
| public string PeriodType { get; set; } = string.Empty; | ||
|
|
||
| public Guid UserId { get; set; } |
There was a problem hiding this comment.
this is a non-null value so, this may be a breaking change if there are pre-existing StatRecord entities in the db.
There was a problem hiding this comment.
alternatively, you can make this nullable public Guid? UserId { get; set; }
| @@ -60,10 +60,27 @@ | |||
| } | |||
|
|
|||
| public async Task<IReadOnlyCollection<StatRecordResponse>> CreateBatchAsync( | |||
There was a problem hiding this comment.
it seems odd that only the batch method would enforce auth in this manner, should CreateAsync and UpdateAsync also enforce this? If so, a shared function would be desirable to avoid code duplication.
| CancellationToken cancellationToken = default | ||
| ) | ||
| { | ||
| var entity = MapToEntity(request); |
There was a problem hiding this comment.
similar issue exists here, were the user id from the request is being trusted and not checked against the logged-in user id.
| .Select(u => u.Id) | ||
| .SingleOrDefaultAsync(cancellationToken); | ||
|
|
||
| if (requests.Any(r => r.UserId != callerId)) |
There was a problem hiding this comment.
just a question, is the user's home location relevant for this? ie. can a user submit stat records for any location?
| selectedLocationId.value = value !== null && value !== undefined ? Number(value) : null; | ||
| if (authStore.isSupervisor) { | ||
| selectedUserId.value = null; | ||
| locationUsers.value = []; |
There was a problem hiding this comment.
should this be added here?
activeLocationId = selectedLocationId.value;
| if (string.IsNullOrWhiteSpace(callerIdirName)) | ||
| throw new UnauthorizedAccessException("Only supervisors can submit records on behalf of another user."); | ||
|
|
||
| var callerId = await db |
There was a problem hiding this comment.
Id be tempted to have a user service handle these user queries, (possibly by a call at the controller level). Otherwise if we have multiple service methods that need to do user checking they are all going to have to duplicate this code.
| var result = await service.CreateBatchAsync( | ||
| requests, | ||
| User.Identity?.Name ?? string.Empty, | ||
| User.IsInRole("Supervisor"), |
There was a problem hiding this comment.
nit: could have an enum for the available roles instead of hardcoded strings.
Pull Request for JIRA Ticket: https://jira.justice.gov.bc.ca/browse/SS-932
Description
Adds UserId to stat records so each record is associated with the employee it belongs to (not just the audit creator). Introduces a supervisor flow that allows supervisors to enter
time on behalf of other users at a selected location. Also exposes roles from the auth endpoint directly, replacing fragile hardcoded claim type URLs on the frontend.
Changes
Data Model
API — Stats
entirely (no unnecessary DB query)
from primary constructor style to property-style init records
API — User Management
Infrastructure
Frontend
fetch responses are discarded via an activeLocationId guard
Type of change
How Has This Been Tested?
Checklist: