PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.4.5
Fluent Support – Helpdesk & Customer Support Ticket System v2.4.5
2.4.5 2.4.0 2.3.2 2.3.1 2.3.0 2.2.1 2.2.0 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.4.0 1.4.1 1.4.2 1.4.5 1.4.6 1.4.7 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 All 69 releases
← All changes | app/Http/Policies/AgentTicketPolicy.php +24 -57 2.3.1 → 2.4.5 View file →
@@ -8,16 +8,21 @@
8 8
9 9 class AgentTicketPolicy extends Policy
10 10 {
11 11 /**
12 - * Default policy check: GET requests require view permission, POST/PUT/DELETE require manage permission.
12 + * Reads need view permission, writes need manage permission.
13 13 *
14 - * @param \FluentSupport\Framework\Request\Request $request
14 + * Use getMethod(), not method(). method() returns the raw REQUEST_METHOD, but
15 + * WordPress dispatches on the _method / X-HTTP-Method-Override value, so a
16 + * write could pass as a GET.
17 + *
18 + * @param \FluentSupport\Framework\Http\Request\Request $request
15 19 * @return Boolean
16 20 */
17 21 public function verifyRequest(Request $request)
18 22 {
19 - if ($request->method() === 'GET') {
23 + // @phpstan-ignore-next-line -- proxied to WP_REST_Request by Request::__call()
24 + if ($request->getMethod() === 'GET') {
20 25 $status = PermissionManager::userCan([
21 26 'fst_view_tickets',
22 27 'fst_draft_reply',
23 28 'fst_manage_own_tickets',
@@ -24,11 +29,10 @@
24 29 'fst_manage_unassigned_tickets',
25 30 'fst_manage_other_tickets'
26 31 ]);
27 32 } else {
28 - // Non-GET requests require manage permission by default.
29 - // Routes safe for draft/view-only agents have dedicated policy methods
30 - // (e.g. createResponse, createOrUpdatDraft, storeOrUpdateLabelSearch).
33 + // Unknown verbs land here too. Writes open to draft/view-only agents
34 + // have their own policy methods below.
31 35 $status = PermissionManager::canManageTickets();
32 36 }
33 37
34 38 return apply_filters('fluent_support/agent_has_access', $status, $request);
@@ -34,10 +38,9 @@
34 38 return apply_filters('fluent_support/agent_has_access', $status, $request);
35 39 }
36 40
37 41 /**
38 - * Contact search backs the Add Ticket flow, so any agent who can manage
39 - * tickets needs it to work.
42 + * Backs the Add Ticket flow.
40 43 */
41 44 public function searchContact(Request $request)
42 45 {
43 46 return PermissionManager::canManageTickets();
@@ -43,10 +46,10 @@
43 46 return PermissionManager::canManageTickets();
44 47 }
45 48
46 49 /**
47 - * Bulk actions: delete requires fst_delete_tickets plus manage permission
48 - * (mirroring deleteTicket), others require manage permission.
50 + * Same gates as the single-ticket routes. Both assign actions write agent_id,
51 + * so both need fst_assign_agents.
49 52 */
50 53 public function doBulkActions(Request $request)
51 54 {
52 55 $action = $request->getSafe('bulk_action', 'sanitize_text_field');
@@ -55,15 +58,19 @@
55 58 return PermissionManager::currentUserCan('fst_delete_tickets')
56 59 && PermissionManager::canManageTickets();
57 60 }
58 61
62 + if ($action === 'assign_agent' || $action === 'assign_agent_group') {
63 + return PermissionManager::currentUserCan('fst_assign_agents')
64 + && PermissionManager::canManageTickets();
65 + }
66 +
59 67 return PermissionManager::canManageTickets();
60 68 }
61 69
62 70 /**
63 - * Delete ticket requires explicit delete permission and manage permission.
64 - * View-only and draft agents resolve to full ticket visibility, so the
65 - * delete capability alone would let them delete any ticket.
71 + * View-only and draft agents see every ticket, so fst_delete_tickets alone
72 + * would let them delete any of them.
66 73 */
67 74 public function deleteTicket(Request $request)
68 75 {
69 76 return PermissionManager::currentUserCan('fst_delete_tickets')
@@ -70,11 +77,9 @@
70 77 && PermissionManager::canManageTickets();
71 78 }
72 79
73 80 /**
74 - * Delete an individual response: requires explicit delete permission and
75 - * manage permission, mirroring deleteTicket. Per-ticket access is enforced
76 - * in the controller via ensureCanAccessTicket().
81 + * Same gate as deleteTicket. The controller checks per-ticket access.
77 82 */
78 83 public function deleteResponse(Request $request)
79 84 {
80 85 return PermissionManager::currentUserCan('fst_delete_tickets')
@@ -81,10 +86,9 @@
81 86 && PermissionManager::canManageTickets();
82 87 }
83 88
84 89 /**
85 - * Update an individual response: requires manage permission. Author/type
86 - * and per-ticket access rules are enforced in the controller.
90 + * Author, type and per-ticket access are checked in the controller.
87 91 */
88 92 public function updateResponse(Request $request)
89 93 {
90 94 return PermissionManager::canManageTickets();
@@ -89,12 +93,8 @@
89 93 {
90 94 return PermissionManager::canManageTickets();
91 95 }
92 96
93 - /**
94 - * Creating a response: accessible to manage and draft agents.
95 - * View-only agents cannot create responses or drafts.
96 - */
97 97 public function createResponse(Request $request)
98 98 {
99 99 return PermissionManager::canManageTickets()
100 100 || PermissionManager::currentUserCan('fst_draft_reply');
@@ -99,12 +99,8 @@
99 99 return PermissionManager::canManageTickets()
100 100 || PermissionManager::currentUserCan('fst_draft_reply');
101 101 }
102 102
103 - /**
104 - * Auto-save draft: accessible to manage and draft agents.
105 - * View-only agents cannot create drafts.
106 - */
107 103 public function createOrUpdatDraft(Request $request)
108 104 {
109 105 return PermissionManager::canManageTickets()
110 106 || PermissionManager::currentUserCan('fst_draft_reply');
@@ -110,9 +106,9 @@
110 106 || PermissionManager::currentUserCan('fst_draft_reply');
111 107 }
112 108
113 109 /**
114 - * Label search save: POST endpoint accessible to any agent with ticket access.
110 + * Saved label searches are personal, so any agent with ticket access may write them.
115 111 */
116 112 public function storeOrUpdateLabelSearch(Request $request)
117 113 {
118 114 return PermissionManager::canAccessTicketRoutes();
@@ -117,67 +113,43 @@
117 113 {
118 114 return PermissionManager::canAccessTicketRoutes();
119 115 }
120 116
121 - /**
122 - * Label search delete: DELETE endpoint accessible to any agent (personal data).
123 - */
124 117 public function deleteLabelSearch(Request $request)
125 118 {
126 119 return PermissionManager::canAccessTicketRoutes();
127 120 }
128 121
129 - /**
130 - * Live activity removal: DELETE endpoint accessible to any agent (cleanup).
131 - */
132 122 public function removeLiveActivity(Request $request)
133 123 {
134 124 return PermissionManager::canAccessTicketRoutes();
135 125 }
136 126
137 - /**
138 - * Update ticket property (product, priority, etc.): requires manage ticket permission.
139 - */
140 127 public function updateTicketProperty(Request $request)
141 128 {
142 129 return PermissionManager::canManageTickets();
143 130 }
144 131
145 - /**
146 - * Add watchers to a ticket: requires manage ticket permission.
147 - */
148 132 public function addTicketWatchers(Request $request)
149 133 {
150 134 return PermissionManager::canManageTickets();
151 135 }
152 136
153 - /**
154 - * Sync watchers on a ticket: requires manage ticket permission.
155 - */
156 137 public function syncTicketWatchers(Request $request)
157 138 {
158 139 return PermissionManager::canManageTickets();
159 140 }
160 141
161 - /**
162 - * Update estimated time: requires manage ticket permission.
163 - */
164 142 public function updateEstimatedTime(Request $request)
165 143 {
166 144 return PermissionManager::canManageTickets();
167 145 }
168 146
169 - /**
170 - * Manual time commit: requires manage ticket permission.
171 - */
172 147 public function manualCommitTrack(Request $request)
173 148 {
174 149 return PermissionManager::canManageTickets();
175 150 }
176 151
177 - /**
178 - * Approve draft response: requires approve permission and ticket route access.
179 - */
180 152 public function approveDraftResponse(Request $request)
181 153 {
182 154 return PermissionManager::currentUserCan('fst_approve_draft_reply')
183 155 && PermissionManager::canAccessTicketRoutes();
@@ -182,11 +154,8 @@
182 154 return PermissionManager::currentUserCan('fst_approve_draft_reply')
183 155 && PermissionManager::canAccessTicketRoutes();
184 156 }
185 157
186 - /**
187 - * Delete draft: accessible to draft-capable agents (same as create/update draft).
188 - */
189 158 public function deleteDraft(Request $request)
190 159 {
191 160 return PermissionManager::canManageTickets()
192 161 || PermissionManager::currentUserCan('fst_draft_reply');
@@ -191,11 +160,9 @@
191 160 return PermissionManager::canManageTickets()
192 161 || PermissionManager::currentUserCan('fst_draft_reply');
193 162 }
194 163
195 - /**
196 - * FluentBot AI-assist actions: accessible to any agent with ticket access.
197 - */
164 + // FluentBot AI-assist actions.
198 165 public function generateResponse(Request $request)
199 166 {
200 167 return PermissionManager::canAccessTicketRoutes();
201 168 }