Let HR record their own absence - #47
Merged
Merged
Conversation
An HR member could not pick themselves in "Record absence", so they could not record their own sick leave at all. Not a permission problem — the server has always allowed it. create() defaults employeeUid to the actor, onBehalf is false for yourself, and both update() and cancel() carry explicit branches for "HR editing their own HR-recorded leave" (§5.6), which were unreachable for a record HR could never create. The picker was the blocker. It calls the app's employee search, which wraps core's collaborator search — and that deliberately drops the searching user from its own results, because it answers "who can I share with" and nobody shares with themselves. This picker asks "whose absence is this?", where you are a valid answer. The dialog then refuses to submit until an employee is chosen, and the only other route, "New request", offers just the self-requestable types, which sick leave deliberately is not. So there was no way through. The search now adds the signed-in user when they match what was typed, listed first because somebody typing their own name has matched it exactly. Guests are still excluded, their own account included. This one result is deliberately not gated on user-enumeration settings: those exist to stop people discovering colleagues, and returning you to yourself discloses nothing you do not know. Two of the five new tests fail without the change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An HR member could not pick themselves in Record absence, so they could not record their own sick leave at all.
Not a permission problem
The server has always allowed this.
RequestService::create()defaultsemployeeUidto the actor when none is given, soonBehalfisfalsefor yourself — a supported path. More tellingly, bothupdate()andcancel()carry explicit branches for "HR editing their own HR-recorded leave":Those branches were unreachable for a record HR could never create in the first place.
The picker was the blocker
/api/employees/searchwraps core's collaborator search, which deliberately removes the searching user from its own results:That rule is right for what it was built for — "who can I share with", and nobody shares with themselves. This picker asks a different question: "whose absence is this?", where you are a perfectly valid answer.
And there was no way around it.
canSubmit()refuses until an employee is chosen:while the only other route — New request — offers just
requestableLeaveTypes(enabled && employeeRequestable), which excludes sick leave by design (§5.6). So for exactly the types Record-absence exists for, HR had no route at all.The fix
The search now includes the signed-in user when they match what was typed, listed first — somebody typing their own name has matched it exactly and should not be pushed below looser matches.
Guests are still excluded, their own account included: a guest holds no entitlement and takes no leave whoever is doing the searching (§2.2).
This one result is deliberately not gated on the admin's user-enumeration settings. Those exist to stop people discovering colleagues they have no business seeing; returning you to yourself discloses nothing you do not already know. Every other result stays gated exactly as before.
I did not make the dialog default to you when nothing is typed — its main use is recording other people's sick leave, and a self-default there invites mis-filing.
Testing
171 tests, 471 assertions, 0 failures (5 new, in a new
EmployeeControllerTest). Two of the five fail without the change. The other three pin the rules that must not regress: a non-matching self stays out, a guest self is never offered, and self is never listed twice should core ever stop filtering it.No frontend change — the picker already renders whatever the endpoint returns — so there is no asset rebuild in this PR.
🤖 Generated with Claude Code