'integer', 'description' => __('Custom page for login', 'acemedia-login-block'), 'default' => 0, ]); // Register settings for redirect URLs and 2FA per role $roles = wp_roles()->roles; foreach ($roles as $role => $details) { // Register role-specific redirect URL settings $role_redirect_key = "acemedia_login_block_redirect_{$role}"; register_setting('acemedia_login_block_options_group', $role_redirect_key, [ 'type' => 'string', /* translators: %s: WordPress role name. */ 'description' => sprintf(__('Redirect URL for %s role', 'acemedia-login-block'), $details['name']), 'default' => '', ]); // Register role-specific 2FA settings $role_2fa_key = "acemedia_2fa_enabled_{$role}"; register_setting('acemedia_login_block_options_group', $role_2fa_key, [ 'type' => 'boolean', /* translators: %s: WordPress role name. */ 'description' => sprintf(__('Enable 2FA for %s role', 'acemedia-login-block'), $details['name']), 'default' => false, ]); $role_passkey_passwordless_key = "acemedia_passkey_passwordless_{$role}"; register_setting('acemedia_login_block_options_group', $role_passkey_passwordless_key, [ 'type' => 'boolean', /* translators: %s: WordPress role name. */ 'description' => sprintf(__('Allow passkey passwordless login for %s role', 'acemedia-login-block'), $details['name']), 'default' => false, ]); $role_passkey_2fa_required_key = "acemedia_passkey_2fa_required_{$role}"; register_setting('acemedia_login_block_options_group', $role_passkey_2fa_required_key, [ 'type' => 'boolean', /* translators: %s: WordPress role name. */ 'description' => sprintf(__('Require passkey as 2FA method for %s role', 'acemedia-login-block'), $details['name']), 'default' => false, ]); } register_setting('acemedia_login_block_options_group', 'acemedia_login_lockout_enabled', [ 'type' => 'boolean', 'description' => __('Enable login lockout', 'acemedia-login-block'), 'sanitize_callback' => 'rest_sanitize_boolean', 'default' => true, ]); register_setting('acemedia_login_block_options_group', 'acemedia_login_lockout_max_attempts', [ 'type' => 'integer', 'description' => __('Maximum failed login attempts before lockout', 'acemedia-login-block'), 'sanitize_callback' => 'absint', 'default' => 5, ]); register_setting('acemedia_login_block_options_group', 'acemedia_login_lockout_window_minutes', [ 'type' => 'integer', 'description' => __('Failed login attempt window (minutes)', 'acemedia-login-block'), 'sanitize_callback' => 'absint', 'default' => 15, ]); register_setting('acemedia_login_block_options_group', 'acemedia_login_lockout_duration_minutes', [ 'type' => 'integer', 'description' => __('Lockout duration (minutes)', 'acemedia-login-block'), 'sanitize_callback' => 'absint', 'default' => 30, ]); register_setting('acemedia_login_block_options_group', 'acemedia_login_lockout_ip_max_attempts', [ 'type' => 'integer', 'description' => __('Failed login attempts from one IP address before it is locked', 'acemedia-login-block'), 'sanitize_callback' => 'absint', 'default' => 20, ]); register_setting('acemedia_login_block_options_group', 'acemedia_login_trusted_proxy_header', [ 'type' => 'string', 'description' => __('Trusted proxy header for the client IP', 'acemedia-login-block'), 'sanitize_callback' => function ($value) { return $value === 'auto' ? 'auto' : 'off'; }, 'default' => 'off', ]); register_setting('acemedia_login_block_options_group', 'acemedia_login_lockout_notify', [ 'type' => 'boolean', 'description' => __('Email the site admin when a lockout happens', 'acemedia-login-block'), 'sanitize_callback' => 'rest_sanitize_boolean', 'default' => true, ]); register_setting('acemedia_login_block_options_group', 'acemedia_login_log_retention_days', [ 'type' => 'integer', 'description' => __('Days to keep the login attempt log', 'acemedia-login-block'), 'sanitize_callback' => 'absint', 'default' => 30, ]); register_setting('acemedia_login_block_options_group', 'acemedia_security_alerts_enabled', [ 'type' => 'boolean', 'description' => __('Enable security alert emails', 'acemedia-login-block'), 'sanitize_callback' => 'rest_sanitize_boolean', 'default' => false, ]); register_setting('acemedia_login_block_options_group', 'acemedia_security_alerts_email', [ 'type' => 'string', 'description' => __('Security alert email recipient', 'acemedia-login-block'), 'sanitize_callback' => 'sanitize_email', 'default' => '', ]); // Add the settings page add_options_page( __('Ace Login Block Settings', 'acemedia-login-block'), __('Ace Login Block', 'acemedia-login-block'), 'manage_options', 'acemedia-login-block', [$this, 'render_settings_page'] ); } /** * Add site logo setting */ public function add_site_logo_setting() { register_setting('acemedia_login_block_options_group', 'acemedia_use_site_logo', [ 'type' => 'boolean', 'description' => __('Use site logo on login page', 'acemedia-login-block'), 'sanitize_callback' => 'rest_sanitize_boolean', 'default' => false, ]); register_setting('acemedia_login_block_options_group', 'acemedia_passkeys_enabled', [ 'type' => 'boolean', 'description' => __('Enable passkeys on the login page', 'acemedia-login-block'), 'sanitize_callback' => 'rest_sanitize_boolean', 'default' => true, ]); register_setting('acemedia_login_block_options_group', 'acemedia_passkeys_rp_id', [ 'type' => 'string', 'description' => __('Passkeys RP ID override (optional)', 'acemedia-login-block'), 'sanitize_callback' => 'sanitize_text_field', 'default' => '', ]); register_setting('acemedia_login_block_options_group', 'acemedia_passkeys_attestation', [ 'type' => 'string', 'description' => __('Passkeys attestation preference', 'acemedia-login-block'), 'sanitize_callback' => 'sanitize_text_field', 'default' => 'preferred', ]); } /** * Handle logo display on login page */ public function use_site_logo() { if (get_option('acemedia_use_site_logo', false)) { $custom_logo_id = get_theme_mod('custom_logo'); if ($custom_logo_id) { $logo_url = wp_get_attachment_image_url($custom_logo_id, 'full'); if ($logo_url) { ?> '; echo ''; foreach ($pages as $page) { echo ''; } echo ''; } /** * Add the toggle option to the settings page. */ private function acemedia_render_site_logo_setting() { $use_site_logo = get_option('acemedia_use_site_logo', false); ?>