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); $auditLog = new AuditLogModel($conn); $currentUserId = $_SESSION['user']['user_id']; $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); if (!is_array($data)) { http_response_code(400); echo json_encode(['success' => false, 'error' => 'Invalid JSON']); exit; } $result = $model->createDefinition($data); if (!empty($result['success'])) { $auditLog->log($currentUserId, 'create', 'custom_field', (string)($result['field_id'] ?? ''), [ 'field_name' => $data['field_name'] ?? null, 'field_label' => $data['field_label'] ?? null, 'field_type' => $data['field_type'] ?? null ]); } echo json_encode($result); break; case 'PUT': if (!$id) { http_response_code(400); echo json_encode(['success' => false, 'error' => 'ID required']); exit; } $data = json_decode(file_get_contents('php://input'), true); if (!is_array($data)) { http_response_code(400); echo json_encode(['success' => false, 'error' => 'Invalid JSON']); exit; } $result = $model->updateDefinition($id, $data); if (!empty($result['success'])) { $auditLog->log($currentUserId, 'update', 'custom_field', (string)$id, [ 'entity' => 'custom_field', 'field_name' => $data['field_name'] ?? null, 'field_label' => $data['field_label'] ?? null, 'field_type' => $data['field_type'] ?? null ]); } echo json_encode($result); break; case 'DELETE': if (!$id) { http_response_code(400); echo json_encode(['success' => false, 'error' => 'ID required']); exit; } $toDelete = $model->getDefinition($id); $result = $model->deleteDefinition($id); if (!empty($result['success'])) { $auditLog->log($currentUserId, 'delete', 'custom_field', (string)$id, [ 'entity' => 'custom_field', 'field_name' => $toDelete['field_name'] ?? 'unknown' ]); } 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']); }