mirror of
https://github.com/myronblair/epic-download
synced 2026-07-28 04:52:29 -05:00
auto-commit for f3b04df9-f563-4cb2-9a0a-69756e09f838
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* Authentication Endpoints
|
||||
*/
|
||||
|
||||
$db = Database::getInstance()->getConnection();
|
||||
|
||||
// Login endpoint
|
||||
if ($method === 'POST' && $id === 'login') {
|
||||
$input = getJsonInput();
|
||||
|
||||
// Validate input
|
||||
$errors = validateRequired($input, ['email', 'password']);
|
||||
if (!empty($errors)) {
|
||||
jsonResponse(['error' => implode(', ', $errors)], 400);
|
||||
}
|
||||
|
||||
$email = sanitizeString($input['email']);
|
||||
$password = $input['password'];
|
||||
|
||||
// Find admin user
|
||||
$stmt = $db->prepare("SELECT * FROM admin_users WHERE email = ?");
|
||||
$stmt->execute([$email]);
|
||||
$admin = $stmt->fetch();
|
||||
|
||||
if (!$admin) {
|
||||
jsonResponse(['error' => 'Invalid email or password'], 401);
|
||||
}
|
||||
|
||||
// Verify password
|
||||
if (!password_verify($password, $admin['password_hash'])) {
|
||||
jsonResponse(['error' => 'Invalid email or password'], 401);
|
||||
}
|
||||
|
||||
// Create token
|
||||
$token = JWT::createToken($email);
|
||||
|
||||
jsonResponse([
|
||||
'access_token' => $token,
|
||||
'token_type' => 'bearer',
|
||||
'email' => $email
|
||||
]);
|
||||
}
|
||||
|
||||
// Verify token endpoint
|
||||
if ($method === 'POST' && $id === 'verify') {
|
||||
$payload = requireAuth();
|
||||
|
||||
jsonResponse([
|
||||
'valid' => true,
|
||||
'email' => $payload['sub']
|
||||
]);
|
||||
}
|
||||
|
||||
jsonResponse(['error' => 'Invalid auth endpoint'], 404);
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Contact Form Endpoint
|
||||
*/
|
||||
|
||||
$db = Database::getInstance()->getConnection();
|
||||
|
||||
if ($method === 'POST') {
|
||||
$input = getJsonInput();
|
||||
|
||||
$errors = validateRequired($input, ['name', 'email', 'message']);
|
||||
if (!empty($errors)) {
|
||||
jsonResponse(['error' => implode(', ', $errors)], 400);
|
||||
}
|
||||
|
||||
if (!isValidEmail($input['email'])) {
|
||||
jsonResponse(['error' => 'Invalid email address'], 400);
|
||||
}
|
||||
|
||||
$id = generateUuid();
|
||||
|
||||
$stmt = $db->prepare("
|
||||
INSERT INTO contacts (id, name, email, message, created_at)
|
||||
VALUES (?, ?, ?, ?, NOW())
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
$id,
|
||||
sanitizeString($input['name']),
|
||||
sanitizeString($input['email']),
|
||||
$input['message']
|
||||
]);
|
||||
|
||||
jsonResponse(['message' => 'Contact form submitted successfully']);
|
||||
}
|
||||
|
||||
jsonResponse(['error' => 'Method not allowed'], 405);
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
/**
|
||||
* Destinations CRUD Endpoints
|
||||
*/
|
||||
|
||||
$db = Database::getInstance()->getConnection();
|
||||
|
||||
// GET all destinations or single destination
|
||||
if ($method === 'GET') {
|
||||
if ($id) {
|
||||
// Get single destination
|
||||
$stmt = $db->prepare("SELECT * FROM destinations WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$destination = $stmt->fetch();
|
||||
|
||||
if (!$destination) {
|
||||
jsonResponse(['error' => 'Destination not found'], 404);
|
||||
}
|
||||
|
||||
jsonResponse($destination);
|
||||
} else {
|
||||
// Get all destinations with optional filtering
|
||||
$category = isset($_GET['category']) ? sanitizeString($_GET['category']) : null;
|
||||
$search = isset($_GET['search']) ? sanitizeString($_GET['search']) : null;
|
||||
|
||||
$sql = "SELECT * FROM destinations WHERE 1=1";
|
||||
$params = [];
|
||||
|
||||
if ($category && $category !== 'All') {
|
||||
$sql .= " AND category = ?";
|
||||
$params[] = $category;
|
||||
}
|
||||
|
||||
if ($search) {
|
||||
$sql .= " AND (name LIKE ? OR location LIKE ?)";
|
||||
$params[] = "%$search%";
|
||||
$params[] = "%$search%";
|
||||
}
|
||||
|
||||
$sql .= " LIMIT 100";
|
||||
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$destinations = $stmt->fetchAll();
|
||||
|
||||
jsonResponse($destinations);
|
||||
}
|
||||
}
|
||||
|
||||
// POST create new destination (admin only)
|
||||
if ($method === 'POST') {
|
||||
requireAuth();
|
||||
|
||||
$input = getJsonInput();
|
||||
|
||||
$errors = validateRequired($input, ['name', 'location', 'description', 'image', 'category', 'rating', 'price']);
|
||||
if (!empty($errors)) {
|
||||
jsonResponse(['error' => implode(', ', $errors)], 400);
|
||||
}
|
||||
|
||||
$id = generateUuid();
|
||||
$stmt = $db->prepare("
|
||||
INSERT INTO destinations (id, name, location, description, image, category, rating, price, currency, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
$id,
|
||||
sanitizeString($input['name']),
|
||||
sanitizeString($input['location']),
|
||||
$input['description'],
|
||||
$input['image'],
|
||||
$input['category'],
|
||||
$input['rating'],
|
||||
$input['price'],
|
||||
isset($input['currency']) ? $input['currency'] : 'USD'
|
||||
]);
|
||||
|
||||
// Fetch created destination
|
||||
$stmt = $db->prepare("SELECT * FROM destinations WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$destination = $stmt->fetch();
|
||||
|
||||
jsonResponse($destination, 201);
|
||||
}
|
||||
|
||||
// PUT update destination (admin only)
|
||||
if ($method === 'PUT' && $id) {
|
||||
requireAuth();
|
||||
|
||||
$input = getJsonInput();
|
||||
|
||||
// Build update query dynamically
|
||||
$updates = [];
|
||||
$params = [];
|
||||
|
||||
$allowedFields = ['name', 'location', 'description', 'image', 'category', 'rating', 'price', 'currency'];
|
||||
|
||||
foreach ($allowedFields as $field) {
|
||||
if (isset($input[$field])) {
|
||||
$updates[] = "$field = ?";
|
||||
$params[] = $field === 'description' ? $input[$field] : sanitizeString($input[$field]);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($updates)) {
|
||||
jsonResponse(['error' => 'No fields to update'], 400);
|
||||
}
|
||||
|
||||
$params[] = $id;
|
||||
|
||||
$sql = "UPDATE destinations SET " . implode(', ', $updates) . " WHERE id = ?";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
// Fetch updated destination
|
||||
$stmt = $db->prepare("SELECT * FROM destinations WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$destination = $stmt->fetch();
|
||||
|
||||
jsonResponse($destination);
|
||||
}
|
||||
|
||||
// DELETE destination (admin only)
|
||||
if ($method === 'DELETE' && $id) {
|
||||
requireAuth();
|
||||
|
||||
// Delete destination (cascades to specials)
|
||||
$stmt = $db->prepare("DELETE FROM destinations WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
|
||||
if ($stmt->rowCount() === 0) {
|
||||
jsonResponse(['error' => 'Destination not found'], 404);
|
||||
}
|
||||
|
||||
jsonResponse(['message' => 'Destination deleted successfully']);
|
||||
}
|
||||
|
||||
jsonResponse(['error' => 'Invalid destinations endpoint'], 404);
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Newsletter Subscription Endpoint
|
||||
*/
|
||||
|
||||
$db = Database::getInstance()->getConnection();
|
||||
|
||||
if ($method === 'POST' && $id === 'subscribe') {
|
||||
$input = getJsonInput();
|
||||
|
||||
if (!isset($input['email']) || !isValidEmail($input['email'])) {
|
||||
jsonResponse(['error' => 'Valid email address is required'], 400);
|
||||
}
|
||||
|
||||
$email = sanitizeString($input['email']);
|
||||
|
||||
// Check if already subscribed
|
||||
$stmt = $db->prepare("SELECT id FROM newsletter_subscribers WHERE email = ?");
|
||||
$stmt->execute([$email]);
|
||||
|
||||
if ($stmt->fetch()) {
|
||||
jsonResponse(['message' => 'Email already subscribed']);
|
||||
}
|
||||
|
||||
$id = generateUuid();
|
||||
|
||||
$stmt = $db->prepare("
|
||||
INSERT INTO newsletter_subscribers (id, email, subscribed_at)
|
||||
VALUES (?, ?, NOW())
|
||||
");
|
||||
|
||||
$stmt->execute([$id, $email]);
|
||||
|
||||
jsonResponse(['message' => 'Successfully subscribed to newsletter']);
|
||||
}
|
||||
|
||||
jsonResponse(['error' => 'Invalid newsletter endpoint'], 404);
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
/**
|
||||
* Weekly Specials CRUD Endpoints
|
||||
*/
|
||||
|
||||
$db = Database::getInstance()->getConnection();
|
||||
|
||||
// GET all specials
|
||||
if ($method === 'GET' && !$id) {
|
||||
$stmt = $db->query("SELECT * FROM specials LIMIT 100");
|
||||
$specials = $stmt->fetchAll();
|
||||
|
||||
// Parse JSON highlights
|
||||
foreach ($specials as &$special) {
|
||||
$special['highlights'] = json_decode($special['highlights'], true);
|
||||
}
|
||||
|
||||
jsonResponse($specials);
|
||||
}
|
||||
|
||||
// POST create special (admin only)
|
||||
if ($method === 'POST') {
|
||||
requireAuth();
|
||||
|
||||
$input = getJsonInput();
|
||||
|
||||
$errors = validateRequired($input, ['destination_id', 'discount', 'end_date', 'highlights']);
|
||||
if (!empty($errors)) {
|
||||
jsonResponse(['error' => implode(', ', $errors)], 400);
|
||||
}
|
||||
|
||||
// Check if destination exists
|
||||
$stmt = $db->prepare("SELECT id FROM destinations WHERE id = ?");
|
||||
$stmt->execute([$input['destination_id']]);
|
||||
if (!$stmt->fetch()) {
|
||||
jsonResponse(['error' => 'Destination not found'], 404);
|
||||
}
|
||||
|
||||
// Check if special already exists for this destination
|
||||
$stmt = $db->prepare("SELECT id FROM specials WHERE destination_id = ?");
|
||||
$stmt->execute([$input['destination_id']]);
|
||||
if ($stmt->fetch()) {
|
||||
jsonResponse(['error' => 'Special already exists for this destination'], 400);
|
||||
}
|
||||
|
||||
$id = generateUuid();
|
||||
$highlights = json_encode($input['highlights']);
|
||||
|
||||
$stmt = $db->prepare("
|
||||
INSERT INTO specials (id, destination_id, discount, end_date, highlights, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, NOW())
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
$id,
|
||||
$input['destination_id'],
|
||||
$input['discount'],
|
||||
$input['end_date'],
|
||||
$highlights
|
||||
]);
|
||||
|
||||
// Fetch created special
|
||||
$stmt = $db->prepare("SELECT * FROM specials WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$special = $stmt->fetch();
|
||||
$special['highlights'] = json_decode($special['highlights'], true);
|
||||
|
||||
jsonResponse($special, 201);
|
||||
}
|
||||
|
||||
// PUT update special (admin only)
|
||||
if ($method === 'PUT' && $id) {
|
||||
requireAuth();
|
||||
|
||||
$input = getJsonInput();
|
||||
|
||||
$updates = [];
|
||||
$params = [];
|
||||
|
||||
if (isset($input['discount'])) {
|
||||
$updates[] = "discount = ?";
|
||||
$params[] = $input['discount'];
|
||||
}
|
||||
|
||||
if (isset($input['end_date'])) {
|
||||
$updates[] = "end_date = ?";
|
||||
$params[] = $input['end_date'];
|
||||
}
|
||||
|
||||
if (isset($input['highlights'])) {
|
||||
$updates[] = "highlights = ?";
|
||||
$params[] = json_encode($input['highlights']);
|
||||
}
|
||||
|
||||
if (empty($updates)) {
|
||||
jsonResponse(['error' => 'No fields to update'], 400);
|
||||
}
|
||||
|
||||
$params[] = $id;
|
||||
|
||||
$sql = "UPDATE specials SET " . implode(', ', $updates) . " WHERE id = ?";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
// Fetch updated special
|
||||
$stmt = $db->prepare("SELECT * FROM specials WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$special = $stmt->fetch();
|
||||
$special['highlights'] = json_decode($special['highlights'], true);
|
||||
|
||||
jsonResponse($special);
|
||||
}
|
||||
|
||||
// DELETE special by destination_id (admin only)
|
||||
if ($method === 'DELETE' && isset($pathParts[1]) && $pathParts[1] === 'destination' && isset($pathParts[2])) {
|
||||
requireAuth();
|
||||
|
||||
$destinationId = $pathParts[2];
|
||||
|
||||
$stmt = $db->prepare("DELETE FROM specials WHERE destination_id = ?");
|
||||
$stmt->execute([$destinationId]);
|
||||
|
||||
if ($stmt->rowCount() === 0) {
|
||||
jsonResponse(['error' => 'Special not found for this destination'], 404);
|
||||
}
|
||||
|
||||
jsonResponse(['message' => 'Special removed successfully']);
|
||||
}
|
||||
|
||||
jsonResponse(['error' => 'Invalid specials endpoint'], 404);
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/**
|
||||
* Image Upload Endpoint
|
||||
*/
|
||||
|
||||
requireAuth(); // Only authenticated users can upload
|
||||
|
||||
if ($method === 'POST' && $id === 'image') {
|
||||
if (!isset($_FILES['file'])) {
|
||||
jsonResponse(['error' => 'No file uploaded'], 400);
|
||||
}
|
||||
|
||||
$file = $_FILES['file'];
|
||||
|
||||
// Validate file
|
||||
if ($file['error'] !== UPLOAD_ERR_OK) {
|
||||
jsonResponse(['error' => 'File upload failed'], 400);
|
||||
}
|
||||
|
||||
// Check file size
|
||||
if ($file['size'] > MAX_UPLOAD_SIZE) {
|
||||
jsonResponse(['error' => 'File too large. Maximum size is 5MB'], 400);
|
||||
}
|
||||
|
||||
// Check file type
|
||||
$allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp'];
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mimeType = finfo_file($finfo, $file['tmp_name']);
|
||||
finfo_close($finfo);
|
||||
|
||||
if (!in_array($mimeType, $allowedTypes)) {
|
||||
jsonResponse(['error' => 'Invalid file type. Only JPG, PNG, and WebP allowed'], 400);
|
||||
}
|
||||
|
||||
// Generate unique filename
|
||||
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||
$filename = generateUuid() . '.' . $extension;
|
||||
$filepath = UPLOAD_DIR . $filename;
|
||||
|
||||
// Move uploaded file
|
||||
if (!move_uploaded_file($file['tmp_name'], $filepath)) {
|
||||
jsonResponse(['error' => 'Failed to save file'], 500);
|
||||
}
|
||||
|
||||
$fileUrl = '/api/uploads/' . $filename;
|
||||
|
||||
jsonResponse([
|
||||
'url' => $fileUrl,
|
||||
'filename' => $filename
|
||||
]);
|
||||
}
|
||||
|
||||
// Serve uploaded images
|
||||
if ($method === 'GET' && isset($pathParts[1]) && $pathParts[1] === 'uploads' && isset($pathParts[2])) {
|
||||
$filename = basename($pathParts[2]);
|
||||
$filepath = UPLOAD_DIR . $filename;
|
||||
|
||||
if (!file_exists($filepath)) {
|
||||
jsonResponse(['error' => 'Image not found'], 404);
|
||||
}
|
||||
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mimeType = finfo_file($finfo, $filepath);
|
||||
finfo_close($finfo);
|
||||
|
||||
header('Content-Type: ' . $mimeType);
|
||||
header('Content-Length: ' . filesize($filepath));
|
||||
readfile($filepath);
|
||||
exit;
|
||||
}
|
||||
|
||||
jsonResponse(['error' => 'Invalid upload endpoint'], 404);
|
||||
Reference in New Issue
Block a user