38458-vm/api/submit_vote.php
2026-02-15 20:43:30 +00:00

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());
}
}