"Invalid CSRF token"]); http_response_code(403); exit; } if ( !isset($_SESSION['authenticated']) || $_SESSION['authenticated'] !== true || !isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true ) { echo json_encode(["error" => "Unauthorized"]); exit; } } // Get input data from JSON. $data = json_decode(file_get_contents("php://input"), true); $newUsername = trim($data["username"] ?? ""); $newPassword = trim($data["password"] ?? ""); // In setup mode, force the new user to be admin. if ($setupMode) { $isAdmin = "1"; } else { $isAdmin = !empty($data["isAdmin"]) ? "1" : "0"; // "1" for admin, "0" for regular user. } // Validate input. if (!$newUsername || !$newPassword) { echo json_encode(["error" => "Username and password required"]); exit; } // Validate username using preg_match (allow letters, numbers, underscores, dashes, and spaces). if (!preg_match(REGEX_USER, $newUsername)) { echo json_encode(["error" => "Invalid username. Only letters, numbers, underscores, dashes, and spaces are allowed."]); exit; } // Ensure users.txt exists. if (!file_exists($usersFile)) { file_put_contents($usersFile, ''); } // Check if username already exists. $existingUsers = file($usersFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($existingUsers as $line) { list($storedUser, $storedHash, $storedRole) = explode(':', trim($line)); if ($newUsername === $storedUser) { echo json_encode(["error" => "User already exists"]); exit; } } // Hash the password. $hashedPassword = password_hash($newPassword, PASSWORD_BCRYPT); // Prepare new user line. $newUserLine = $newUsername . ":" . $hashedPassword . ":" . $isAdmin . PHP_EOL; // In setup mode, overwrite users.txt; otherwise, append to it. if ($setupMode) { file_put_contents($usersFile, $newUserLine); } else { file_put_contents($usersFile, $newUserLine, FILE_APPEND); } echo json_encode(["success" => "User added successfully"]); ?>