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
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]>
62 lines
2.1 KiB
PHP
62 lines
2.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Unsupervised\Schedular\Auth;
|
|
|
|
/**
|
|
* Enforces the pending state of self-signup accounts:
|
|
* - an account whose email is not yet confirmed cannot log in at all;
|
|
* - a confirmed-but-unapproved account may log in, but its booking capability
|
|
* is withheld so it only reaches the "awaiting approval" screen.
|
|
*
|
|
* Both checks key solely off the pending user meta, so invite- and
|
|
* admin-created students (which carry none of it) are unaffected.
|
|
*/
|
|
class RegistrationLoginGate {
|
|
|
|
public function register(): void {
|
|
add_filter( 'wp_authenticate_user', [ $this, 'blockUnconfirmed' ], 10, 1 );
|
|
add_filter( 'user_has_cap', [ $this, 'withholdBookingWhilePending' ], 10, 4 );
|
|
}
|
|
|
|
/**
|
|
* Block authentication for a self-signup that has not yet confirmed its
|
|
* email. Runs after password verification.
|
|
*
|
|
* @param \WP_User|\WP_Error $user Authenticating user, or an earlier error.
|
|
* @return \WP_User|\WP_Error
|
|
*/
|
|
public function blockUnconfirmed( $user ) {
|
|
if (
|
|
$user instanceof \WP_User
|
|
&& RegistrationStatus::isAwaitingApproval( (int) $user->ID )
|
|
&& ! RegistrationStatus::emailConfirmed( (int) $user->ID )
|
|
) {
|
|
return new \WP_Error(
|
|
'us_email_unconfirmed',
|
|
esc_html__( 'Please confirm your email address before logging in — check your inbox for the confirmation link.', 'unsupervised-schedular' )
|
|
);
|
|
}
|
|
|
|
return $user;
|
|
}
|
|
|
|
/**
|
|
* Strip the booking capability from any account still awaiting approval, so a
|
|
* confirmed-but-unapproved student cannot book until a studio admin approves.
|
|
*
|
|
* @param array<string, bool> $allcaps All capabilities currently held.
|
|
* @param array<int, string> $caps Required capabilities (unused).
|
|
* @param array<int, mixed> $args Callback args (unused).
|
|
* @param mixed $user The user being checked (a WP_User in practice).
|
|
* @return array<string, bool>
|
|
*/
|
|
public function withholdBookingWhilePending( array $allcaps, array $caps, array $args, mixed $user ): array {
|
|
if ( $user instanceof \WP_User && RegistrationStatus::isAwaitingApproval( (int) $user->ID ) ) {
|
|
unset( $allcaps[ RoleManager::CAP_BOOK_LESSON ] );
|
|
}
|
|
|
|
return $allcaps;
|
|
}
|
|
}
|