Sindbad~EG File Manager
<?php
session_start();
require_once 'config/database.php';
require_once 'includes/functions.php';
// Redirect if already logged in
if (isset($_SESSION['user_id'])) {
header('Location: index.php');
exit();
}
$error_message = '';
$success_message = '';
$show_2fa_form = false;
$pending_token = '';
$pending_email = '';
// Get token from POST or GET
$pending_token = isset($_POST['pending_token']) ? $_POST['pending_token'] : (isset($_GET['token']) ? $_GET['token'] : '');
// Handle cancel 2FA
if (isset($_GET['cancel'])) {
header('Location: login.php');
exit();
}
// Get pending user ID from token (database-based, not session)
$pending_user_id = null;
if ($pending_token) {
$pending_user_id = get2FAUserByToken($pending_token);
if ($pending_user_id) {
// Get user email for display
$stmt = $db->prepare("SELECT email FROM users WHERE id = ?");
$stmt->execute([$pending_user_id]);
$userRow = $stmt->fetch(PDO::FETCH_ASSOC);
$pending_email = $userRow ? $userRow['email'] : '';
}
}
// Handle 2FA verification
if ($_POST && isset($_POST['verify_2fa'])) {
$code = trim($_POST['2fa_code']);
if (!$pending_user_id) {
$error_message = 'Session expired. Please login again.';
$show_2fa_form = false;
} else {
if (verify2FACode($pending_user_id, $code)) {
// Get user data and complete login
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$pending_user_id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user) {
// Create full session
createSession($user);
logAudit('LOGIN', 'users', $user['id'], null, ['2fa_verified' => true]);
// Send login alert if enabled
if (isLoginAlertEnabled()) {
sendLoginAlertEmail($user['email'], $user['first_name']);
}
header('Location: index.php');
exit();
}
} else {
// Check why it failed
$checkStmt = $db->prepare("SELECT code, expires_at > NOW() as is_valid FROM two_factor_codes WHERE user_id = ?");
$checkStmt->execute([$pending_user_id]);
$checkRow = $checkStmt->fetch(PDO::FETCH_ASSOC);
if (!$checkRow) {
$error_message = 'No verification code found. Please click "Resend Code".';
} elseif (!$checkRow['is_valid']) {
$error_message = 'Code has expired. Please click "Resend Code" to get a new one.';
} else {
$error_message = 'Invalid verification code. Please check the code in your email.';
}
$show_2fa_form = true;
}
}
}
// Handle resend 2FA code
if ($_POST && isset($_POST['resend_2fa'])) {
if ($pending_user_id) {
$stmt = $db->prepare("SELECT email, first_name FROM users WHERE id = ?");
$stmt->execute([$pending_user_id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user) {
$code = generate2FACode();
$pending_token = store2FACode($pending_user_id, $code);
$email_result = send2FAEmail($user['email'], $user['first_name'], $code);
if ($email_result === true) {
$success_message = 'A new verification code has been sent to your email.';
$pending_email = $user['email'];
} else {
$error_message = 'Failed to send verification code. Please try again.';
}
}
$show_2fa_form = true;
} else {
$error_message = 'Session expired. Please login again.';
}
}
// Handle initial login
if ($_POST && isset($_POST['login']) && !isset($_POST['verify_2fa']) && !isset($_POST['resend_2fa'])) {
$username_or_email = sanitizeInput($_POST['login']);
$password = $_POST['password'];
if (empty($username_or_email) || empty($password)) {
$error_message = 'Please enter both username/email and password.';
} else {
$user = authenticate($username_or_email, $password);
if ($user) {
// Check if 2FA is enabled
if (is2FAEnabled()) {
// Generate and send 2FA code
$code = generate2FACode();
$pending_token = store2FACode($user['id'], $code);
$email_result = send2FAEmail($user['email'], $user['first_name'], $code);
if ($email_result === true) {
$pending_email = $user['email'];
$show_2fa_form = true;
$success_message = 'A verification code has been sent to your email address.';
} else {
// If email fails, log in anyway but log the issue
createSession($user);
logAudit('LOGIN', 'users', $user['id'], null, ['2fa_email_failed' => true]);
if (isLoginAlertEnabled()) {
sendLoginAlertEmail($user['email'], $user['first_name']);
}
header('Location: index.php');
exit();
}
} else {
// No 2FA, proceed with normal login
createSession($user);
logAudit('LOGIN', 'users', $user['id']);
// Send login alert if enabled
if (isLoginAlertEnabled()) {
sendLoginAlertEmail($user['email'], $user['first_name']);
}
header('Location: index.php');
exit();
}
} else {
$error_message = 'Invalid username/email or password.';
logAudit('FAILED_LOGIN', 'users', null, null, ['login_attempt' => $username_or_email]);
}
}
}
// Check if we have a pending 2FA verification
if ($pending_user_id && $pending_token) {
$show_2fa_form = true;
}
$site_title = getSetting('site_title', 'COP Madina Area Reports');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - <?php echo htmlspecialchars($site_title); ?></title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
'cop-blue': '#1e40af',
'cop-light-blue': '#3b82f6',
'cop-gray': '#6b7280',
}
}
}
}
</script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.glass-effect {
backdrop-filter: blur(16px) saturate(180%);
-webkit-backdrop-filter: blur(16px) saturate(180%);
background-color: rgba(255, 255, 255, 0.75);
border: 1px solid rgba(209, 213, 219, 0.3);
}
.login-card {
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
</style>
</head>
<body class="gradient-bg min-h-screen flex items-center justify-center p-4">
<div class="w-full max-w-md mx-auto">
<!-- Logo and Title -->
<div class="text-center mb-8">
<div class="mx-auto w-20 h-20 bg-white rounded-full flex items-center justify-center mb-4 shadow-lg">
<i class="fas fa-church text-3xl text-cop-blue"></i>
</div>
<h1 class="text-3xl font-bold text-white mb-2"><?php echo htmlspecialchars($site_title); ?></h1>
<p class="text-blue-100">Data Entry & Report Generation Platform</p>
</div>
<!-- Login Form -->
<div class="glass-effect rounded-2xl p-8 login-card">
<div class="text-center mb-6">
<h2 class="text-2xl font-semibold text-gray-800">Welcome Back</h2>
<p class="text-gray-600 mt-2">Please sign in to your account</p>
</div>
<?php if ($error_message): ?>
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-lg mb-6">
<div class="flex items-center">
<i class="fas fa-exclamation-circle mr-2"></i>
<span><?php echo htmlspecialchars($error_message); ?></span>
</div>
</div>
<?php endif; ?>
<?php if ($success_message): ?>
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded-lg mb-6">
<div class="flex items-center">
<i class="fas fa-check-circle mr-2"></i>
<span><?php echo htmlspecialchars($success_message); ?></span>
</div>
</div>
<?php endif; ?>
<?php if ($show_2fa_form): ?>
<!-- 2FA Verification Form -->
<div class="text-center mb-4">
<div class="w-16 h-16 bg-cop-blue/10 rounded-full flex items-center justify-center mx-auto mb-4">
<i class="fas fa-shield-alt text-2xl text-cop-blue"></i>
</div>
<p class="text-gray-600 text-sm">
Enter the 6-digit code sent to<br>
<strong><?php echo htmlspecialchars($pending_email); ?></strong>
</p>
</div>
<form method="POST" action="" class="space-y-6">
<input type="hidden" name="pending_token" value="<?php echo htmlspecialchars($pending_token); ?>">
<div>
<label for="2fa_code" class="block text-sm font-medium text-gray-700 mb-2">
<i class="fas fa-key mr-2"></i>Verification Code
</label>
<input type="text"
id="2fa_code"
name="2fa_code"
required
maxlength="6"
pattern="[0-9]{6}"
autocomplete="one-time-code"
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-cop-blue focus:border-transparent transition duration-200 bg-white/80 text-center text-2xl tracking-widest font-mono"
placeholder="000000">
</div>
<button type="submit"
name="verify_2fa"
class="w-full bg-gradient-to-r from-cop-blue to-cop-light-blue text-white py-3 px-4 rounded-lg font-medium hover:from-cop-light-blue hover:to-cop-blue transition duration-300 transform hover:scale-105 shadow-lg">
<i class="fas fa-check mr-2"></i>Verify Code
</button>
</form>
<div class="mt-4 flex justify-between items-center">
<form method="POST" action="">
<input type="hidden" name="pending_token" value="<?php echo htmlspecialchars($pending_token); ?>">
<button type="submit"
name="resend_2fa"
class="text-sm text-cop-blue hover:text-cop-light-blue transition duration-200">
<i class="fas fa-redo mr-1"></i>Resend Code
</button>
</form>
<a href="login.php?cancel=1"
class="text-sm text-gray-500 hover:text-gray-700 transition duration-200">
<i class="fas fa-arrow-left mr-1"></i>Back to Login
</a>
</div>
<?php else: ?>
<!-- Normal Login Form -->
<form method="POST" action="" class="space-y-6">
<div>
<label for="login" class="block text-sm font-medium text-gray-700 mb-2">
<i class="fas fa-user mr-2"></i>Username or Email
</label>
<input type="text"
id="login"
name="login"
required
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-cop-blue focus:border-transparent transition duration-200 bg-white/80"
placeholder="Enter your username or email"
value="<?php echo isset($_POST['login']) ? htmlspecialchars($_POST['login']) : ''; ?>">
</div>
<div>
<label for="password" class="block text-sm font-medium text-gray-700 mb-2">
<i class="fas fa-lock mr-2"></i>Password
</label>
<div class="relative">
<input type="password"
id="password"
name="password"
required
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-cop-blue focus:border-transparent transition duration-200 bg-white/80 pr-12"
placeholder="Enter your password">
<button type="button"
onclick="togglePassword()"
class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500 hover:text-gray-700">
<i id="password-icon" class="fas fa-eye"></i>
</button>
</div>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center">
<input type="checkbox"
id="remember"
name="remember"
class="h-4 w-4 text-cop-blue focus:ring-cop-blue border-gray-300 rounded">
<label for="remember" class="ml-2 block text-sm text-gray-700">
Remember me
</label>
</div>
<a href="#" class="text-sm text-cop-blue hover:text-cop-light-blue transition duration-200">
Forgot password?
</a>
</div>
<button type="submit"
class="w-full bg-gradient-to-r from-cop-blue to-cop-light-blue text-white py-3 px-4 rounded-lg font-medium hover:from-cop-light-blue hover:to-cop-blue transition duration-300 transform hover:scale-105 shadow-lg">
<i class="fas fa-sign-in-alt mr-2"></i>Sign In
</button>
</form>
<?php endif; ?>
<!-- Additional Info -->
<div class="mt-8 pt-6 border-t border-gray-200">
<div class="text-center text-sm text-gray-600">
<p>Need access? Contact your administrator</p>
<div class="mt-4 flex justify-center space-x-4">
<div class="flex items-center text-xs text-gray-500">
<i class="fas fa-shield-alt mr-1"></i>
Secure Login
</div>
<div class="flex items-center text-xs text-gray-500">
<i class="fas fa-clock mr-1"></i>
24/7 Access
</div>
</div>
</div>
</div>
</div>
<!-- Footer -->
<div class="text-center mt-8 text-white/80">
<p class="text-sm">
<?php echo htmlspecialchars(getSetting('footer_title', '© 2024 The Church of Pentecost - Madina Area')); ?>
</p>
<p class="text-xs mt-2">Version <?php echo APP_VERSION; ?></p>
</div>
</div>
<script>
function togglePassword() {
const passwordInput = document.getElementById('password');
const passwordIcon = document.getElementById('password-icon');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
passwordIcon.className = 'fas fa-eye-slash';
} else {
passwordInput.type = 'password';
passwordIcon.className = 'fas fa-eye';
}
}
// Auto-hide error messages after 5 seconds
setTimeout(function() {
const errorDiv = document.querySelector('.bg-red-100');
if (errorDiv) {
errorDiv.style.transition = 'opacity 0.5s';
errorDiv.style.opacity = '0';
setTimeout(() => errorDiv.remove(), 500);
}
}, 5000);
// Form validation
document.querySelector('form').addEventListener('submit', function(e) {
const login = document.getElementById('login').value.trim();
const password = document.getElementById('password').value;
if (!login || !password) {
e.preventDefault();
alert('Please fill in all fields');
}
});
</script>
</body>
</html>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists