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
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
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]>
This commit is contained in:
@@ -9,6 +9,12 @@ anyone may sign up, confirm their email, and then be approved by a studio admin
|
||||
before the account can be used. Both modes coexist — invites keep working when
|
||||
open registration is on.
|
||||
|
||||
A studio admin can also generate a **group invite link** — a multi-use, tokenised
|
||||
link with an explicit expiry date (e.g. for a newsletter). Anyone with the link
|
||||
may register while it is valid, regardless of the registration mode: they supply
|
||||
their own email, must confirm it, and are then **approved automatically** —
|
||||
group-link signups never enter the Pending Students queue.
|
||||
|
||||
## Registration Modes
|
||||
Stored in the `us_registration_mode` option (default `invite`), toggled from
|
||||
**Studio Settings → Registration**:
|
||||
@@ -59,14 +65,16 @@ confirmation token's SHA-256 hash is stored; the token expires after 48h
|
||||
| Column | Type | Notes |
|
||||
|--------------------|------------------|--------------------------------------------------------|
|
||||
| `id` | BIGINT UNSIGNED | Primary key |
|
||||
| `email` | VARCHAR(191) | Invited email address |
|
||||
| `email` | VARCHAR(191) | Invited email address; empty string for group links |
|
||||
| `token` | VARCHAR(64) | SHA-256 hash of the token embedded in the registration link (raw token is never stored) |
|
||||
| `role` | VARCHAR(32) | Role granted on acceptance (default `us_student`) |
|
||||
| `status` | VARCHAR(20) | `pending` / `accepted` / `revoked` |
|
||||
| `kind` | VARCHAR(10) | `personal` (single-use, per email) or `group` (multi-use link) |
|
||||
| `status` | VARCHAR(20) | `pending` / `accepted` / `revoked` (group links stay `pending` until revoked/expired) |
|
||||
| `invited_by` | BIGINT UNSIGNED | WordPress user ID of the studio admin who invited |
|
||||
| `accepted_user_id` | BIGINT UNSIGNED | The created user's ID once accepted; NULL while pending |
|
||||
| `accepted_user_id` | BIGINT UNSIGNED | The created user's ID once accepted; NULL while pending / for group links |
|
||||
| `created_at` | DATETIME | Insertion time |
|
||||
| `accepted_at` | DATETIME | When accepted; NULL while pending |
|
||||
| `accepted_at` | DATETIME | When accepted; NULL while pending / for group links |
|
||||
| `expires_at` | DATETIME | Explicit expiry (end of the chosen day); set on every group link, NULL for personal invites (which expire 14 days after creation) |
|
||||
|
||||
## Policy Acceptance Scope
|
||||
Policies declare **when** they must be accepted via `us_policies.acceptance_scope`:
|
||||
@@ -88,11 +96,19 @@ recorded in `us_policy_acceptances` with `registration_type = account` and
|
||||
4. The applicant opens the emailed `?us_confirm=<token>` link → email confirmed, studio admins notified.
|
||||
5. Studio admin approves under **Students → Pending Students** → pending flags cleared, student emailed; they can now log in and book. Rejection deletes the account.
|
||||
|
||||
## Flow (group invite link)
|
||||
1. Studio admin opens **Invites** and generates a **group link**, choosing the expiry date (required; the link stops working at the end of that day). The link is shown **once**, like personal invite links.
|
||||
2. Anyone opens the link while it is pending and unexpired — in **any** registration mode — and the form collects an **editable email**, display name, password, and the signup policies.
|
||||
3. On submit the account is created pending with the auto-approve marker (`RegistrationStatus::markPending($userId, autoApprove: true)`, meta `us_auto_approve`) and a confirmation email is sent. The invite row is **not** marked accepted — the link remains usable by others.
|
||||
4. Opening the `?us_confirm=<token>` link confirms the email and **approves the account immediately** (`EmailConfirmationHandler`): no admin heads-up, no Pending Students entry; the student gets the "approved" email and the page shows a "ready to use" notice (`?us_confirmed=ready`) with a sign-in link.
|
||||
5. The link can be revoked at any time from the Invites page.
|
||||
|
||||
## Admin Interface
|
||||
**Invites** in wp-admin (`manage_students`, studio admin only):
|
||||
- Select the **registration page** (the page hosting `[us_student_register]`), stored in the `us_registration_page_id` option; invitation links point there (falling back to the home page if unset)
|
||||
- Invite an email (creates a pending invite; the link is displayed once, at creation only)
|
||||
- List pending invites (email + invited date); revoke an invite
|
||||
- Generate a **group invite link** with a required expiry date (link displayed once)
|
||||
- List pending invites (email or "Group link", created + expiry dates); revoke an invite
|
||||
|
||||
**Pending Students** — submenu under Students (`manage_students`), only relevant in `self_approval` mode:
|
||||
- "Awaiting approval" (email confirmed) — approve or reject
|
||||
|
||||
Reference in New Issue
Block a user