Files
tinker_tickets/api/custom_fields.php
Jared Vititoe ed9c2a39d1 Fix error message disclosure in API endpoints
Replace exception getMessage() exposure with generic error messages
to prevent internal information disclosure. Errors are now logged
with full details while clients receive sanitized responses.

Affected endpoints:
- add_comment, update_comment, delete_comment
- update_ticket, export_tickets
- generate_api_key, revoke_api_key
- manage_templates, manage_workflows, manage_recurring
- custom_fields, get_users

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 18:56:29 -05:00

104 lines
3.4 KiB
PHP

<?php
/**
* Custom Fields Management API
* CRUD operations for custom field definitions
*/
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';
require_once dirname(__DIR__) . '/models/CustomFieldModel.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');
$model = new CustomFieldModel($conn);
$method = $_SERVER['REQUEST_METHOD'];
$id = isset($_GET['id']) ? (int)$_GET['id'] : null;
$category = isset($_GET['category']) ? $_GET['category'] : null;
switch ($method) {
case 'GET':
if ($id) {
$field = $model->getDefinition($id);
echo json_encode(['success' => (bool)$field, 'field' => $field]);
} else {
// Get all definitions, optionally filtered by category
$activeOnly = !isset($_GET['include_inactive']);
$fields = $model->getAllDefinitions($category, $activeOnly);
echo json_encode(['success' => true, 'fields' => $fields]);
}
break;
case 'POST':
$data = json_decode(file_get_contents('php://input'), true);
$result = $model->createDefinition($data);
echo json_encode($result);
break;
case 'PUT':
if (!$id) {
echo json_encode(['success' => false, 'error' => 'ID required']);
exit;
}
$data = json_decode(file_get_contents('php://input'), true);
$result = $model->updateDefinition($id, $data);
echo json_encode($result);
break;
case 'DELETE':
if (!$id) {
echo json_encode(['success' => false, 'error' => 'ID required']);
exit;
}
$result = $model->deleteDefinition($id);
echo json_encode($result);
break;
default:
http_response_code(405);
echo json_encode(['success' => false, 'error' => 'Method not allowed']);
}
} catch (Exception $e) {
error_log("Custom fields API error: " . $e->getMessage());
http_response_code(500);
echo json_encode(['success' => false, 'error' => 'An internal error occurred']);
}