Changeset 3401251
- Timestamp:
- 11/23/2025 11:39:05 AM (3 months ago)
- Location:
- admin-safety-guard
- Files:
-
- 4 edited
- 1 copied
-
tags/1.1.1 (copied) (copied from admin-safety-guard/trunk)
-
tags/1.1.1/app/Classes/Features/TwoFactorAuth.php (modified) (10 diffs)
-
tags/1.1.1/views/settings/support.php (modified) (8 diffs)
-
trunk/app/Classes/Features/TwoFactorAuth.php (modified) (10 diffs)
-
trunk/views/settings/support.php (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
admin-safety-guard/tags/1.1.1/app/Classes/Features/TwoFactorAuth.php
r3370983 r3401251 34 34 */ 35 35 public function register_hooks() { 36 $this->action( 'init', [ $this, 'email_otp_authentication'] );36 $this->action( 'init', [$this, 'email_otp_authentication'] ); 37 37 } 38 38 … … 46 46 47 47 if ( $this->is_enabled( $settings, 'otp-email' ) ) { 48 $this->action( 'login_form', [ $this, 'check_otp_submission'] );49 $this->action( 'login_form', [ $this, 'render_otp_input'] );50 $this->filter( 'authenticate', [ $this, 'intercept_login_with_otp'], 30, 3 );48 $this->action( 'login_form', [$this, 'check_otp_submission'] ); 49 $this->action( 'login_form', [$this, 'render_otp_input'] ); 50 $this->filter( 'authenticate', [$this, 'intercept_login_with_otp'], 30, 3 ); 51 51 } 52 52 } … … 58 58 */ 59 59 public function render_otp_input() { 60 if ( ! isset( $_GET['tpsa_verify_email_otp'] ) ) { 61 return; 62 } 63 64 $user_id = intval( $_GET['tpsa_verify_email_otp'] ); 65 $user = get_userdata($user_id); 60 if ( !isset( $_GET['tpsa_verify_email_otp'] ) ) { 61 return; 62 } 63 64 $user_id = intval( $_GET['tpsa_verify_email_otp'] ); 65 $user = get_userdata( $user_id ); 66 67 if ( !$user ) { 68 return; 69 } 66 70 67 71 $stored_data = get_user_meta( $user_id, '_tpsa_otp_code', true ); … … 69 73 $password = isset( $stored_data['password'] ) ? $stored_data['password'] : ''; 70 74 71 72 73 if ( ! empty( $username ) && ! empty( $password ) ) { 75 if ( !empty( $username ) && !empty( $password ) ) { 74 76 ?> 75 <script type="text/javascript">76 document.addEventListener( 'DOMContentLoaded', function() {77 var loginInput = document.getElementById( 'user_login');78 var passInput = document.getElementById( 'user_pass');79 80 if ( loginInput && passInput) {81 loginInput.value = <?php echo wp_json_encode( $username ); ?>;82 passInput.value = <?php echo wp_json_encode( $password ); ?>;83 }84 });85 </script>86 <?php87 }77 <script type="text/javascript"> 78 document.addEventListener('DOMContentLoaded', function() { 79 var loginInput = document.getElementById('user_login'); 80 var passInput = document.getElementById('user_pass'); 81 82 if (loginInput && passInput) { 83 loginInput.value = <?php echo wp_json_encode( $username ); ?>; 84 passInput.value = <?php echo wp_json_encode( $password ); ?>; 85 } 86 }); 87 </script> 88 <?php 89 } 88 90 ?> 89 <style type="text/css"> 90 #user_login, 91 #user_pass, 92 label[for="user_login"], 93 label[for="user_pass"], 94 .wp-hide-pw, 95 .forgetmenot, 96 .submit { 97 display: none !important; 98 } 99 100 #tpsa_otp_field { 101 font-size: 16px; 102 line-height: 1.5; 103 height: auto; 104 padding: 3px 8px; 105 width: 100%; 106 box-sizing: border-box; 107 } 108 109 #tpsa_verify_btn { 110 width: 100%; 111 padding: 8px 10px; 112 background: #2271b1; 113 border: none; 114 color: #fff; 115 font-weight: 600; 116 border-radius: 3px; 117 cursor: pointer; 118 font-size: 14px; 119 } 120 121 #tpsa_verify_btn:hover { 122 background: #165a96; 123 } 124 </style> 125 <div id="tpsa_otp_wrap"> 126 <label for="tpsa_otp_field"><?php echo esc_html__( 'One Time Password', 'tp-secure-plugin' ); ?></label> 127 <input type="hidden" name="tpsa_user_id" value="<?php echo esc_attr( $user_id ); ?>"> 128 <input type="hidden" name="tpsa_otp_verify" value="1"> 129 <input 130 type="text" 131 name="tpsa_otp" 132 id="tpsa_otp_field" 133 class="input" 134 placeholder="<?php echo esc_attr__( 'Enter OTP', 'tp-secure-plugin' ); ?>" 135 required 136 autocomplete="off" 137 > 138 <?php $this->sent_email_message( $user ); ?> 139 </div> 140 <button type="submit" id="tpsa_verify_btn"><?php echo esc_html__( 'Verify OTP', 'tp-secure-plugin' ); ?></button> 141 <?php 142 } 91 <style type="text/css"> 92 #user_login, 93 #user_pass, 94 label[for="user_login"], 95 label[for="user_pass"], 96 .wp-hide-pw, 97 .forgetmenot, 98 .submit { 99 display: none !important; 100 } 101 102 #tpsa_otp_field { 103 font-size: 16px; 104 line-height: 1.5; 105 height: auto; 106 padding: 3px 8px; 107 width: 100%; 108 box-sizing: border-box; 109 } 110 111 #tpsa_verify_btn { 112 width: 100%; 113 padding: 8px 10px; 114 background: #2271b1; 115 border: none; 116 color: #fff; 117 font-weight: 600; 118 border-radius: 3px; 119 cursor: pointer; 120 font-size: 14px; 121 } 122 123 #tpsa_verify_btn:hover { 124 background: #165a96; 125 } 126 </style> 127 <div id="tpsa_otp_wrap"> 128 <label for="tpsa_otp_field"><?php echo esc_html__( 'One Time Password', 'tp-secure-plugin' ); ?></label> 129 <input type="hidden" name="tpsa_user_id" value="<?php echo esc_attr( $user_id ); ?>"> 130 <input type="hidden" name="tpsa_otp_verify" value="1"> 131 <input type="text" name="tpsa_otp" id="tpsa_otp_field" class="input" 132 placeholder="<?php echo esc_attr__( 'Enter OTP', 'tp-secure-plugin' ); ?>" required autocomplete="off"> 133 <?php $this->sent_email_message( $user ); ?> 134 </div> 135 <button type="submit" id="tpsa_verify_btn"><?php echo esc_html__( 'Verify OTP', 'tp-secure-plugin' ); ?></button> 136 <?php 137 } 143 138 144 139 /** … … 148 143 */ 149 144 public function check_otp_submission() { 150 if ( 'POST' === strtoupper( $_SERVER['REQUEST_METHOD'] ) && isset( $_POST['tpsa_otp_verify'] ) ) { 151 $user_id = isset( $_POST['tpsa_user_id'] ) ? intval( $_POST['tpsa_user_id'] ) : 0; 152 $otp_input = isset( $_POST['tpsa_otp'] ) ? sanitize_text_field( wp_unslash( $_POST['tpsa_otp'] ) ) : ''; 153 154 if ( ! $user_id || empty( $otp_input ) ) { 155 return; 156 } 157 158 $stored_data = get_user_meta( $user_id, '_tpsa_otp_code', true ); 159 $stored_otp = isset( $stored_data['otp'] ) ? $stored_data['otp'] : ''; 160 161 if ( $otp_input === $stored_otp ) { 162 delete_user_meta( $user_id, '_tpsa_otp_code' ); 163 wp_set_auth_cookie( $user_id ); 164 wp_redirect( admin_url() ); 165 exit; 166 } else { 167 // Display error message above the form. 168 add_action( 'login_message', function() { 169 echo '<div style="color:red; margin-bottom:10px;">' . esc_html__( 'Invalid OTP. Please try again.', 'tp-secure-plugin' ) . '</div>'; 170 }); 171 } 145 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) || !isset( $_POST['tpsa_otp_verify'] ) ) { 146 return; 147 } 148 149 $user_id = isset( $_POST['tpsa_user_id'] ) ? intval( $_POST['tpsa_user_id'] ) : 0; 150 $otp_input = isset( $_POST['tpsa_otp'] ) ? sanitize_text_field( wp_unslash( $_POST['tpsa_otp'] ) ) : ''; 151 152 if ( !$user_id || empty( $otp_input ) ) { 153 return; 154 } 155 156 $stored_data = get_user_meta( $user_id, '_tpsa_otp_code', true ); 157 $stored_otp = isset( $stored_data['otp'] ) ? $stored_data['otp'] : ''; 158 $remember = !empty( $stored_data['remember'] ); 159 160 if ( $otp_input === $stored_otp ) { 161 // Clean up OTP data. 162 delete_user_meta( $user_id, '_tpsa_otp_code' ); 163 164 // Log user in with correct persistence. 165 wp_set_auth_cookie( $user_id, $remember ); 166 wp_set_current_user( $user_id ); 167 168 wp_redirect( admin_url() ); 169 exit; 170 } else { 171 // Display error message above the form. 172 add_action( 'login_message', function () { 173 echo '<div style="color:red; margin-bottom:10px;">' . esc_html__( 'Invalid OTP. Please try again.', 'tp-secure-plugin' ) . '</div>'; 174 } ); 172 175 } 173 176 } … … 177 180 * 178 181 * @param \WP_User|\WP_Error|null $user The WP_User or WP_Error object returned from authentication. 179 * @param string $username Username.180 * @param string $password Password.182 * @param string $username Username. 183 * @param string $password Password. 181 184 * 182 185 * @return \WP_User|\WP_Error|null 183 186 */ 184 187 public function intercept_login_with_otp( $user, $username, $password ) { 188 // If we are in the OTP verification step, let WordPress handle normally. 185 189 if ( isset( $_POST['tpsa_otp_verify'] ) ) { 186 // Let OTP verify handler manage login187 190 return $user; 188 191 } … … 192 195 } 193 196 194 // Generate and store OTP 197 // Capture the "Remember me" choice from the original login form. 198 $remember = !empty( $_POST['rememberme'] ); 199 200 // Generate and store OTP + remember flag. 195 201 $otp = rand( 1000, 99999 ); 196 202 197 update_user_meta( $user->ID, '_tpsa_otp_code', [ 198 'username' => $username, 199 'password' => $password, 200 'otp' => strval( $otp ), 201 ] ); 202 203 204 205 // Send OTP email (replace or extend for SMS if needed) 203 update_user_meta( 204 $user->ID, 205 '_tpsa_otp_code', 206 [ 207 'username' => $username, 208 'password' => $password, 209 'otp' => strval( $otp ), 210 'remember' => $remember ? 1 : 0, 211 ] 212 ); 213 214 // Send OTP email (replace or extend for SMS if needed). 206 215 $this->send_mail( $user, $otp ); 207 216 208 // Redirect to OTP verification page 217 // Redirect to OTP verification page. 209 218 wp_redirect( wp_login_url() . '?tpsa_verify_email_otp=' . intval( $user->ID ) ); 210 219 exit; 211 220 } 212 221 222 /** 223 * Send OTP email. 224 * 225 * @param \WP_User $user User object. 226 * @param int $otp One-time password. 227 * 228 * @return void 229 */ 213 230 private function send_mail( $user, $otp ) { 214 215 231 $user_email = $user->user_email; 216 232 $site_name = get_bloginfo( 'name' ); 233 217 234 $subject = sprintf( '%s - Your OTP is: %s', $site_name, $otp ); 218 235 $subject = apply_filters( 'tpsa_otp_email_subject', $subject, $otp ); … … 223 240 <style> 224 241 .email-container { 225 max-width: 400px;226 margin: 35px auto;227 padding: 20px;228 background-color: #f7f9fc;229 font-family: Arial, sans-serif;230 text-align: center;231 border-radius: 8px;242 max-width: 400px; 243 margin: 35px auto; 244 padding: 20px; 245 background-color: #f7f9fc; 246 font-family: Arial, sans-serif; 247 text-align: center; 248 border-radius: 8px; 232 249 } 233 250 .email-title { 234 font-size: 28px;235 font-weight: semibold;236 margin-bottom: 20px;237 color: #333333;251 font-size: 28px; 252 font-weight: 600; 253 margin-bottom: 20px; 254 color: #333333; 238 255 } 239 256 .otp-box { 240 background-color: #0073aa;241 color: #ffffff;242 font-size: 32px;243 font-weight: bold;244 padding: 15px 40px;245 border-radius: 6px;246 user-select: all;247 display: inline-block;248 letter-spacing: 6px;257 background-color: #0073aa; 258 color: #ffffff; 259 font-size: 32px; 260 font-weight: bold; 261 padding: 15px 40px; 262 border-radius: 6px; 263 user-select: all; 264 display: inline-block; 265 letter-spacing: 6px; 249 266 } 250 267 </style> … … 261 278 $message = apply_filters( 'tpsa_otp_email_message', $message, $otp ); 262 279 263 // Set content-type header for HTML email 264 $headers = array( 'Content-Type: text/html; charset=UTF-8' );280 // Set content-type header for HTML email. 281 $headers = ['Content-Type: text/html; charset=UTF-8']; 265 282 266 283 wp_mail( $user_email, $subject, $message, $headers ); 267 284 } 268 285 286 /** 287 * Show "email sent" message under OTP field. 288 * 289 * @param \WP_User $user 290 * 291 * @return void 292 */ 269 293 private function sent_email_message( $user ) { 270 if ( ! $user ) return; 271 $email = $user->user_email; 272 $email_parts = explode( '@', $email ); 273 $local = $email_parts[0]; 274 $domain = $email_parts[1] ?? ''; 275 $last_chars = substr($local, -3); 276 $masked_email = '....' . $last_chars . '@' . $domain; 277 294 if ( !$user ) { 295 return; 296 } 297 298 $email = $user->user_email; 299 $email_parts = explode( '@', $email ); 300 $local = $email_parts[0]; 301 $domain = $email_parts[1] ?? ''; 302 $last_chars = substr( $local, -3 ); 303 $masked_email = '....' . $last_chars . '@' . $domain; 278 304 ?> 279 <p style="color: green; font-weight: 600; margin-bottom: 20px;">280 <?php281 printf(282 __( 'OTP code sent to your email address %s. Please check your inbox or spam folder.', 'tp-secure-plugin '),283 esc_html( $masked_email )284 );285 ?>286 </p>287 <?php 288 }305 <p style="color: green; font-weight: 600; margin-bottom: 20px;"> 306 <?php 307 printf( 308 __( 'OTP code sent to your email address %s. Please check your inbox or spam folder.', 'tp-secure-plugin' ), 309 esc_html( $masked_email ) 310 ); 311 ?> 312 </p> 313 <?php 314 } 289 315 290 316 /** … … 307 333 */ 308 334 private function is_enabled( $settings, $key ) { 309 return isset( $settings[ $key ] ) && (int) $settings[ $key] === 1;310 } 311 } 335 return isset( $settings[$key] ) && (int) $settings[$key] === 1; 336 } 337 } -
admin-safety-guard/tags/1.1.1/views/settings/support.php
r3399014 r3401251 12 12 $support_notice_class = 'updated'; 13 13 14 if ( 'POST' === $_SERVER['REQUEST_METHOD'] && isset( $_POST['tpsa_support_name'], $_POST['tpsa_support_email'], $_POST['tpsa_support_message'] ) ) { 14 if ( 15 'POST' === $_SERVER['REQUEST_METHOD'] 16 && isset( 17 $_POST['tpsa_support_name'], 18 $_POST['tpsa_support_email'], 19 $_POST['tpsa_support_message'], 20 $_POST['tpsa_support_phone'] 21 ) 22 ) { 15 23 16 24 // Verify nonce 17 if ( !isset( $_POST['tpsa_support_form_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tpsa_support_form_nonce'] ) ), 'tpsa_support_form_nonce' ) ) { 25 if ( 26 !isset( $_POST['tpsa_support_form_nonce'] ) 27 || !wp_verify_nonce( 28 sanitize_text_field( wp_unslash( $_POST['tpsa_support_form_nonce'] ) ), 29 'tpsa_support_form_nonce' 30 ) 31 ) { 18 32 $support_notice = __( 'Security check failed. Please try again.', 'tp-secure-plugin' ); 19 33 $support_notice_class = 'error'; … … 24 38 $email = isset( $_POST['tpsa_support_email'] ) ? sanitize_email( wp_unslash( $_POST['tpsa_support_email'] ) ) : ''; 25 39 $message = isset( $_POST['tpsa_support_message'] ) ? wp_kses_post( wp_unslash( $_POST['tpsa_support_message'] ) ) : ''; 26 27 if ( empty( $name ) || empty( $email ) || empty( $message ) ) { 40 $phone = isset( $_POST['tpsa_support_phone'] ) ? sanitize_text_field( wp_unslash( $_POST['tpsa_support_phone'] ) ) : ''; 41 42 if ( empty( $name ) || empty( $email ) || empty( $message ) || empty( $phone ) ) { 28 43 $support_notice = __( 'Please fill all required fields.', 'tp-secure-plugin' ); 29 44 $support_notice_class = 'error'; … … 52 67 'name' => $name, 53 68 'email' => $email, 69 'phone' => $phone, 54 70 'message' => $message, 55 71 // Hardcoded plugin name as requested … … 79 95 $_POST['tpsa_support_email'] = ''; 80 96 $_POST['tpsa_support_message'] = ''; 97 $_POST['tpsa_support_phone'] = ''; 81 98 } else { 82 99 $error_msg = ''; … … 122 139 <div class="tp-field"> 123 140 <div class="tp-field-label"> 124 <label><?php esc_html_e( 'Your Name', 'tp-secure-plugin' ); ?> <span 125 style="color:red;">*</span> </label> 141 <label> 142 <?php esc_html_e( 'Your Name', 'tp-secure-plugin' ); ?> 143 <span style="color:red;">*</span> 144 </label> 126 145 </div> 127 146 <div class="tp-field-input"> … … 137 156 <div class="tp-field"> 138 157 <div class="tp-field-label"> 139 <label><?php esc_html_e( 'Your Email', 'tp-secure-plugin' ); ?> <span 140 style="color:red;">*</span> </label> 158 <label> 159 <?php esc_html_e( 'Your Email', 'tp-secure-plugin' ); ?> 160 <span style="color:red;">*</span> 161 </label> 141 162 </div> 142 163 <div class="tp-field-input"> … … 150 171 </div> 151 172 152 <div class="tp-field"> 153 <div class="tp-field-label"> 154 <label><?php esc_html_e( 'Your Message', 'tp-secure-plugin' ); ?> <span 155 style="color:red;">*</span> </label> 173 <!-- New Phone Number Field --> 174 <div class="tp-field"> 175 <div class="tp-field-label"> 176 <label> 177 <?php esc_html_e( 'Phone Number (with country code)', 'tp-secure-plugin' ); ?> 178 <span style="color:red;">*</span> 179 </label> 180 </div> 181 <div class="tp-field-input"> 182 <div class="tp-switch-wrapper"> 183 <input type="text" name="tpsa_support_phone" 184 value="<?php echo isset( $_POST['tpsa_support_phone'] ) ? esc_attr( wp_unslash( $_POST['tpsa_support_phone'] ) ) : ''; ?>" 185 placeholder="+8801XXXXXXXXX" required> 186 </div> 187 <p class="tp-field-desc"></p> 188 </div> 189 </div> 190 191 <div class="tp-field"> 192 <div class="tp-field-label"> 193 <label> 194 <?php esc_html_e( 'Your Message', 'tp-secure-plugin' ); ?> 195 <span style="color:red;">*</span> 196 </label> 156 197 </div> 157 198 <div class="tp-field-input"> … … 170 211 <div class="tp-switch-wrapper"> 171 212 <div class="tpsa-save-button"> 172 <button 173 type="submit"><?php esc_html_e( 'Send Support Request', 'tp-secure-plugin' ); ?></button> 213 <button type="submit"> 214 <?php esc_html_e( 'Send Support Request', 'tp-secure-plugin' ); ?> 215 </button> 174 216 </div> 175 217 </div> -
admin-safety-guard/trunk/app/Classes/Features/TwoFactorAuth.php
r3370983 r3401251 34 34 */ 35 35 public function register_hooks() { 36 $this->action( 'init', [ $this, 'email_otp_authentication'] );36 $this->action( 'init', [$this, 'email_otp_authentication'] ); 37 37 } 38 38 … … 46 46 47 47 if ( $this->is_enabled( $settings, 'otp-email' ) ) { 48 $this->action( 'login_form', [ $this, 'check_otp_submission'] );49 $this->action( 'login_form', [ $this, 'render_otp_input'] );50 $this->filter( 'authenticate', [ $this, 'intercept_login_with_otp'], 30, 3 );48 $this->action( 'login_form', [$this, 'check_otp_submission'] ); 49 $this->action( 'login_form', [$this, 'render_otp_input'] ); 50 $this->filter( 'authenticate', [$this, 'intercept_login_with_otp'], 30, 3 ); 51 51 } 52 52 } … … 58 58 */ 59 59 public function render_otp_input() { 60 if ( ! isset( $_GET['tpsa_verify_email_otp'] ) ) { 61 return; 62 } 63 64 $user_id = intval( $_GET['tpsa_verify_email_otp'] ); 65 $user = get_userdata($user_id); 60 if ( !isset( $_GET['tpsa_verify_email_otp'] ) ) { 61 return; 62 } 63 64 $user_id = intval( $_GET['tpsa_verify_email_otp'] ); 65 $user = get_userdata( $user_id ); 66 67 if ( !$user ) { 68 return; 69 } 66 70 67 71 $stored_data = get_user_meta( $user_id, '_tpsa_otp_code', true ); … … 69 73 $password = isset( $stored_data['password'] ) ? $stored_data['password'] : ''; 70 74 71 72 73 if ( ! empty( $username ) && ! empty( $password ) ) { 75 if ( !empty( $username ) && !empty( $password ) ) { 74 76 ?> 75 <script type="text/javascript">76 document.addEventListener( 'DOMContentLoaded', function() {77 var loginInput = document.getElementById( 'user_login');78 var passInput = document.getElementById( 'user_pass');79 80 if ( loginInput && passInput) {81 loginInput.value = <?php echo wp_json_encode( $username ); ?>;82 passInput.value = <?php echo wp_json_encode( $password ); ?>;83 }84 });85 </script>86 <?php87 }77 <script type="text/javascript"> 78 document.addEventListener('DOMContentLoaded', function() { 79 var loginInput = document.getElementById('user_login'); 80 var passInput = document.getElementById('user_pass'); 81 82 if (loginInput && passInput) { 83 loginInput.value = <?php echo wp_json_encode( $username ); ?>; 84 passInput.value = <?php echo wp_json_encode( $password ); ?>; 85 } 86 }); 87 </script> 88 <?php 89 } 88 90 ?> 89 <style type="text/css"> 90 #user_login, 91 #user_pass, 92 label[for="user_login"], 93 label[for="user_pass"], 94 .wp-hide-pw, 95 .forgetmenot, 96 .submit { 97 display: none !important; 98 } 99 100 #tpsa_otp_field { 101 font-size: 16px; 102 line-height: 1.5; 103 height: auto; 104 padding: 3px 8px; 105 width: 100%; 106 box-sizing: border-box; 107 } 108 109 #tpsa_verify_btn { 110 width: 100%; 111 padding: 8px 10px; 112 background: #2271b1; 113 border: none; 114 color: #fff; 115 font-weight: 600; 116 border-radius: 3px; 117 cursor: pointer; 118 font-size: 14px; 119 } 120 121 #tpsa_verify_btn:hover { 122 background: #165a96; 123 } 124 </style> 125 <div id="tpsa_otp_wrap"> 126 <label for="tpsa_otp_field"><?php echo esc_html__( 'One Time Password', 'tp-secure-plugin' ); ?></label> 127 <input type="hidden" name="tpsa_user_id" value="<?php echo esc_attr( $user_id ); ?>"> 128 <input type="hidden" name="tpsa_otp_verify" value="1"> 129 <input 130 type="text" 131 name="tpsa_otp" 132 id="tpsa_otp_field" 133 class="input" 134 placeholder="<?php echo esc_attr__( 'Enter OTP', 'tp-secure-plugin' ); ?>" 135 required 136 autocomplete="off" 137 > 138 <?php $this->sent_email_message( $user ); ?> 139 </div> 140 <button type="submit" id="tpsa_verify_btn"><?php echo esc_html__( 'Verify OTP', 'tp-secure-plugin' ); ?></button> 141 <?php 142 } 91 <style type="text/css"> 92 #user_login, 93 #user_pass, 94 label[for="user_login"], 95 label[for="user_pass"], 96 .wp-hide-pw, 97 .forgetmenot, 98 .submit { 99 display: none !important; 100 } 101 102 #tpsa_otp_field { 103 font-size: 16px; 104 line-height: 1.5; 105 height: auto; 106 padding: 3px 8px; 107 width: 100%; 108 box-sizing: border-box; 109 } 110 111 #tpsa_verify_btn { 112 width: 100%; 113 padding: 8px 10px; 114 background: #2271b1; 115 border: none; 116 color: #fff; 117 font-weight: 600; 118 border-radius: 3px; 119 cursor: pointer; 120 font-size: 14px; 121 } 122 123 #tpsa_verify_btn:hover { 124 background: #165a96; 125 } 126 </style> 127 <div id="tpsa_otp_wrap"> 128 <label for="tpsa_otp_field"><?php echo esc_html__( 'One Time Password', 'tp-secure-plugin' ); ?></label> 129 <input type="hidden" name="tpsa_user_id" value="<?php echo esc_attr( $user_id ); ?>"> 130 <input type="hidden" name="tpsa_otp_verify" value="1"> 131 <input type="text" name="tpsa_otp" id="tpsa_otp_field" class="input" 132 placeholder="<?php echo esc_attr__( 'Enter OTP', 'tp-secure-plugin' ); ?>" required autocomplete="off"> 133 <?php $this->sent_email_message( $user ); ?> 134 </div> 135 <button type="submit" id="tpsa_verify_btn"><?php echo esc_html__( 'Verify OTP', 'tp-secure-plugin' ); ?></button> 136 <?php 137 } 143 138 144 139 /** … … 148 143 */ 149 144 public function check_otp_submission() { 150 if ( 'POST' === strtoupper( $_SERVER['REQUEST_METHOD'] ) && isset( $_POST['tpsa_otp_verify'] ) ) { 151 $user_id = isset( $_POST['tpsa_user_id'] ) ? intval( $_POST['tpsa_user_id'] ) : 0; 152 $otp_input = isset( $_POST['tpsa_otp'] ) ? sanitize_text_field( wp_unslash( $_POST['tpsa_otp'] ) ) : ''; 153 154 if ( ! $user_id || empty( $otp_input ) ) { 155 return; 156 } 157 158 $stored_data = get_user_meta( $user_id, '_tpsa_otp_code', true ); 159 $stored_otp = isset( $stored_data['otp'] ) ? $stored_data['otp'] : ''; 160 161 if ( $otp_input === $stored_otp ) { 162 delete_user_meta( $user_id, '_tpsa_otp_code' ); 163 wp_set_auth_cookie( $user_id ); 164 wp_redirect( admin_url() ); 165 exit; 166 } else { 167 // Display error message above the form. 168 add_action( 'login_message', function() { 169 echo '<div style="color:red; margin-bottom:10px;">' . esc_html__( 'Invalid OTP. Please try again.', 'tp-secure-plugin' ) . '</div>'; 170 }); 171 } 145 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) || !isset( $_POST['tpsa_otp_verify'] ) ) { 146 return; 147 } 148 149 $user_id = isset( $_POST['tpsa_user_id'] ) ? intval( $_POST['tpsa_user_id'] ) : 0; 150 $otp_input = isset( $_POST['tpsa_otp'] ) ? sanitize_text_field( wp_unslash( $_POST['tpsa_otp'] ) ) : ''; 151 152 if ( !$user_id || empty( $otp_input ) ) { 153 return; 154 } 155 156 $stored_data = get_user_meta( $user_id, '_tpsa_otp_code', true ); 157 $stored_otp = isset( $stored_data['otp'] ) ? $stored_data['otp'] : ''; 158 $remember = !empty( $stored_data['remember'] ); 159 160 if ( $otp_input === $stored_otp ) { 161 // Clean up OTP data. 162 delete_user_meta( $user_id, '_tpsa_otp_code' ); 163 164 // Log user in with correct persistence. 165 wp_set_auth_cookie( $user_id, $remember ); 166 wp_set_current_user( $user_id ); 167 168 wp_redirect( admin_url() ); 169 exit; 170 } else { 171 // Display error message above the form. 172 add_action( 'login_message', function () { 173 echo '<div style="color:red; margin-bottom:10px;">' . esc_html__( 'Invalid OTP. Please try again.', 'tp-secure-plugin' ) . '</div>'; 174 } ); 172 175 } 173 176 } … … 177 180 * 178 181 * @param \WP_User|\WP_Error|null $user The WP_User or WP_Error object returned from authentication. 179 * @param string $username Username.180 * @param string $password Password.182 * @param string $username Username. 183 * @param string $password Password. 181 184 * 182 185 * @return \WP_User|\WP_Error|null 183 186 */ 184 187 public function intercept_login_with_otp( $user, $username, $password ) { 188 // If we are in the OTP verification step, let WordPress handle normally. 185 189 if ( isset( $_POST['tpsa_otp_verify'] ) ) { 186 // Let OTP verify handler manage login187 190 return $user; 188 191 } … … 192 195 } 193 196 194 // Generate and store OTP 197 // Capture the "Remember me" choice from the original login form. 198 $remember = !empty( $_POST['rememberme'] ); 199 200 // Generate and store OTP + remember flag. 195 201 $otp = rand( 1000, 99999 ); 196 202 197 update_user_meta( $user->ID, '_tpsa_otp_code', [ 198 'username' => $username, 199 'password' => $password, 200 'otp' => strval( $otp ), 201 ] ); 202 203 204 205 // Send OTP email (replace or extend for SMS if needed) 203 update_user_meta( 204 $user->ID, 205 '_tpsa_otp_code', 206 [ 207 'username' => $username, 208 'password' => $password, 209 'otp' => strval( $otp ), 210 'remember' => $remember ? 1 : 0, 211 ] 212 ); 213 214 // Send OTP email (replace or extend for SMS if needed). 206 215 $this->send_mail( $user, $otp ); 207 216 208 // Redirect to OTP verification page 217 // Redirect to OTP verification page. 209 218 wp_redirect( wp_login_url() . '?tpsa_verify_email_otp=' . intval( $user->ID ) ); 210 219 exit; 211 220 } 212 221 222 /** 223 * Send OTP email. 224 * 225 * @param \WP_User $user User object. 226 * @param int $otp One-time password. 227 * 228 * @return void 229 */ 213 230 private function send_mail( $user, $otp ) { 214 215 231 $user_email = $user->user_email; 216 232 $site_name = get_bloginfo( 'name' ); 233 217 234 $subject = sprintf( '%s - Your OTP is: %s', $site_name, $otp ); 218 235 $subject = apply_filters( 'tpsa_otp_email_subject', $subject, $otp ); … … 223 240 <style> 224 241 .email-container { 225 max-width: 400px;226 margin: 35px auto;227 padding: 20px;228 background-color: #f7f9fc;229 font-family: Arial, sans-serif;230 text-align: center;231 border-radius: 8px;242 max-width: 400px; 243 margin: 35px auto; 244 padding: 20px; 245 background-color: #f7f9fc; 246 font-family: Arial, sans-serif; 247 text-align: center; 248 border-radius: 8px; 232 249 } 233 250 .email-title { 234 font-size: 28px;235 font-weight: semibold;236 margin-bottom: 20px;237 color: #333333;251 font-size: 28px; 252 font-weight: 600; 253 margin-bottom: 20px; 254 color: #333333; 238 255 } 239 256 .otp-box { 240 background-color: #0073aa;241 color: #ffffff;242 font-size: 32px;243 font-weight: bold;244 padding: 15px 40px;245 border-radius: 6px;246 user-select: all;247 display: inline-block;248 letter-spacing: 6px;257 background-color: #0073aa; 258 color: #ffffff; 259 font-size: 32px; 260 font-weight: bold; 261 padding: 15px 40px; 262 border-radius: 6px; 263 user-select: all; 264 display: inline-block; 265 letter-spacing: 6px; 249 266 } 250 267 </style> … … 261 278 $message = apply_filters( 'tpsa_otp_email_message', $message, $otp ); 262 279 263 // Set content-type header for HTML email 264 $headers = array( 'Content-Type: text/html; charset=UTF-8' );280 // Set content-type header for HTML email. 281 $headers = ['Content-Type: text/html; charset=UTF-8']; 265 282 266 283 wp_mail( $user_email, $subject, $message, $headers ); 267 284 } 268 285 286 /** 287 * Show "email sent" message under OTP field. 288 * 289 * @param \WP_User $user 290 * 291 * @return void 292 */ 269 293 private function sent_email_message( $user ) { 270 if ( ! $user ) return; 271 $email = $user->user_email; 272 $email_parts = explode( '@', $email ); 273 $local = $email_parts[0]; 274 $domain = $email_parts[1] ?? ''; 275 $last_chars = substr($local, -3); 276 $masked_email = '....' . $last_chars . '@' . $domain; 277 294 if ( !$user ) { 295 return; 296 } 297 298 $email = $user->user_email; 299 $email_parts = explode( '@', $email ); 300 $local = $email_parts[0]; 301 $domain = $email_parts[1] ?? ''; 302 $last_chars = substr( $local, -3 ); 303 $masked_email = '....' . $last_chars . '@' . $domain; 278 304 ?> 279 <p style="color: green; font-weight: 600; margin-bottom: 20px;">280 <?php281 printf(282 __( 'OTP code sent to your email address %s. Please check your inbox or spam folder.', 'tp-secure-plugin '),283 esc_html( $masked_email )284 );285 ?>286 </p>287 <?php 288 }305 <p style="color: green; font-weight: 600; margin-bottom: 20px;"> 306 <?php 307 printf( 308 __( 'OTP code sent to your email address %s. Please check your inbox or spam folder.', 'tp-secure-plugin' ), 309 esc_html( $masked_email ) 310 ); 311 ?> 312 </p> 313 <?php 314 } 289 315 290 316 /** … … 307 333 */ 308 334 private function is_enabled( $settings, $key ) { 309 return isset( $settings[ $key ] ) && (int) $settings[ $key] === 1;310 } 311 } 335 return isset( $settings[$key] ) && (int) $settings[$key] === 1; 336 } 337 } -
admin-safety-guard/trunk/views/settings/support.php
r3399014 r3401251 12 12 $support_notice_class = 'updated'; 13 13 14 if ( 'POST' === $_SERVER['REQUEST_METHOD'] && isset( $_POST['tpsa_support_name'], $_POST['tpsa_support_email'], $_POST['tpsa_support_message'] ) ) { 14 if ( 15 'POST' === $_SERVER['REQUEST_METHOD'] 16 && isset( 17 $_POST['tpsa_support_name'], 18 $_POST['tpsa_support_email'], 19 $_POST['tpsa_support_message'], 20 $_POST['tpsa_support_phone'] 21 ) 22 ) { 15 23 16 24 // Verify nonce 17 if ( !isset( $_POST['tpsa_support_form_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tpsa_support_form_nonce'] ) ), 'tpsa_support_form_nonce' ) ) { 25 if ( 26 !isset( $_POST['tpsa_support_form_nonce'] ) 27 || !wp_verify_nonce( 28 sanitize_text_field( wp_unslash( $_POST['tpsa_support_form_nonce'] ) ), 29 'tpsa_support_form_nonce' 30 ) 31 ) { 18 32 $support_notice = __( 'Security check failed. Please try again.', 'tp-secure-plugin' ); 19 33 $support_notice_class = 'error'; … … 24 38 $email = isset( $_POST['tpsa_support_email'] ) ? sanitize_email( wp_unslash( $_POST['tpsa_support_email'] ) ) : ''; 25 39 $message = isset( $_POST['tpsa_support_message'] ) ? wp_kses_post( wp_unslash( $_POST['tpsa_support_message'] ) ) : ''; 26 27 if ( empty( $name ) || empty( $email ) || empty( $message ) ) { 40 $phone = isset( $_POST['tpsa_support_phone'] ) ? sanitize_text_field( wp_unslash( $_POST['tpsa_support_phone'] ) ) : ''; 41 42 if ( empty( $name ) || empty( $email ) || empty( $message ) || empty( $phone ) ) { 28 43 $support_notice = __( 'Please fill all required fields.', 'tp-secure-plugin' ); 29 44 $support_notice_class = 'error'; … … 52 67 'name' => $name, 53 68 'email' => $email, 69 'phone' => $phone, 54 70 'message' => $message, 55 71 // Hardcoded plugin name as requested … … 79 95 $_POST['tpsa_support_email'] = ''; 80 96 $_POST['tpsa_support_message'] = ''; 97 $_POST['tpsa_support_phone'] = ''; 81 98 } else { 82 99 $error_msg = ''; … … 122 139 <div class="tp-field"> 123 140 <div class="tp-field-label"> 124 <label><?php esc_html_e( 'Your Name', 'tp-secure-plugin' ); ?> <span 125 style="color:red;">*</span> </label> 141 <label> 142 <?php esc_html_e( 'Your Name', 'tp-secure-plugin' ); ?> 143 <span style="color:red;">*</span> 144 </label> 126 145 </div> 127 146 <div class="tp-field-input"> … … 137 156 <div class="tp-field"> 138 157 <div class="tp-field-label"> 139 <label><?php esc_html_e( 'Your Email', 'tp-secure-plugin' ); ?> <span 140 style="color:red;">*</span> </label> 158 <label> 159 <?php esc_html_e( 'Your Email', 'tp-secure-plugin' ); ?> 160 <span style="color:red;">*</span> 161 </label> 141 162 </div> 142 163 <div class="tp-field-input"> … … 150 171 </div> 151 172 152 <div class="tp-field"> 153 <div class="tp-field-label"> 154 <label><?php esc_html_e( 'Your Message', 'tp-secure-plugin' ); ?> <span 155 style="color:red;">*</span> </label> 173 <!-- New Phone Number Field --> 174 <div class="tp-field"> 175 <div class="tp-field-label"> 176 <label> 177 <?php esc_html_e( 'Phone Number (with country code)', 'tp-secure-plugin' ); ?> 178 <span style="color:red;">*</span> 179 </label> 180 </div> 181 <div class="tp-field-input"> 182 <div class="tp-switch-wrapper"> 183 <input type="text" name="tpsa_support_phone" 184 value="<?php echo isset( $_POST['tpsa_support_phone'] ) ? esc_attr( wp_unslash( $_POST['tpsa_support_phone'] ) ) : ''; ?>" 185 placeholder="+8801XXXXXXXXX" required> 186 </div> 187 <p class="tp-field-desc"></p> 188 </div> 189 </div> 190 191 <div class="tp-field"> 192 <div class="tp-field-label"> 193 <label> 194 <?php esc_html_e( 'Your Message', 'tp-secure-plugin' ); ?> 195 <span style="color:red;">*</span> 196 </label> 156 197 </div> 157 198 <div class="tp-field-input"> … … 170 211 <div class="tp-switch-wrapper"> 171 212 <div class="tpsa-save-button"> 172 <button 173 type="submit"><?php esc_html_e( 'Send Support Request', 'tp-secure-plugin' ); ?></button> 213 <button type="submit"> 214 <?php esc_html_e( 'Send Support Request', 'tp-secure-plugin' ); ?> 215 </button> 174 216 </div> 175 217 </div>
Note: See TracChangeset
for help on using the changeset viewer.