86 lines
3.1 KiB
PHP
86 lines
3.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require_once __DIR__ . "/../auth_helper.php";
|
|
require_login();
|
|
|
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
|
$election_id = $_POST["election_id"] ?? "";
|
|
$raw_votes = $_POST["votes"] ?? []; // Array of position_id => candidate_id (string or array)
|
|
$user = get_user();
|
|
|
|
if (!$election_id) {
|
|
die("Invalid submission.");
|
|
}
|
|
|
|
try {
|
|
$pdo = db();
|
|
$pdo->beginTransaction();
|
|
|
|
// 1. Verify election is ongoing
|
|
$eStmt = $pdo->prepare("SELECT status FROM elections WHERE id = ?");
|
|
$eStmt->execute([$election_id]);
|
|
$election = $eStmt->fetch();
|
|
if (!$election || $election["status"] !== "Ongoing") {
|
|
throw new Exception("Election is not currently ongoing.");
|
|
}
|
|
|
|
// 2. Verify user hasn't voted yet
|
|
$vCheck = $pdo->prepare("SELECT COUNT(*) FROM votes WHERE election_id = ? AND voter_id = ?");
|
|
$vCheck->execute([$election_id, $user["id"]]);
|
|
if ($vCheck->fetchColumn() > 0) {
|
|
throw new Exception("You have already cast your vote for this election.");
|
|
}
|
|
|
|
// 3. Prepare statement for inserting votes
|
|
$stmt = $pdo->prepare("INSERT INTO votes (id, election_id, position_id, candidate_id, voter_id, ip_address, user_agent) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
|
|
|
// 4. Validate each position's votes
|
|
foreach ($raw_votes as $position_id => $candidate_id) {
|
|
if (empty($candidate_id)) continue;
|
|
|
|
// Fetch position details
|
|
$pStmt = $pdo->prepare("SELECT * FROM positions WHERE id = ? AND election_id = ?");
|
|
$pStmt->execute([$position_id, $election_id]);
|
|
$pos = $pStmt->fetch();
|
|
|
|
if (!$pos) {
|
|
throw new Exception("Invalid position detected.");
|
|
}
|
|
|
|
// Validate candidate
|
|
$cStmt = $pdo->prepare("SELECT c.*, u.track FROM candidates c JOIN users u ON c.user_id = u.id WHERE c.id = ? AND c.position_id = ? AND c.approved = TRUE");
|
|
$cStmt->execute([$candidate_id, $position_id]);
|
|
$cand = $cStmt->fetch();
|
|
|
|
if (!$cand) {
|
|
throw new Exception("Invalid or unapproved candidate selected.");
|
|
}
|
|
|
|
// Check Track Specific logic
|
|
if ($pos["type"] === "Track Specific" && $cand["track"] !== $user["track"]) {
|
|
throw new Exception("Candidate track mismatch for position: " . $pos["name"]);
|
|
}
|
|
|
|
// Insert vote
|
|
$stmt->execute([
|
|
uuid(),
|
|
$election_id,
|
|
$position_id,
|
|
$candidate_id,
|
|
$user["id"],
|
|
$_SERVER["REMOTE_ADDR"] ?? "unknown",
|
|
$_SERVER["HTTP_USER_AGENT"] ?? "unknown"
|
|
]);
|
|
}
|
|
|
|
audit_log("Cast ballot", "elections", $election_id);
|
|
|
|
$pdo->commit();
|
|
header("Location: ../index.php?success=voted");
|
|
exit;
|
|
} catch (Exception $e) {
|
|
if (isset($pdo) && $pdo->inTransaction()) $pdo->rollBack();
|
|
die("Error casting vote: " . $e->getMessage());
|
|
}
|
|
}
|