Security hardening and performance improvements
- Add visibility check to attachment downloads (prevents unauthorized access) - Fix ticket ID collision with uniqueness verification loop - Harden CSP: replace unsafe-inline with nonce-based script execution - Add IP-based rate limiting (supplements session-based) - Add visibility checks to bulk operations - Validate internal visibility requires groups - Optimize user activity query (JOINs vs subqueries) - Update documentation with design decisions and security info Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
41
index.php
41
index.php
@@ -307,14 +307,45 @@ switch (true) {
|
||||
'to' => $_GET['date_to'] ?? date('Y-m-d')
|
||||
];
|
||||
|
||||
// Optimized query using LEFT JOINs with aggregated subqueries instead of correlated subqueries
|
||||
// This eliminates N+1 query pattern and runs much faster with many users
|
||||
$sql = "SELECT
|
||||
u.user_id, u.username, u.display_name, u.is_admin,
|
||||
(SELECT COUNT(*) FROM tickets t WHERE t.created_by = u.user_id AND DATE(t.created_at) BETWEEN ? AND ?) as tickets_created,
|
||||
(SELECT COUNT(*) FROM tickets t WHERE t.assigned_to = u.user_id AND t.status = 'Closed' AND DATE(t.updated_at) BETWEEN ? AND ?) as tickets_resolved,
|
||||
(SELECT COUNT(*) FROM ticket_comments tc WHERE tc.user_id = u.user_id AND DATE(tc.created_at) BETWEEN ? AND ?) as comments_added,
|
||||
(SELECT COUNT(*) FROM tickets t WHERE t.assigned_to = u.user_id AND DATE(t.created_at) BETWEEN ? AND ?) as tickets_assigned,
|
||||
(SELECT MAX(al.created_at) FROM audit_log al WHERE al.user_id = u.user_id) as last_activity
|
||||
COALESCE(tc.tickets_created, 0) as tickets_created,
|
||||
COALESCE(tr.tickets_resolved, 0) as tickets_resolved,
|
||||
COALESCE(cm.comments_added, 0) as comments_added,
|
||||
COALESCE(ta.tickets_assigned, 0) as tickets_assigned,
|
||||
al.last_activity
|
||||
FROM users u
|
||||
LEFT JOIN (
|
||||
SELECT created_by, COUNT(*) as tickets_created
|
||||
FROM tickets
|
||||
WHERE DATE(created_at) BETWEEN ? AND ?
|
||||
GROUP BY created_by
|
||||
) tc ON u.user_id = tc.created_by
|
||||
LEFT JOIN (
|
||||
SELECT assigned_to, COUNT(*) as tickets_resolved
|
||||
FROM tickets
|
||||
WHERE status = 'Closed' AND DATE(updated_at) BETWEEN ? AND ?
|
||||
GROUP BY assigned_to
|
||||
) tr ON u.user_id = tr.assigned_to
|
||||
LEFT JOIN (
|
||||
SELECT user_id, COUNT(*) as comments_added
|
||||
FROM ticket_comments
|
||||
WHERE DATE(created_at) BETWEEN ? AND ?
|
||||
GROUP BY user_id
|
||||
) cm ON u.user_id = cm.user_id
|
||||
LEFT JOIN (
|
||||
SELECT assigned_to, COUNT(*) as tickets_assigned
|
||||
FROM tickets
|
||||
WHERE DATE(created_at) BETWEEN ? AND ?
|
||||
GROUP BY assigned_to
|
||||
) ta ON u.user_id = ta.assigned_to
|
||||
LEFT JOIN (
|
||||
SELECT user_id, MAX(created_at) as last_activity
|
||||
FROM audit_log
|
||||
GROUP BY user_id
|
||||
) al ON u.user_id = al.user_id
|
||||
ORDER BY tickets_created DESC, tickets_resolved DESC";
|
||||
|
||||
$stmt = $conn->prepare($sql);
|
||||
|
||||
Reference in New Issue
Block a user