Security: - Fix IDOR in delete/update comment (add ticket visibility check) - XSS defense-in-depth in DashboardView active filters - Replace innerHTML with DOM construction in toast.js - Remove redundant real_escape_string in check_duplicates - Add rate limiting to get_template, download_attachment, audit_log, saved_filters, user_preferences endpoints Bug fixes: - Session timeout now reads from config instead of hardcoded 18000 - TicketController uses $GLOBALS['config'] instead of duplicate .env parsing - Add DISCORD_WEBHOOK_URL to centralized config - Cleanup script uses hashmap for O(1) ticket ID lookups Dead code removal (~100 lines): - Remove dead getTicketComments() from TicketModel (wrong bind_param type) - Remove dead getCategories()/getTypes() from DashboardController - Remove ~80 lines dead Discord webhook code from update_ticket API Consolidation: - Create api/bootstrap.php for shared API setup (auth, CSRF, rate limit) - Convert 6 API endpoints to use bootstrap - Extract escapeHtml/getTicketIdFromUrl into shared utils.js - Batch save for user preferences (1 request instead of 7) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
54 lines
1.5 KiB
PHP
54 lines
1.5 KiB
PHP
<?php
|
|
/**
|
|
* Get Template API
|
|
* Returns a ticket template by ID
|
|
*/
|
|
|
|
require_once dirname(__DIR__) . '/middleware/RateLimitMiddleware.php';
|
|
RateLimitMiddleware::apply('api');
|
|
|
|
require_once dirname(__DIR__) . '/helpers/ErrorHandler.php';
|
|
ErrorHandler::init();
|
|
|
|
try {
|
|
session_start();
|
|
require_once dirname(__DIR__) . '/config/config.php';
|
|
require_once dirname(__DIR__) . '/helpers/Database.php';
|
|
require_once dirname(__DIR__) . '/models/TemplateModel.php';
|
|
|
|
header('Content-Type: application/json');
|
|
|
|
// Check authentication
|
|
if (!isset($_SESSION['user']) || !isset($_SESSION['user']['user_id'])) {
|
|
ErrorHandler::sendUnauthorizedError('Not authenticated');
|
|
}
|
|
|
|
// Get template ID from query parameter
|
|
$templateId = $_GET['template_id'] ?? null;
|
|
|
|
if (!$templateId || !is_numeric($templateId)) {
|
|
ErrorHandler::sendValidationError(
|
|
['template_id' => 'Valid template ID required'],
|
|
'Invalid request'
|
|
);
|
|
}
|
|
|
|
// Cast to integer for safety
|
|
$templateId = (int)$templateId;
|
|
|
|
// Get template
|
|
$conn = Database::getConnection();
|
|
$templateModel = new TemplateModel($conn);
|
|
$template = $templateModel->getTemplateById($templateId);
|
|
|
|
if ($template) {
|
|
echo json_encode(['success' => true, 'template' => $template]);
|
|
} else {
|
|
ErrorHandler::sendNotFoundError('Template not found');
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
ErrorHandler::log($e->getMessage(), E_ERROR);
|
|
ErrorHandler::sendErrorResponse('Failed to retrieve template', 500, $e);
|
|
}
|