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.
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)
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]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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
Payment\StudioSettings) — enabling mirrors WordPress'sown membership options (
users_can_register=1,default_role=us_student) andsnapshots their prior values so disabling restores them exactly rather than
clobbering the site's settings.
[us_student_register]page (so required signuppolicies are still accepted). WordPress's native registration form is blocked
while open mode is on —
login_initredirect (catches GET and POST beforeprocessing),
registration_errorsfail-safe, andregister_url— so it can'tbe used to bypass policy acceptance.
(
Auth\EmailConfirmationHandler,Auth\RegistrationStatus).Auth\RegistrationLoginGate): unconfirmed email →login blocked; confirmed-but-unapproved → can log in but
book_lessoniswithheld and the booking page shows an "awaiting approval" screen.
(
Auth\RegistrationApprovalController); reject hard-deletes the account so theemail is freed to re-apply.
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 passcomposer lint— PHPStan level 10 cleancomposer cs— PHPCS cleanDocs updated:
docs/features/account-registration.mdandREADME.md.🤖 Generated with Claude Code