Enforce ticket visibility on attachment and update endpoints

- delete_attachment.php: check canUserAccessTicket() before allowing deletion; return 404 (not 403) for inaccessible tickets to prevent existence leakage
- upload_attachment.php: verify ticket access on both GET (list) and POST (upload) before processing
- update_ticket.php: pass currentUser to controller; add canUserAccessTicket() check before permission check; return 404 for inaccessible tickets instead of leaking existence via 403

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-20 21:42:47 -04:00
parent 164c2d231a
commit 84cc023bc4
3 changed files with 43 additions and 4 deletions

View File

@@ -59,14 +59,16 @@ try {
private $workflowModel;
private $userId;
private $isAdmin;
private $currentUser;
public function __construct($conn, $userId = null, $isAdmin = false) {
public function __construct($conn, $userId = null, $isAdmin = false, $currentUser = []) {
$this->ticketModel = new TicketModel($conn);
$this->commentModel = new CommentModel($conn);
$this->auditLog = new AuditLogModel($conn);
$this->workflowModel = new WorkflowModel($conn);
$this->userId = $userId;
$this->isAdmin = $isAdmin;
$this->currentUser = $currentUser;
}
public function update($id, $data) {
@@ -79,6 +81,15 @@ try {
];
}
// Visibility check: return 404 for tickets the user cannot access
if (!$this->ticketModel->canUserAccessTicket($currentTicket, $this->currentUser)) {
return [
'success' => false,
'error' => 'Ticket not found',
'http_status' => 404
];
}
// Authorization: admins can edit any ticket; others only their own or assigned
if (!$this->isAdmin
&& $currentTicket['created_by'] != $this->userId
@@ -206,7 +217,7 @@ try {
$ticketId = (int)$data['ticket_id'];
// Initialize controller
$controller = new ApiTicketController($conn, $userId, $isAdmin);
$controller = new ApiTicketController($conn, $userId, $isAdmin, $currentUser);
// Update ticket
$result = $controller->update($ticketId, $data);
@@ -215,6 +226,10 @@ try {
ob_end_clean();
// Return response
if (!empty($result['http_status'])) {
http_response_code($result['http_status']);
unset($result['http_status']);
}
header('Content-Type: application/json');
echo json_encode($result);