182 lines
9.8 KiB
PHP
182 lines
9.8 KiB
PHP
<?php
|
|
session_start();
|
|
require_once '../includes/db.php';
|
|
require_once '../includes/GoogleAuthenticator.php';
|
|
|
|
$ga = new PHPGangsta_GoogleAuthenticator();
|
|
|
|
$step = 1;
|
|
$error = '';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
|
if (isset($_POST['login_step_1'])) {
|
|
$username = trim($_POST['username'] ?? '');
|
|
$password = $_POST['password'] ?? '';
|
|
|
|
$stmt = $pdo->prepare("SELECT * FROM admin_users WHERE username = ?");
|
|
$stmt->execute([$username]);
|
|
$admin = $stmt->fetch();
|
|
|
|
if ($admin && password_verify($password, $admin['password_hash'])) {
|
|
// Step 1 Success
|
|
$_SESSION['temp_admin_id'] = $admin['id'];
|
|
$_SESSION['temp_admin_username'] = $admin['username'];
|
|
$_SESSION['temp_admin_role'] = $admin['role'];
|
|
$_SESSION['temp_admin_secret'] = $admin['google2fa_secret'];
|
|
|
|
if (empty($admin['google2fa_secret'])) {
|
|
// Not setup 2FA yet, go to setup
|
|
$_SESSION['admin_logged_in'] = true;
|
|
$_SESSION['admin_id'] = $admin['id'];
|
|
$_SESSION['admin_username'] = $admin['username'];
|
|
$_SESSION['admin_role'] = $admin['role'];
|
|
unset($_SESSION['temp_admin_id'], $_SESSION['temp_admin_username'], $_SESSION['temp_admin_role'], $_SESSION['temp_admin_secret']);
|
|
header("Location: setup_2fa.php");
|
|
exit;
|
|
} else {
|
|
$step = 2; // Move to 2FA step
|
|
}
|
|
} else {
|
|
$error = "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง";
|
|
}
|
|
} elseif (isset($_POST['login_step_2'])) {
|
|
$code = $_POST['code2fa'] ?? '';
|
|
$secret = $_SESSION['temp_admin_secret'];
|
|
|
|
if ($ga->verifyCode($secret, $code, 2)) {
|
|
// Success
|
|
$_SESSION['admin_logged_in'] = true;
|
|
$_SESSION['admin_id'] = $_SESSION['temp_admin_id'];
|
|
$_SESSION['admin_username'] = $_SESSION['temp_admin_username'];
|
|
$_SESSION['admin_role'] = $_SESSION['temp_admin_role'];
|
|
unset($_SESSION['temp_admin_id'], $_SESSION['temp_admin_username'], $_SESSION['temp_admin_role'], $_SESSION['temp_admin_secret']);
|
|
header("Location: index.php");
|
|
exit;
|
|
} else {
|
|
$error = "รหัส Google Authenticator ไม่ถูกต้อง";
|
|
$step = 2; // Stay at step 2
|
|
}
|
|
}
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="th">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Admin Login - KSH-STAFF</title>
|
|
<link rel="icon" type="image/png" href="../assets/img/logo.png">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script>
|
|
tailwind.config = {
|
|
theme: {
|
|
extend: {
|
|
fontFamily: {
|
|
sans: ['Sarabun', 'sans-serif'],
|
|
},
|
|
animation: {
|
|
shine: 'shine 3s ease-in-out infinite'
|
|
},
|
|
keyframes: {
|
|
shine: {
|
|
'0%': { left: '-150%' },
|
|
'20%': { left: '150%' },
|
|
'100%': { left: '150%' }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
</head>
|
|
<body class="bg-gray-100 min-h-screen flex items-center justify-center font-sans antialiased">
|
|
<div class="bg-white rounded-xl shadow-lg p-8 w-full max-w-md border border-gray-100">
|
|
<div class="text-center mb-6">
|
|
<div class="relative inline-block overflow-hidden rounded-full w-24 h-24 mx-auto mb-4 shadow-md bg-white p-1">
|
|
<img src="../assets/img/logo.png" alt="Logo" class="w-full h-full object-cover rounded-full relative z-10">
|
|
<div class="absolute inset-0 z-20 w-1/2 h-full bg-gradient-to-r from-transparent via-white/60 to-transparent -skew-x-12 animate-shine mix-blend-overlay"></div>
|
|
</div>
|
|
<h2 class="text-blue-600 text-2xl font-bold">Admin Login</h2>
|
|
</div>
|
|
|
|
<?php if (!empty($error)): ?>
|
|
<div class="text-red-500 text-center text-sm mb-4 font-medium bg-red-50 py-2 rounded-lg"><?= htmlspecialchars($error) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($step === 1): ?>
|
|
<form method="post" class="space-y-4">
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-medium mb-1">Username (หรือ CID)</label>
|
|
<input type="text" name="username" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition" required autofocus>
|
|
</div>
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-medium mb-1">Password</label>
|
|
<input type="password" name="password" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition" required>
|
|
</div>
|
|
<button type="submit" name="login_step_1" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-3 px-4 rounded-lg transition duration-200 shadow-md hover:shadow-lg mt-2">เข้าสู่ระบบ</button>
|
|
</form>
|
|
<?php else: ?>
|
|
<form method="post" id="otp-form" class="space-y-6">
|
|
<div class="text-center text-gray-600 text-sm leading-relaxed">
|
|
กรุณาเปิดแอปพลิเคชัน <strong class="text-gray-800">Google Authenticator</strong><br>และนำรหัส 6 หลักมากรอก
|
|
</div>
|
|
|
|
<div class="flex justify-center gap-2">
|
|
<input type="text" maxlength="1" oninput="moveToNext(this, 'otp2')" id="otp1" class="w-12 h-14 text-center text-2xl font-bold border-2 border-gray-300 rounded-lg focus:border-blue-500 focus:ring-4 focus:ring-blue-500/20 outline-none transition" autofocus>
|
|
<input type="text" maxlength="1" oninput="moveToNext(this, 'otp3')" onkeydown="moveToPrev(event, this, 'otp1')" id="otp2" class="w-12 h-14 text-center text-2xl font-bold border-2 border-gray-300 rounded-lg focus:border-blue-500 focus:ring-4 focus:ring-blue-500/20 outline-none transition">
|
|
<input type="text" maxlength="1" oninput="moveToNext(this, 'otp4')" onkeydown="moveToPrev(event, this, 'otp2')" id="otp3" class="w-12 h-14 text-center text-2xl font-bold border-2 border-gray-300 rounded-lg focus:border-blue-500 focus:ring-4 focus:ring-blue-500/20 outline-none transition">
|
|
<input type="text" maxlength="1" oninput="moveToNext(this, 'otp5')" onkeydown="moveToPrev(event, this, 'otp3')" id="otp4" class="w-12 h-14 text-center text-2xl font-bold border-2 border-gray-300 rounded-lg focus:border-blue-500 focus:ring-4 focus:ring-blue-500/20 outline-none transition">
|
|
<input type="text" maxlength="1" oninput="moveToNext(this, 'otp6')" onkeydown="moveToPrev(event, this, 'otp4')" id="otp5" class="w-12 h-14 text-center text-2xl font-bold border-2 border-gray-300 rounded-lg focus:border-blue-500 focus:ring-4 focus:ring-blue-500/20 outline-none transition">
|
|
<input type="text" maxlength="1" oninput="submitOtp()" onkeydown="moveToPrev(event, this, 'otp5')" id="otp6" class="w-12 h-14 text-center text-2xl font-bold border-2 border-gray-300 rounded-lg focus:border-blue-500 focus:ring-4 focus:ring-blue-500/20 outline-none transition">
|
|
</div>
|
|
|
|
<input type="hidden" name="code2fa" id="code2fa" required>
|
|
|
|
<button type="submit" name="login_step_2" id="submit-btn" class="hidden">ยืนยันตัวตน</button>
|
|
<div class="text-center mt-6">
|
|
<a href="login.php" class="text-sm text-gray-500 hover:text-gray-800 hover:underline transition">ยกเลิก / กลับไปหน้าแรก</a>
|
|
</div>
|
|
</form>
|
|
|
|
<script>
|
|
function moveToNext(current, nextFieldId) {
|
|
if (current.value.length === 1) {
|
|
if (nextFieldId) document.getElementById(nextFieldId).focus();
|
|
}
|
|
}
|
|
function moveToPrev(e, current, prevFieldId) {
|
|
if (e.key === 'Backspace' && current.value === '') {
|
|
if (prevFieldId) document.getElementById(prevFieldId).focus();
|
|
}
|
|
}
|
|
function submitOtp() {
|
|
let code = '';
|
|
for (let i = 1; i <= 6; i++) {
|
|
code += document.getElementById('otp' + i).value;
|
|
}
|
|
document.getElementById('code2fa').value = code;
|
|
if (code.length === 6) {
|
|
document.getElementById('submit-btn').click();
|
|
}
|
|
}
|
|
|
|
// Handle pasting 6 digits at once
|
|
document.getElementById('otp1').addEventListener('paste', function(e) {
|
|
let paste = (e.clipboardData || window.clipboardData).getData('text');
|
|
if (paste.length === 6 && /^\d+$/.test(paste)) {
|
|
for (let i = 0; i < 6; i++) {
|
|
document.getElementById('otp' + (i+1)).value = paste[i];
|
|
}
|
|
submitOtp();
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
</script>
|
|
<?php endif; ?>
|
|
</div>
|
|
</body>
|
|
</html>
|