Add multi-use group invite links with expiry and auto-approval on email confirmation #83

Merged
thatguygriff merged 1 commits from feature/group-invite-links into main 2026-07-22 13:49:15 +00:00
Owner

Closes #77

Note: branched from fix/invite-email-lock (PR #82) because both touch the registration page/template — merge #82 first and this PR reduces to just the group-link commit.

What & why

From the user demo: an admin option to generate a group invite link to include in a newsletter.

  • Invites admin page gains a Group Invite Link form with a required expiry date (the link stops working at the end of that day). The link is shown once, like personal invite links, and appears in the pending list as "Group link" with its expiry; it can be revoked.
  • The link is multi-use: it is never marked accepted, and anyone with it can register while it is pending and unexpired — in any registration mode, so invite-only studios can run a campaign.
  • The registration form collects an editable email for group links (personal invites keep the locked, prefilled email from #78).
  • Group signups must confirm their email (same hashed-token flow as open registration), but confirming skips admin approval: the account is approved on the spot, the student gets the approved email, and the page shows a "ready to use" notice with a sign-in link. They never appear under Pending Students.

Mechanics

  • us_invites grows kind (personal/group) and expires_at (dbDelta adds the columns via the existing version-bump upgrade path). An explicit expires_at overrides the personal 14-day window in Invite::isExpired().
  • RegistrationStatus::markPending($userId, autoApprove: true) stamps a us_auto_approve user meta; EmailConfirmationHandler::maybeConfirm() approves such accounts immediately after confirming (no admin heads-up email) and redirects with us_confirmed=ready.

Tests

New/updated coverage across InviteTest (expiry precedence, kind defaults), InviteRepositoryTest (persisted columns), RegistrationStatusTest (auto-approve marker lifecycle), EmailConfirmationHandlerTest (auto-approve vs. review-queue confirmation paths), and RegistrationPageTest (group signup creates a pending auto-approve account without login even in invite-only mode; group form shows an editable email).

  • composer test — 377 tests pass; composer lint (PHPStan level 10) and composer cs clean.

Docs updated: docs/features/account-registration.md.

🤖 Generated with Claude Code

Closes #77 > **Note:** branched from `fix/invite-email-lock` (PR #82) because both touch the registration page/template — merge #82 first and this PR reduces to just the group-link commit. ## What & why From the user demo: an admin option to generate a **group invite link** to include in a newsletter. - **Invites admin page** gains a *Group Invite Link* form with a **required expiry date** (the link stops working at the end of that day). The link is shown once, like personal invite links, and appears in the pending list as "Group link" with its expiry; it can be revoked. - The link is **multi-use**: it is never marked accepted, and anyone with it can register while it is pending and unexpired — **in any registration mode**, so invite-only studios can run a campaign. - The registration form collects an **editable email** for group links (personal invites keep the locked, prefilled email from #78). - Group signups must **confirm their email** (same hashed-token flow as open registration), but confirming **skips admin approval**: the account is approved on the spot, the student gets the approved email, and the page shows a "ready to use" notice with a sign-in link. They never appear under Pending Students. ## Mechanics - `us_invites` grows `kind` (`personal`/`group`) and `expires_at` (dbDelta adds the columns via the existing version-bump upgrade path). An explicit `expires_at` overrides the personal 14-day window in `Invite::isExpired()`. - `RegistrationStatus::markPending($userId, autoApprove: true)` stamps a `us_auto_approve` user meta; `EmailConfirmationHandler::maybeConfirm()` approves such accounts immediately after confirming (no admin heads-up email) and redirects with `us_confirmed=ready`. ## Tests New/updated coverage across `InviteTest` (expiry precedence, kind defaults), `InviteRepositoryTest` (persisted columns), `RegistrationStatusTest` (auto-approve marker lifecycle), `EmailConfirmationHandlerTest` (auto-approve vs. review-queue confirmation paths), and `RegistrationPageTest` (group signup creates a pending auto-approve account without login even in invite-only mode; group form shows an editable email). - `composer test` — 377 tests pass; `composer lint` (PHPStan level 10) and `composer cs` clean. Docs updated: `docs/features/account-registration.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
thatguygriff added 1 commit 2026-07-22 13:45:09 +00:00
Add multi-use group invite links with expiry and auto-approval on email confirmation
CI / Tests (PHP 8.2) (pull_request) Successful in 44s
CI / Tests (PHP 8.1) (pull_request) Successful in 46s
CI / No Debug Code (pull_request) Successful in 2s
CI / Coding Standards (pull_request) Successful in 2m46s
CI / PHPStan (pull_request) Successful in 2m51s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m38s
CI / Build Plugin Zip (pull_request) Skipped
356d9f984d
A studio admin can generate a shareable group invite link (e.g. for a
newsletter) from the Invites page, choosing a required expiry date. Anyone
with the link may register while it is valid, in any registration mode: the
form collects their own email, they must confirm it via the usual hashed
token, and confirming approves the account immediately — group signups never
enter the Pending Students queue.

- us_invites grows kind (personal/group) and expires_at; an explicit expiry
  wins over the personal 14-day window. Group links stay pending (multi-use)
  until revoked or expired.
- RegistrationPage: group signups create the account pending with the
  us_auto_approve marker and send the confirmation email; no auto-login.
- EmailConfirmationHandler: auto-approve accounts are approved on
  confirmation, emailed the approved notice, and redirected to a new
  us_confirmed=ready notice with a sign-in link.

Closes #77

Co-Authored-By: Claude Fable 5 <[email protected]>
thatguygriff merged commit 5808defd1a into main 2026-07-22 13:49:15 +00:00
thatguygriff deleted branch feature/group-invite-links 2026-07-22 13:49:15 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Unsupervised/unsupervised-scheduler#83