Files
tinker_tickets/api/manage_templates.php
Jared Vititoe 7575d6a277 Add performance, security, and reliability improvements
- Consolidate all 20 API files to use centralized Database helper
- Add optimistic locking to ticket updates to prevent concurrent conflicts
- Add caching to StatsModel (60s TTL) for dashboard performance
- Add health check endpoint (api/health.php) for monitoring
- Improve rate limit cleanup with cron script and efficient DirectoryIterator
- Enable rate limit response headers (X-RateLimit-*)
- Add audit logging for workflow transitions
- Log Discord webhook failures instead of silencing
- Fix visibility check on export_tickets.php
- Add database migration system with performance indexes
- Fix cron recurring tickets to use assignTicket method

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:39:13 -05:00

145 lines
5.1 KiB
PHP

<?php
/**
* Template Management API
* CRUD operations for ticket_templates table
*/
ini_set('display_errors', 0);
error_reporting(E_ALL);
require_once dirname(__DIR__) . '/middleware/RateLimitMiddleware.php';
RateLimitMiddleware::apply('api');
try {
require_once dirname(__DIR__) . '/config/config.php';
require_once dirname(__DIR__) . '/helpers/Database.php';
// Check authentication
session_start();
if (!isset($_SESSION['user']) || !isset($_SESSION['user']['user_id'])) {
http_response_code(401);
echo json_encode(['success' => false, 'error' => 'Authentication required']);
exit;
}
// Check admin privileges for write operations
if ($_SERVER['REQUEST_METHOD'] !== 'GET' && !$_SESSION['user']['is_admin']) {
http_response_code(403);
echo json_encode(['success' => false, 'error' => 'Admin privileges required']);
exit;
}
// CSRF Protection for write operations
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
require_once dirname(__DIR__) . '/middleware/CsrfMiddleware.php';
$csrfToken = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
if (!CsrfMiddleware::validateToken($csrfToken)) {
http_response_code(403);
echo json_encode(['success' => false, 'error' => 'Invalid CSRF token']);
exit;
}
}
// Use centralized database connection
$conn = Database::getConnection();
header('Content-Type: application/json');
$method = $_SERVER['REQUEST_METHOD'];
$id = isset($_GET['id']) ? (int)$_GET['id'] : null;
switch ($method) {
case 'GET':
if ($id) {
// Get single template
$stmt = $conn->prepare("SELECT * FROM ticket_templates WHERE template_id = ?");
$stmt->bind_param('i', $id);
$stmt->execute();
$result = $stmt->get_result();
$template = $result->fetch_assoc();
$stmt->close();
echo json_encode(['success' => true, 'template' => $template]);
} else {
// Get all templates
$result = $conn->query("SELECT * FROM ticket_templates ORDER BY template_name");
$templates = [];
while ($row = $result->fetch_assoc()) {
$templates[] = $row;
}
echo json_encode(['success' => true, 'templates' => $templates]);
}
break;
case 'POST':
$data = json_decode(file_get_contents('php://input'), true);
$stmt = $conn->prepare("INSERT INTO ticket_templates
(template_name, title_template, description_template, category, type, default_priority, is_active)
VALUES (?, ?, ?, ?, ?, ?, ?)");
$stmt->bind_param('sssssii',
$data['template_name'],
$data['title_template'],
$data['description_template'],
$data['category'],
$data['type'],
$data['default_priority'] ?? 4,
$data['is_active'] ?? 1
);
if ($stmt->execute()) {
echo json_encode(['success' => true, 'template_id' => $conn->insert_id]);
} else {
echo json_encode(['success' => false, 'error' => $stmt->error]);
}
$stmt->close();
break;
case 'PUT':
if (!$id) {
echo json_encode(['success' => false, 'error' => 'ID required']);
exit;
}
$data = json_decode(file_get_contents('php://input'), true);
$stmt = $conn->prepare("UPDATE ticket_templates SET
template_name = ?, title_template = ?, description_template = ?,
category = ?, type = ?, default_priority = ?, is_active = ?
WHERE template_id = ?");
$stmt->bind_param('sssssiii',
$data['template_name'],
$data['title_template'],
$data['description_template'],
$data['category'],
$data['type'],
$data['default_priority'] ?? 4,
$data['is_active'] ?? 1,
$id
);
echo json_encode(['success' => $stmt->execute()]);
$stmt->close();
break;
case 'DELETE':
if (!$id) {
echo json_encode(['success' => false, 'error' => 'ID required']);
exit;
}
$stmt = $conn->prepare("DELETE FROM ticket_templates WHERE template_id = ?");
$stmt->bind_param('i', $id);
echo json_encode(['success' => $stmt->execute()]);
$stmt->close();
break;
default:
http_response_code(405);
echo json_encode(['success' => false, 'error' => 'Method not allowed']);
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}