Open student registration with email confirmation and admin approval #64

Merged
thatguygriff merged 1 commits from feature/student-self-signup into main 2026-07-18 13:58:00 +00:00
Owner

Closes #63

What & why

Students could previously join by invite only. This adds an optional
self-approval registration mode, toggled from Studio Settings →
Registration
: anyone may sign up, confirm their email, and then be approved by
a studio admin before the account is usable. Invite registration is unchanged and
both modes coexist.

How it works

  • Settings toggle (Payment\StudioSettings) — enabling mirrors WordPress's
    own membership options (users_can_register=1, default_role=us_student) and
    snapshots their prior values so disabling restores them exactly rather than
    clobbering the site's settings.
  • Open signup reuses the [us_student_register] page (so required signup
    policies are still accepted). WordPress's native registration form is blocked
    while open mode is on — login_init redirect (catches GET and POST before
    processing), registration_errors fail-safe, and register_url — so it can't
    be used to bypass policy acceptance.
  • Email confirmation — hashed, 48h-expiry token emailed as a link
    (Auth\EmailConfirmationHandler, Auth\RegistrationStatus).
  • Hybrid pending gate (Auth\RegistrationLoginGate): unconfirmed email →
    login blocked; confirmed-but-unapproved → can log in but book_lesson is
    withheld and the booking page shows an "awaiting approval" screen.
  • Approval UI — Students → Pending Students
    (Auth\RegistrationApprovalController); reject hard-deletes the account so the
    email is freed to re-apply.
  • Account lifecycle lives in user meta — no new tables.

Tests

7 new unit test suites (Brain\Monkey + Mockery) covering the settings
mirror/restore, status transitions + token expiry, both login/capability gates,
the open/invite branching, email confirmation + native-form blocking, approval /
rejection, and the mailer.

  • composer test — 351 tests pass
  • composer lint — PHPStan level 10 clean
  • composer cs — PHPCS clean

No local WordPress runtime exists in this repo (tests stub WP via Brain\Monkey),
so this was verified via the unit suite + static analysis. Worth a manual smoke
on staging: enable toggle → sign up → confirm email → approve → book.

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

🤖 Generated with Claude Code

Closes #63 ## What & why Students could previously join **by invite only**. This adds an optional **self-approval** registration mode, toggled from **Studio Settings → Registration**: anyone may sign up, confirm their email, and then be approved by a studio admin before the account is usable. Invite registration is unchanged and both modes coexist. ## How it works - **Settings toggle** (`Payment\StudioSettings`) — enabling mirrors WordPress's own membership options (`users_can_register=1`, `default_role=us_student`) and snapshots their prior values so disabling restores them exactly rather than clobbering the site's settings. - **Open signup** reuses the `[us_student_register]` page (so required signup policies are still accepted). WordPress's native registration form is blocked while open mode is on — `login_init` redirect (catches GET **and** POST before processing), `registration_errors` fail-safe, and `register_url` — so it can't be used to bypass policy acceptance. - **Email confirmation** — hashed, 48h-expiry token emailed as a link (`Auth\EmailConfirmationHandler`, `Auth\RegistrationStatus`). - **Hybrid pending gate** (`Auth\RegistrationLoginGate`): unconfirmed email → login blocked; confirmed-but-unapproved → can log in but `book_lesson` is withheld and the booking page shows an "awaiting approval" screen. - **Approval UI** — Students → Pending Students (`Auth\RegistrationApprovalController`); reject hard-deletes the account so the email is freed to re-apply. - Account lifecycle lives in **user meta** — no new tables. ## Tests 7 new unit test suites (Brain\Monkey + Mockery) covering the settings mirror/restore, status transitions + token expiry, both login/capability gates, the open/invite branching, email confirmation + native-form blocking, approval / rejection, and the mailer. - `composer test` — 351 tests pass - `composer lint` — PHPStan level 10 clean - `composer cs` — PHPCS clean > No local WordPress runtime exists in this repo (tests stub WP via Brain\Monkey), > so this was verified via the unit suite + static analysis. Worth a manual smoke > on staging: enable toggle → sign up → confirm email → approve → book. Docs updated: `docs/features/account-registration.md` and `README.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
thatguygriff added 1 commit 2026-07-18 13:51:08 +00:00
Add open student registration with email confirmation and approval
CI / Tests (PHP 8.1) (pull_request) Successful in 1m18s
CI / Tests (PHP 8.2) (pull_request) Successful in 1m18s
CI / No Debug Code (pull_request) Successful in 2s
CI / PHPStan (pull_request) Successful in 3m20s
CI / Coding Standards (pull_request) Successful in 3m25s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m33s
CI / Build Plugin Zip (pull_request) Skipped
7370755951
Students could previously join by invite only. Add an optional
self-approval mode, toggled from Studio Settings → Registration: anyone
may sign up on the existing [us_student_register] page, confirm their
email via a tokenised link, and then be approved by a studio admin
before the account is usable.

- Enabling the toggle mirrors WordPress's own membership settings
  (users_can_register + default_role = us_student) and snapshots their
  previous values so disabling restores them.
- WordPress's native registration form is blocked while open
  registration is on (login_init redirect + registration_errors
  fail-safe + register_url) so it cannot bypass signup policy acceptance.
- Pending accounts: unconfirmed email cannot log in; confirmed but
  unapproved can log in but the booking capability is withheld and the
  booking page shows an "awaiting approval" screen.
- Approve/reject from Students → Pending Students; reject hard-deletes
  the account so the email is freed to re-apply.
- Invite registration is unchanged; both modes coexist.

Account lifecycle lives in user meta (RegistrationStatus); no new tables.

Closes #63

Co-Authored-By: Claude Opus 4.8 <[email protected]>
thatguygriff merged commit e4af0c327c into main 2026-07-18 13:58:00 +00:00
thatguygriff deleted branch feature/student-self-signup 2026-07-18 13:58:00 +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#64