self::get_restriction_message() ), 403 ); } return; } if ( self::is_setup_page_request() ) { return; } wp_safe_redirect( self::get_setup_url() ); exit; } /** * Check whether a restricted user may run an AJAX action. * * Allows the Heartbeat API (keeps the session alive) and passkey registration, * which is a way to enroll. * * @param string $action AJAX action name. * @return bool True when allowed. */ public static function is_allowed_ajax_action( string $action ): bool { return in_array( $action, array( 'heartbeat', 'brain2fa_passkey_register_options', 'brain2fa_passkey_register_verify' ), true ); } /** * Send users who must enroll from front-end pages to the setup page. * * @return void */ public static function restrict_front_end(): void { if ( ! self::current_user_must_enroll() ) { return; } wp_safe_redirect( self::get_setup_url() ); exit; } /** * Refuse cookie-authenticated REST requests from users who must enroll. * * @param WP_Error|null|true $result Result of earlier authentication checks. * @return WP_Error|null|true Unchanged result, or an error for restricted users. */ public static function restrict_rest( $result ) { if ( ! empty( $result ) || ! self::current_user_must_enroll() ) { return $result; } return new WP_Error( 'brain2fa_enrollment_required', self::get_restriction_message(), array( 'status' => 403 ) ); } /** * Let WooCommerce customers open the setup page, which WooCommerce otherwise blocks. * * @param bool $prevent_access Whether WooCommerce will redirect the user away from wp-admin. * @return bool False on the setup page, otherwise unchanged. */ public static function allow_setup_page_for_woocommerce( $prevent_access ) { return self::is_setup_page_request() ? false : $prevent_access; } /** * Show 2FA status and a setup link on the WooCommerce My Account dashboard. * * @return void */ public static function render_my_account_status(): void { if ( ! Utils::is_2fa_enabled_sitewide() || ! is_user_logged_in() ) { return; } $user = wp_get_current_user(); if ( Utils::is_2fa_enabled_for_user( $user->ID ) ) { $message = __( 'Two-factor authentication is active for your account.', 'brain-2fa' ); $link = __( 'Manage two-factor authentication', 'brain-2fa' ); } elseif ( Utils::is_2fa_required_for_user( $user ) ) { $expires_at = Utils::get_grace_period_expiry( $user ); $days = max( 1, (int) ceil( ( $expires_at - time() ) / DAY_IN_SECONDS ) ); $message = sprintf( /* translators: %d: number of days left to set up two-factor authentication */ _n( 'Your account requires two-factor authentication. You have %d day left to set it up.', 'Your account requires two-factor authentication. You have %d days left to set it up.', $days, 'brain-2fa' ), $days ); $link = __( 'Set up two-factor authentication', 'brain-2fa' ); } else { $message = __( 'Protect your account with two-factor authentication.', 'brain-2fa' ); $link = __( 'Set up two-factor authentication', 'brain-2fa' ); } printf( '
%1$s %3$s
', esc_html( $message ), esc_url( self::get_setup_url() ), esc_html( $link ) ); } /** * Get the message shown to users who must enroll. * * @return string Translated message. */ public static function get_restriction_message(): string { return __( 'Your account must use two-factor authentication. Set it up to continue using this site.', 'brain-2fa' ); } }