225 lines
6.9 KiB
PHP
225 lines
6.9 KiB
PHP
<?php
|
|
session_start();
|
|
|
|
require_once __DIR__ . '/db/config.php';
|
|
|
|
// --- Remember Me Logic ---
|
|
if (!isset($_SESSION['user_id']) && isset($_COOKIE['remember_me'])) {
|
|
loginViaCookie();
|
|
}
|
|
|
|
// --- Action Routing ---
|
|
header('Content-Type: application/json');
|
|
$action = $_POST['action'] ?? $_GET['action'] ?? '';
|
|
|
|
switch ($action) {
|
|
case 'login':
|
|
handle_login();
|
|
break;
|
|
case 'logout':
|
|
handle_logout();
|
|
break;
|
|
case 'check_session':
|
|
check_session();
|
|
break;
|
|
case 'register':
|
|
handle_register();
|
|
break;
|
|
default:
|
|
echo json_encode(['success' => false, 'message' => 'Invalid action']);
|
|
break;
|
|
}
|
|
|
|
function handle_login() {
|
|
$username = $_POST['username'] ?? '';
|
|
$password = $_POST['password'] ?? '';
|
|
$remember = isset($_POST['remember']);
|
|
$demo_users = ['admin', 'guru', 'siswa'];
|
|
|
|
if (empty($username) || empty($password)) {
|
|
echo json_encode(['success' => false, 'message' => 'Username and password are required.']);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$pdo = db();
|
|
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
|
|
$stmt->execute(['username' => $username]);
|
|
$user = $stmt->fetch();
|
|
|
|
if ($user && password_verify($password, $user['password'])) {
|
|
// For demo users, we don't regenerate the session ID to allow multiple logins.
|
|
// For regular users, we do it for security.
|
|
if (!in_array($username, $demo_users)) {
|
|
session_regenerate_id(true);
|
|
}
|
|
|
|
$_SESSION['loggedin'] = true;
|
|
$_SESSION['user_id'] = $user['id'];
|
|
$_SESSION['username'] = $user['username'];
|
|
$_SESSION['role'] = $user['role'];
|
|
|
|
if ($remember) {
|
|
setRememberMeCookie($user['id']);
|
|
}
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'message' => 'Login successful!',
|
|
'user' => [
|
|
'username' => $user['username'],
|
|
'role' => $user['role']
|
|
]
|
|
]);
|
|
} else {
|
|
echo json_encode(['success' => false, 'message' => 'Invalid username or password.']);
|
|
}
|
|
} catch (PDOException $e) {
|
|
echo json_encode(['success' => false, 'message' => 'Database error: ' . $e->getMessage()]);
|
|
}
|
|
}
|
|
|
|
function handle_register() {
|
|
$username = $_POST['username'] ?? '';
|
|
$password = $_POST['password'] ?? '';
|
|
|
|
if (empty($username) || empty($password)) {
|
|
echo json_encode(['success' => false, 'message' => 'Username dan password tidak boleh kosong.']);
|
|
return;
|
|
}
|
|
|
|
if (strlen($password) < 6) {
|
|
echo json_encode(['success' => false, 'message' => 'Password minimal harus 6 karakter.']);
|
|
return;
|
|
}
|
|
|
|
if (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
|
|
echo json_encode(['success' => false, 'message' => 'Username hanya boleh berisi huruf, angka, dan underscore.']);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$pdo = db();
|
|
|
|
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = :username");
|
|
$stmt->execute(['username' => $username]);
|
|
if ($stmt->fetch()) {
|
|
echo json_encode(['success' => false, 'message' => 'Username sudah digunakan. Silakan pilih yang lain.']);
|
|
return;
|
|
}
|
|
|
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
|
$stmt = $pdo->prepare("INSERT INTO users (username, password, role) VALUES (:username, :password, 'siswa')");
|
|
$stmt->execute([
|
|
'username' => $username,
|
|
'password' => $hashed_password
|
|
]);
|
|
|
|
echo json_encode(['success' => true, 'message' => 'Registrasi berhasil! Anda akan dialihkan ke halaman login.']);
|
|
|
|
} catch (PDOException $e) {
|
|
echo json_encode(['success' => false, 'message' => 'Terjadi kesalahan pada database.']);
|
|
}
|
|
}
|
|
|
|
function handle_logout() {
|
|
if (isset($_SESSION['user_id'])) {
|
|
clearRememberMeCookie($_SESSION['user_id']);
|
|
}
|
|
session_unset();
|
|
session_destroy();
|
|
echo json_encode(['success' => true, 'message' => 'Logged out successfully.']);
|
|
}
|
|
|
|
function check_session() {
|
|
if (isset($_SESSION['user_id'])) {
|
|
echo json_encode([
|
|
'success' => true,
|
|
'loggedIn' => true,
|
|
'user' => [
|
|
'username' => $_SESSION['username'],
|
|
'role' => $_SESSION['role']
|
|
]
|
|
]);
|
|
} else {
|
|
echo json_encode(['success' => true, 'loggedIn' => false]);
|
|
}
|
|
}
|
|
|
|
// --- Remember Me Helper Functions ---
|
|
|
|
function setRememberMeCookie($userId) {
|
|
try {
|
|
$token = bin2hex(random_bytes(32));
|
|
$hashed_token = hash('sha256', $token);
|
|
|
|
$pdo = db();
|
|
$stmt = $pdo->prepare("UPDATE users SET remember_token = :token WHERE id = :id");
|
|
$stmt->execute(['token' => $hashed_token, 'id' => $userId]);
|
|
|
|
$cookie_value = $userId . ':' . $token;
|
|
$expiry = time() + (86400 * 30); // 30 days
|
|
|
|
setcookie('remember_me', $cookie_value, [
|
|
'expires' => $expiry,
|
|
'path' => '/',
|
|
'domain' => '', // current domain
|
|
'secure' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
|
|
'httponly' => true,
|
|
'samesite' => 'Lax'
|
|
]);
|
|
} catch (Exception $e) {
|
|
// Silently fail on cookie setting error
|
|
}
|
|
}
|
|
|
|
function clearRememberMeCookie($userId) {
|
|
try {
|
|
$pdo = db();
|
|
$stmt = $pdo->prepare("UPDATE users SET remember_token = NULL WHERE id = :id");
|
|
$stmt->execute(['id' => $userId]);
|
|
|
|
if (isset($_COOKIE['remember_me'])) {
|
|
unset($_COOKIE['remember_me']);
|
|
setcookie('remember_me', '', time() - 3600, '/');
|
|
}
|
|
} catch (Exception $e) {
|
|
// Silently fail
|
|
}
|
|
}
|
|
|
|
function loginViaCookie() {
|
|
$cookie = $_COOKIE['remember_me'] ?? '';
|
|
if (!$cookie) return;
|
|
|
|
$parts = explode(':', $cookie);
|
|
if (count($parts) !== 2) return;
|
|
|
|
list($userId, $token) = $parts;
|
|
if (empty($userId) || empty($token)) return;
|
|
|
|
try {
|
|
$pdo = db();
|
|
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
|
|
$stmt->execute(['id' => $userId]);
|
|
$user = $stmt->fetch();
|
|
|
|
if ($user && !empty($user['remember_token'])) {
|
|
$hashed_token_from_cookie = hash('sha256', $token);
|
|
if (hash_equals($user['remember_token'], $hashed_token_from_cookie)) {
|
|
// Log user in
|
|
session_regenerate_id(true);
|
|
$_SESSION['loggedin'] = true;
|
|
$_SESSION['user_id'] = $user['id'];
|
|
$_SESSION['username'] = $user['username'];
|
|
$_SESSION['role'] = $user['role'];
|
|
|
|
// Security: Rotate token
|
|
setRememberMeCookie($user['id']);
|
|
}
|
|
}
|
|
} catch (Exception $e) {
|
|
// Silently fail
|
|
}
|
|
}
|