Repository navigation
Admin → Users: accept an invited user's invitation with a password the administrator sets - #716
Merged
Merged
Conversation
…e administrator sets
An invited local account signed in only once its user had followed the
invitation link and chosen a password, so an administrator who set an
account up for someone without email or a mailbox could not hand it over
ready to use: it stayed invited, or its invitation expired.
POST /admin/users/{id}/invitation/accept with {"password"} now accepts the
invitation on the user's behalf, in one transaction: the password becomes
the account's, the account is no longer invited (status active), and its
invitation, live or expired, is marked accepted, so its link answers as
invalid. It works whether a live invitation waits or not. The password
follows the invitation page's rules (12 characters to 1024 bytes, 400
otherwise); an account that is not an active invited local one (its user
chose a password already, an account of another realm, a service account,
a deactivated account) is refused with 409, and no account is 404. The
change is in the audit trail with the administrator who made it.
Admin → Users → <user> offers Accept invitation on an invited account: a
dialog asks for the password twice, checks it by the invitation page's
rules (now shared with that page), shows the server's refusal, and says
afterwards that the user signs in with the password set. docs/deployment.md
(Inviting users) describes it as the only way an administrator sets
another person's password.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012e6DJbbDh51swmocfFvXPe
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.
Fixes #653
An invited local account (#322) could sign in only after its user followed the invitation link and chose a password. An administrator who set up an account for someone else could not finish the invitation for them, for example on an install without email or for a user without a mailbox. The account stayed invited, or became invitation expired.
The change
POST /admin/users/{id}/invitation/acceptwith{"password": "…"}accepts the invitation on the user's behalf. One transaction (invitation_dao::accept_for_user) does all of this:invitedis cleared, so the status isactive;invited,invitation_expired, and a revoked invitation (no row).invitations::check_password): at least 12 characters and at most 1024 bytes. Otherwise 400 with the reason.… AND invited AND active AND auth_source = 'local' AND kind = 'user').admin changeline records the request. Aforge::auditline also names the account and the administrator who accepted for it.Web UI
invitationPasswordProbleminweb/src/api/auth.ts, which/inviteuses too.Docs
docs/deployment.md→ Inviting users: the intro now says an administrator sets another person's password only this way. A new bullet describes Accept invitation, and the API paragraph lists the endpoint with its 400/409/404.docs/changes/2.2.0/653.feature.md.Tests
crates/server/tests/invitations.rs→an_administrator_accepts_an_invitation_with_a_password_they_set:accepted_atis set, and the old link fails both/auth/invitations/lookupand/auth/invitations/accept(and the password sent there does not sign in);web/src/routes/admin/users/users.test.tsx, two new tests:{password}, dialog closed, notice shown, invitation actions gone, status active);Checks run
cargo test -p forge-server --test invitations: 6 passed (all 5 existing ones plus the new one), against Postgres 18, versitygw and mailpit testcontainers.cargo clippy -p forge-db -p forge-server --lib --test invitations -- -D warningsandcargo fmt --all --check.cargo xtask changelog --checkandcargo xtask docs --check.pnpm run tsc;pnpm run test: 536 passed, 40 files.Notes
.sqlxchange: the new queries use the runtimesqlx::queryAPI, like the rest ofinvitation_dao.form=id. Browsers then submit on Enter in either field. user-event does not simulate that, so the test clicks the button.Generated by Claude Code