From fd777aa69096633c77524df5d1cc55286b28318c Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Tue, 8 Sep 2026 21:28:25 -0400 Subject: [PATCH] Fix visibility-group matching disagreement between filter and access check (#28) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getVisibilityFilter() (dashboard list/stats) matched via FIND_IN_SET(?, REPLACE(t.visibility_groups, ' ', '')) — stripping spaces from the column but not from the bound group name — while canUserAccessTicket() (single-ticket access) did a plain trim with no space-stripping at all. For a group name containing a space (e.g. "IT Support"), a member could open an internal ticket directly by URL but never see it in their dashboard list or stats counts. Now strips spaces from the bound parameter too, matching the column- side normalization, so both paths agree. Verified against real MariaDB: a ticket visible via canUserAccessTicket() for a space-containing group is now also matched by getVisibilityFilter()'s SQL, a wrong-group user is denied by both, and the plain no-space case is unaffected. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_015nCxwFFsy8ouMWzn56rPVP --- models/TicketModel.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/models/TicketModel.php b/models/TicketModel.php index b64c837..7e05e42 100644 --- a/models/TicketModel.php +++ b/models/TicketModel.php @@ -726,7 +726,10 @@ class TicketModel $groupConditions = []; foreach ($userGroups as $group) { $groupConditions[] = "FIND_IN_SET(?, REPLACE(t.visibility_groups, ' ', ''))"; - $params[] = $group; + // Strip spaces from the bound value too, matching the REPLACE() + // applied to the column, so a group name like "IT Support" is + // normalized the same way on both sides of the comparison. + $params[] = str_replace(' ', '', $group); $types .= 's'; } $conditions[] = "(t.visibility = 'internal' AND (" . implode(' OR ', $groupConditions) . "))";