after login
This commit is contained in:
parent
8a6a18d0c2
commit
c225ebebc1
@ -440,6 +440,19 @@
|
|||||||
.login-container {
|
.login-container {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.login-container {
|
||||||
|
max-width: 600px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) and (max-width: 991px) {
|
||||||
|
.login-container {
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
.login-form-wrapper {
|
.login-form-wrapper {
|
||||||
padding: 2rem 1.5rem;
|
padding: 2rem 1.5rem;
|
||||||
}
|
}
|
||||||
|
|||||||
193
auth_handler.php
193
auth_handler.php
@ -1,17 +1,195 @@
|
|||||||
<?php
|
<?php
|
||||||
// MUST be called before session_start()
|
|
||||||
require_once 'includes/session_config.php';
|
require_once 'includes/session_config.php';
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
require_once 'db/config.php';
|
require_once 'db/config.php';
|
||||||
|
require_once 'mail/MailService.php';
|
||||||
|
|
||||||
// If Google user info is not in the session, redirect to login.
|
// Main router for authentication actions
|
||||||
|
$action = $_GET['action'] ?? '';
|
||||||
|
|
||||||
|
switch ($action) {
|
||||||
|
case 'send_otp':
|
||||||
|
handle_send_otp();
|
||||||
|
break;
|
||||||
|
case 'verify_otp':
|
||||||
|
handle_verify_otp();
|
||||||
|
break;
|
||||||
|
case 'resend_otp':
|
||||||
|
handle_resend_otp();
|
||||||
|
break;
|
||||||
|
case 'google_callback':
|
||||||
|
handle_google_callback();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'درخواست نامعتبر است.'];
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_resend_otp() {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
if (!isset($_SESSION['otp_identifier'])) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'جلسه شما یافت نشد. لطفا دوباره تلاش کنید.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$identifier = $_SESSION['otp_identifier'];
|
||||||
|
$login_method = filter_var($identifier, FILTER_VALIDATE_EMAIL) ? 'email' : 'phone';
|
||||||
|
|
||||||
|
// Generate a new, cryptographically secure 6-digit OTP for resend
|
||||||
|
$otp = random_int(100000, 999999);
|
||||||
|
$expires = date('Y-m-d H:i:s', time() + (10 * 60)); // 10 minutes expiry
|
||||||
|
|
||||||
|
try {
|
||||||
|
// A new OTP is inserted. The verification logic automatically picks the latest valid one.
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO otp_codes (identifier, code, expires_at) VALUES (?, ?, ?)");
|
||||||
|
$stmt->execute([$identifier, $otp, $expires]);
|
||||||
|
|
||||||
|
// FOR TESTING: Always show the OTP for debugging purposes
|
||||||
|
$_SESSION['show_otp_for_debugging'] = $otp;
|
||||||
|
|
||||||
|
echo json_encode(['success' => true, 'otp' => $otp, 'message' => 'کد جدید با موفقیت ارسال شد.']);
|
||||||
|
exit;
|
||||||
|
|
||||||
|
} catch (Throwable $t) {
|
||||||
|
error_log("OTP Resend Error: " . $t->getMessage());
|
||||||
|
echo json_encode(['success' => false, 'message' => 'خطایی در سیستم هنگام ارسال مجدد کد رخ داد.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_send_otp() {
|
||||||
|
$pdo = db();
|
||||||
|
$identifier = '';
|
||||||
|
$login_method = '';
|
||||||
|
|
||||||
|
// Simplified and corrected logic
|
||||||
|
if (isset($_POST['email'])) {
|
||||||
|
// Trim whitespace from the email input
|
||||||
|
$identifier = trim($_POST['email']);
|
||||||
|
if (filter_var($identifier, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$login_method = 'email';
|
||||||
|
} else {
|
||||||
|
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'لطفا یک ایمیل معتبر وارد کنید.'];
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
} elseif (isset($_POST['phone'])) {
|
||||||
|
// Trim whitespace from the phone input
|
||||||
|
$identifier = trim($_POST['phone']);
|
||||||
|
if (preg_match('/^09[0-9]{9}$/', $identifier)) {
|
||||||
|
$login_method = 'phone';
|
||||||
|
} else {
|
||||||
|
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'لطفا یک شماره تلفن معتبر (مانند 09123456789) وارد کنید.'];
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Neither email nor phone was submitted
|
||||||
|
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'ایمیل یا شماره تلفن ارسال نشده است.'];
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
// Generate a cryptographically secure 6-digit OTP
|
||||||
|
$otp = random_int(100000, 999999);
|
||||||
|
$expires = date('Y-m-d H:i:s', time() + (10 * 60)); // 10 minutes expiry
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO otp_codes (identifier, code, expires_at) VALUES (?, ?, ?)");
|
||||||
|
$stmt->execute([$identifier, $otp, $expires]);
|
||||||
|
|
||||||
|
$_SESSION['otp_identifier'] = $identifier;
|
||||||
|
|
||||||
|
// FOR TESTING: Always show the OTP for debugging purposes for both email and phone
|
||||||
|
$_SESSION['show_otp_for_debugging'] = $otp;
|
||||||
|
|
||||||
|
|
||||||
|
header('Location: verify.php');
|
||||||
|
exit;
|
||||||
|
|
||||||
|
} catch (Throwable $t) {
|
||||||
|
error_log("OTP Generation Error: " . $t->getMessage());
|
||||||
|
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'خطایی در سیستم رخ داد. لطفا دوباره تلاش کنید.'];
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_verify_otp() {
|
||||||
|
if (empty($_POST['otp_code']) || empty($_SESSION['otp_identifier'])) {
|
||||||
|
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'جلسه شما منقضی شده است. لطفا دوباره تلاش کنید.'];
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
$identifier = $_SESSION['otp_identifier'];
|
||||||
|
$otp_code = $_POST['otp_code'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM otp_codes WHERE identifier = ? AND code = ? AND expires_at > NOW() ORDER BY created_at DESC LIMIT 1");
|
||||||
|
$stmt->execute([$identifier, $otp_code]);
|
||||||
|
$otp_entry = $stmt->fetch();
|
||||||
|
|
||||||
|
if ($otp_entry) {
|
||||||
|
// OTP is correct, clean up and log the user in
|
||||||
|
$delete_stmt = $pdo->prepare("DELETE FROM otp_codes WHERE identifier = ?");
|
||||||
|
$delete_stmt->execute([$identifier]);
|
||||||
|
unset($_SESSION['otp_identifier']);
|
||||||
|
unset($_SESSION['show_otp_for_debugging']);
|
||||||
|
|
||||||
|
// Determine if login was via email or phone
|
||||||
|
$is_email = filter_var($identifier, FILTER_VALIDATE_EMAIL);
|
||||||
|
$column = $is_email ? 'email' : 'phone';
|
||||||
|
|
||||||
|
$user_stmt = $pdo->prepare("SELECT * FROM users WHERE $column = ?");
|
||||||
|
$user_stmt->execute([$identifier]);
|
||||||
|
$user = $user_stmt->fetch();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
// User exists, log them in
|
||||||
|
$_SESSION['user_id'] = $user['id'];
|
||||||
|
$_SESSION['user_name'] = trim($user['first_name'] . ' ' . $user['last_name']);
|
||||||
|
$_SESSION['is_admin'] = $user['is_admin'];
|
||||||
|
} else {
|
||||||
|
// User does not exist, create a new one
|
||||||
|
$insert_column = $is_email ? 'email' : 'phone';
|
||||||
|
$insert_stmt = $pdo->prepare("INSERT INTO users ($insert_column, created_at) VALUES (?, NOW())");
|
||||||
|
$insert_stmt->execute([$identifier]);
|
||||||
|
$newUserId = $pdo->lastInsertId();
|
||||||
|
|
||||||
|
$_SESSION['user_id'] = $newUserId;
|
||||||
|
$_SESSION['user_name'] = $identifier; // Placeholder name
|
||||||
|
$_SESSION['is_admin'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: profile.php');
|
||||||
|
exit;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Invalid or expired OTP
|
||||||
|
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'کد تایید نامعتبر یا منقضی شده است.'];
|
||||||
|
header('Location: verify.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Throwable $t) {
|
||||||
|
// Reverted to production error handling
|
||||||
|
error_log("OTP Verification Error: " . $t->getMessage());
|
||||||
|
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'خطایی در پایگاه داده رخ داد. لطفا دوباره تلاش کنید.'];
|
||||||
|
header('Location: verify.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_google_callback() {
|
||||||
if (!isset($_SESSION['google_user_info'])) {
|
if (!isset($_SESSION['google_user_info'])) {
|
||||||
header('Location: login.php?error=google_auth_failed');
|
header('Location: login.php?error=google_auth_failed');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve user info from session
|
|
||||||
$google_user = $_SESSION['google_user_info'];
|
$google_user = $_SESSION['google_user_info'];
|
||||||
$email = $google_user['email'];
|
$email = $google_user['email'];
|
||||||
$fullName = $google_user['name'];
|
$fullName = $google_user['name'];
|
||||||
@ -29,12 +207,10 @@ try {
|
|||||||
$user = $stmt->fetch();
|
$user = $stmt->fetch();
|
||||||
|
|
||||||
if ($user) {
|
if ($user) {
|
||||||
// User exists, log them in
|
|
||||||
$_SESSION['user_id'] = $user['id'];
|
$_SESSION['user_id'] = $user['id'];
|
||||||
$_SESSION['user_name'] = trim($user['first_name'] . ' ' . $user['last_name']);
|
$_SESSION['user_name'] = trim($user['first_name'] . ' ' . $user['last_name']);
|
||||||
$_SESSION['is_admin'] = $user['is_admin'];
|
$_SESSION['is_admin'] = $user['is_admin'];
|
||||||
} else {
|
} else {
|
||||||
// User does not exist, create a new one
|
|
||||||
$insertStmt = $pdo->prepare("INSERT INTO users (first_name, last_name, email, password, is_admin, created_at) VALUES (?, ?, ?, NULL, 0, NOW())");
|
$insertStmt = $pdo->prepare("INSERT INTO users (first_name, last_name, email, password, is_admin, created_at) VALUES (?, ?, ?, NULL, 0, NOW())");
|
||||||
$insertStmt->execute([$firstName, $lastName, $email]);
|
$insertStmt->execute([$firstName, $lastName, $email]);
|
||||||
$newUserId = $pdo->lastInsertId();
|
$newUserId = $pdo->lastInsertId();
|
||||||
@ -48,8 +224,9 @@ try {
|
|||||||
exit();
|
exit();
|
||||||
|
|
||||||
} catch (Throwable $t) {
|
} catch (Throwable $t) {
|
||||||
$error_message = 'Database error during Google auth processing: ' . $t->getMessage();
|
error_log('Database error during Google auth processing: ' . $t->getMessage());
|
||||||
error_log($error_message);
|
|
||||||
header('Location: login.php?error=db_error');
|
header('Location: login.php?error=db_error');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
3
db/migrations/017_fix_otp_table.sql
Normal file
3
db/migrations/017_fix_otp_table.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE `otp_codes`
|
||||||
|
CHANGE COLUMN `email` `identifier` VARCHAR(255) NOT NULL,
|
||||||
|
CHANGE COLUMN `code_hash` `code` VARCHAR(255) NOT NULL;
|
||||||
3
db/migrations/018_allow_null_names_in_users.sql
Normal file
3
db/migrations/018_allow_null_names_in_users.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE `users`
|
||||||
|
MODIFY COLUMN `first_name` VARCHAR(100) NULL,
|
||||||
|
MODIFY COLUMN `last_name` VARCHAR(100) NULL;
|
||||||
1
db/migrations/019_allow_null_email_in_users.sql
Normal file
1
db/migrations/019_allow_null_email_in_users.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;
|
||||||
@ -31,3 +31,4 @@ Google token response: Array
|
|||||||
)
|
)
|
||||||
|
|
||||||
Google Auth Exception: Token error: Bad Request
|
Google Auth Exception: Token error: Bad Request
|
||||||
|
OTP Send Mail Error: PHPMailer error: SMTP Error: data not accepted.
|
||||||
|
|||||||
@ -6,8 +6,8 @@ session_start();
|
|||||||
require_once 'vendor/autoload.php';
|
require_once 'vendor/autoload.php';
|
||||||
|
|
||||||
// Google API configuration
|
// Google API configuration
|
||||||
define('GOOGLE_CLIENT_ID', '915631311746-o6gk076l6lfvuboin99u2h8cgqilc0qk.apps.googleusercontent.com');
|
define('GOOGLE_CLIENT_ID', '915631311746-u10nasn59smdjn3ofle2a186vobmgll7.apps.googleusercontent.com');
|
||||||
define('GOOGLE_CLIENT_SECRET', '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');
|
define('GOOGLE_CLIENT_SECRET', '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');
|
||||||
define('GOOGLE_REDIRECT_URL', 'https://atimah-leather.dev.flatlogic.app/google_callback.php');
|
define('GOOGLE_REDIRECT_URL', 'https://atimah-leather.dev.flatlogic.app/google_callback.php');
|
||||||
|
|
||||||
// Check if the user has a temporary identifier from the initial login, and clear it.
|
// Check if the user has a temporary identifier from the initial login, and clear it.
|
||||||
@ -48,7 +48,7 @@ if (isset($_GET['code'])) {
|
|||||||
// Explicitly save the session data before redirecting.
|
// Explicitly save the session data before redirecting.
|
||||||
session_write_close();
|
session_write_close();
|
||||||
|
|
||||||
header('Location: auth_handler.php');
|
header('Location: auth_handler.php?action=google_callback');
|
||||||
exit();
|
exit();
|
||||||
|
|
||||||
} catch (Throwable $t) {
|
} catch (Throwable $t) {
|
||||||
@ -59,9 +59,7 @@ if (isset($_GET['code'])) {
|
|||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$authUrl = $client->createAuthUrl();
|
// It's the initial request, redirect to Google's OAuth 2.0 server
|
||||||
// Instead of redirecting, print the URL for debugging
|
header('Location: ' . $client->createAuthUrl());
|
||||||
echo "Please copy this URL and send it back to me:<br><br>";
|
|
||||||
echo $authUrl;
|
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|||||||
66
login.php
66
login.php
@ -68,13 +68,27 @@ $body_class = "login-page-modern";
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Email Input -->
|
||||||
|
<div id="email_input_group">
|
||||||
<div class="form-floating mb-3">
|
<div class="form-floating mb-3">
|
||||||
<input type="email" class="form-control" id="login_identifier" name="email" placeholder="ایمیل خود را وارد کنید" required>
|
<input type="email" class="form-control" id="email_input" name="email" placeholder="ایمیل خود را وارد کنید" required>
|
||||||
<label for="login_identifier">ایمیل</label>
|
<label for="email_input">ایمیل</label>
|
||||||
<div class="invalid-feedback" id="invalid_feedback_message">
|
<div class="invalid-feedback">
|
||||||
لطفا یک ایمیل معتبر وارد کنید.
|
لطفا یک ایمیل معتبر وارد کنید.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Phone Input (hidden by default) -->
|
||||||
|
<div id="phone_input_group" style="display: none;">
|
||||||
|
<div class="form-floating mb-3">
|
||||||
|
<input type="tel" class="form-control" id="phone_input" name="phone" placeholder="09123456789" pattern="09[0-9]{9}" required>
|
||||||
|
<label for="phone_input">تلفن همراه</label>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
لطفا یک شماره تلفن معتبر (مانند 09123456789) وارد کنید.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="d-grid mt-4">
|
<div class="d-grid mt-4">
|
||||||
<button type="submit" class="btn btn-primary btn-lg">ادامه</button>
|
<button type="submit" class="btn btn-primary btn-lg">ادامه</button>
|
||||||
@ -99,7 +113,7 @@ $body_class = "login-page-modern";
|
|||||||
<!-- Bootstrap JS -->
|
<!-- Bootstrap JS -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
// Simple form validation
|
// Standard Bootstrap validation script
|
||||||
(function () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
var forms = document.querySelectorAll('.needs-validation');
|
var forms = document.querySelectorAll('.needs-validation');
|
||||||
@ -115,49 +129,45 @@ $body_class = "login-page-modern";
|
|||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Login toggle logic
|
// New, simplified toggle logic
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const emailToggle = document.getElementById('email_toggle');
|
const emailToggle = document.getElementById('email_toggle');
|
||||||
const phoneToggle = document.getElementById('phone_toggle');
|
const phoneToggle = document.getElementById('phone_toggle');
|
||||||
const loginInput = document.getElementById('login_identifier');
|
|
||||||
const loginLabel = document.querySelector('label[for="login_identifier"]');
|
|
||||||
const feedbackMessage = document.getElementById('invalid_feedback_message');
|
|
||||||
|
|
||||||
function updateInput(isEmail) {
|
const emailGroup = document.getElementById('email_input_group');
|
||||||
if (isEmail) {
|
const phoneGroup = document.getElementById('phone_input_group');
|
||||||
loginInput.type = 'email';
|
|
||||||
loginInput.name = 'email';
|
const emailInput = document.getElementById('email_input');
|
||||||
loginInput.placeholder = 'ایمیل خود را وارد کنید';
|
const phoneInput = document.getElementById('phone_input');
|
||||||
loginInput.pattern = null; // Use browser's default email validation
|
|
||||||
loginLabel.textContent = 'ایمیل';
|
function toggleInputs(showEmail) {
|
||||||
feedbackMessage.textContent = 'لطفا یک ایمیل معتبر وارد کنید.';
|
if (showEmail) {
|
||||||
|
emailGroup.style.display = 'block';
|
||||||
|
emailInput.disabled = false;
|
||||||
|
phoneGroup.style.display = 'none';
|
||||||
|
phoneInput.disabled = true;
|
||||||
} else {
|
} else {
|
||||||
loginInput.type = 'tel';
|
emailGroup.style.display = 'none';
|
||||||
loginInput.name = 'phone';
|
emailInput.disabled = true;
|
||||||
loginInput.placeholder = '09123456789';
|
phoneGroup.style.display = 'block';
|
||||||
loginInput.pattern = '09[0-9]{9}'; // Simple Iranian mobile pattern
|
phoneInput.disabled = false;
|
||||||
loginLabel.textContent = 'تلفن همراه';
|
|
||||||
feedbackMessage.textContent = 'لطفا یک شماره تلفن معتبر (مانند 09123456789) وارد کنید.';
|
|
||||||
}
|
}
|
||||||
// Reset validation state
|
|
||||||
loginInput.value = '';
|
|
||||||
loginInput.closest('form').classList.remove('was-validated');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emailToggle.addEventListener('change', function() {
|
emailToggle.addEventListener('change', function() {
|
||||||
if (this.checked) {
|
if (this.checked) {
|
||||||
updateInput(true);
|
toggleInputs(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
phoneToggle.addEventListener('change', function() {
|
phoneToggle.addEventListener('change', function() {
|
||||||
if (this.checked) {
|
if (this.checked) {
|
||||||
updateInput(false);
|
toggleInputs(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize on page load
|
// Initialize on page load
|
||||||
updateInput(emailToggle.checked);
|
toggleInputs(emailToggle.checked);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
111
verify.php
111
verify.php
@ -59,11 +59,13 @@ $debug_otp = $_SESSION['show_otp_for_debugging'] ?? null;
|
|||||||
<?php unset($_SESSION['flash_message']); ?>
|
<?php unset($_SESSION['flash_message']); ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div id="otpDisplayContainer">
|
||||||
<?php if ($debug_otp): ?>
|
<?php if ($debug_otp): ?>
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
<strong>حالت آزمایشی:</strong> سرویس پیامک فعال نیست. کد شما: <strong><?= htmlspecialchars($debug_otp); ?></strong>
|
<strong>حالت آزمایشی:</strong> سرویس پیامک فعال نیست. کد شما: <strong id="otpCode"><?= htmlspecialchars($debug_otp); ?></strong>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form action="auth_handler.php?action=verify_otp" method="POST" class="needs-validation" novalidate>
|
<form action="auth_handler.php?action=verify_otp" method="POST" class="needs-validation" novalidate>
|
||||||
<input type="hidden" name="identifier" value="<?= $identifier_for_display; ?>">
|
<input type="hidden" name="identifier" value="<?= $identifier_for_display; ?>">
|
||||||
@ -80,13 +82,116 @@ $debug_otp = $_SESSION['show_otp_for_debugging'] ?? null;
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="auth-footer text-center mt-4">
|
<div class="resend-container text-center mt-4">
|
||||||
<p><a href="login.php"><i class="ri-arrow-right-line align-middle"></i> بازگشت و اصلاح</a></p>
|
<button id="resendBtn" class="btn btn-link text-decoration-none" disabled>ارسال مجدد کد</button>
|
||||||
|
<div id="timerContainer" class="timer-container text-secondary mt-2">
|
||||||
|
<span id="timer_message">ارسال مجدد تا <span id="timer" class="fw-bold">30</span> ثانیه دیگر</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="auth-footer text-center mt-3">
|
||||||
|
<p><a href="login.php" class="text-secondary"><i class="ri-arrow-right-line align-middle"></i> بازگشت و اصلاح</a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Bootstrap JS -->
|
<!-- Bootstrap JS -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const resendBtn = document.getElementById('resendBtn');
|
||||||
|
const timerEl = document.getElementById('timer');
|
||||||
|
const timerContainer = document.getElementById('timerContainer');
|
||||||
|
let countdownInterval;
|
||||||
|
|
||||||
|
function startTimer() {
|
||||||
|
let countdown = 30;
|
||||||
|
resendBtn.disabled = true;
|
||||||
|
timerContainer.style.display = 'block';
|
||||||
|
timerEl.textContent = countdown;
|
||||||
|
|
||||||
|
countdownInterval = setInterval(() => {
|
||||||
|
countdown--;
|
||||||
|
if (countdown > 0) {
|
||||||
|
timerEl.textContent = countdown;
|
||||||
|
} else {
|
||||||
|
clearInterval(countdownInterval);
|
||||||
|
timerContainer.style.display = 'none';
|
||||||
|
resendBtn.disabled = false;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
resendBtn.addEventListener('click', function() {
|
||||||
|
clearInterval(countdownInterval);
|
||||||
|
startTimer();
|
||||||
|
|
||||||
|
const originalBtnText = resendBtn.textContent;
|
||||||
|
resendBtn.textContent = 'در حال ارسال...';
|
||||||
|
resendBtn.disabled = true;
|
||||||
|
|
||||||
|
fetch('auth_handler.php?action=resend_otp', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Network response was not ok');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
console.log('Resend request completed:', data);
|
||||||
|
resendBtn.textContent = originalBtnText;
|
||||||
|
|
||||||
|
if (data.success && data.otp) {
|
||||||
|
let otpDisplayContainer = document.getElementById('otpDisplayContainer');
|
||||||
|
let otpCodeEl = document.getElementById('otpCode');
|
||||||
|
|
||||||
|
if (otpCodeEl) {
|
||||||
|
// If the element exists, just update the code
|
||||||
|
otpCodeEl.textContent = data.otp;
|
||||||
|
} else {
|
||||||
|
// If the element doesn't exist, create and inject it
|
||||||
|
const newOtpDisplay = document.createElement('div');
|
||||||
|
newOtpDisplay.className = 'alert alert-warning';
|
||||||
|
newOtpDisplay.innerHTML = `<strong>حالت آزمایشی:</strong> سرویس پیامک فعال نیست. کد شما: <strong id="otpCode">${data.otp}</strong>`;
|
||||||
|
|
||||||
|
// Find a good place to insert it, e.g., before the form
|
||||||
|
const form = document.querySelector('.needs-validation');
|
||||||
|
if (form) {
|
||||||
|
otpDisplayContainer.appendChild(newOtpDisplay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can add a small visual confirmation, like a flash
|
||||||
|
const otpDisplayDiv = document.querySelector('#otpDisplayContainer .alert');
|
||||||
|
if(otpDisplayDiv) {
|
||||||
|
otpDisplayDiv.style.transition = 'none';
|
||||||
|
otpDisplayDiv.style.backgroundColor = '#fff3cd'; // Bootstrap's warning yellow
|
||||||
|
setTimeout(() => {
|
||||||
|
otpDisplayDiv.style.transition = 'background-color 0.5s ease';
|
||||||
|
otpDisplayDiv.style.backgroundColor = '';
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Handle server-side errors
|
||||||
|
alert(data.message || 'خطایی در ارسال مجدد کد رخ داد.');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error resending OTP:', error);
|
||||||
|
resendBtn.textContent = originalBtnText;
|
||||||
|
alert('یک خطای ارتباطی رخ داد. لطفاً اتصال اینترنت خود را بررسی کنید.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start the timer when the page loads
|
||||||
|
startTimer();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user