- RegistrationPage::maybeRedirectToRegistrationPage() (hooked on template_redirect): any front-end request carrying a us_invite token is redirected to the configured registration page (token preserved), unless already there. Covers links shared before a page was selected; no-op when no page is set. - Invites button text: "Send Invite" -> "Generate Invitation Link". - Doc updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.4 KiB
Feature: Account Registration
Overview
People register for a student account through a front-end page, accepting any
signup-scoped policies at that time. Registration is invite-only by default: a
studio admin sends an invite, and the invitee completes signup via a tokenised
link. A settings seam (us_registration_mode) allows switching to open
self-registration with approval later.
Registration Modes
Stored in the us_registration_mode option (default invite):
invite— only a valid, pending invite token grants access to the registration form. (implemented)self_approval— anyone may register; the account is created in a pending state until a studio admin approves it. (reserved for a later iteration)
Data Model — {prefix}us_invites
| Column | Type | Notes |
|---|---|---|
id |
BIGINT UNSIGNED | Primary key |
email |
VARCHAR(191) | Invited email address |
token |
VARCHAR(64) | Opaque token embedded in the registration link |
role |
VARCHAR(32) | Role granted on acceptance (default us_student) |
status |
VARCHAR(20) | pending / accepted / revoked |
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 |
created_at |
DATETIME | Insertion time |
accepted_at |
DATETIME | When accepted; NULL while pending |
Policy Acceptance Scope
Policies declare when they must be accepted via us_policies.acceptance_scope:
signup, booking, or both (see policies.md). The registration form requires
acceptance of every published policy scoped signup or both. Acceptances are
recorded in us_policy_acceptances with registration_type = account and
registration_id = <new user ID>.
Flow (invite mode)
- Studio admin opens Invites (
manage_students) and invites an email; an invite row is created with a token and a registration link. - The invitee opens
[us_student_register]with the token (?us_invite=<token>). - The form pre-fills the email and collects a display name and password, and renders the signup-scoped published policies, each with a required acceptance checkbox.
- On submit, the token is re-validated; a
us_studentuser is created, the policy acceptances are recorded (accounttype), the invite is markedaccepted, and the user is logged in.
Admin Interface
Invites in wp-admin (manage_students, studio admin only):
- Select the registration page (the page hosting
[us_student_register]), stored in theus_registration_page_idoption; invitation links point there (falling back to the home page if unset) - Invite an email (creates a pending invite + link)
- List pending invites; revoke an invite
Frontend Shortcode
[us_student_register]— the registration page. Shows the form for a valid pending invite; otherwise shows an "by invitation only" message (ininvitemode).
Token Redirect
A template_redirect handler (RegistrationPage::maybeRedirectToRegistrationPage())
sends any front-end request carrying a us_invite token to the configured
registration page (preserving the token), unless it is already on that page. This
covers invitation links generated/shared before a registration page was selected.
No-op when no registration page is set.
Capabilities
manage_students— manage invites (studio admin; administrators inherit it via theuser_has_capfilter). Added toRoleManager::STUDIO_ADMIN_CAPS.
Implementation
- Models:
Unsupervised\Schedular\Auth\Invite - Repository:
Unsupervised\Schedular\Auth\InviteRepository - Admin controller:
Unsupervised\Schedular\Auth\RegistrationController - Frontend:
Unsupervised\Schedular\Auth\RegistrationPage - Reuses
Policy\PolicyRepository,Policy\PolicyVersionRepository,Policy\AcceptanceRepository - Schema:
us_invites;us_policies.acceptance_scope
Tests
tests/Unit/Auth/InviteTest.phptests/Unit/Auth/InviteRepositoryTest.php