PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.4.0
Fluent Support – Helpdesk & Customer Support Ticket System v2.4.0
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 1.5.5 All 68 releases
← All changes | app/Http/Controllers/CustomerPortalController.php +52 -25 2.3.22.4.0 View file →
@@ -2,8 +2,9 @@
2 2
3 3 namespace FluentSupport\App\Http\Controllers;
4 4
5 5 use Exception;
6 +use FluentSupport\App\Hooks\Handlers\ReCaptchaHandler;
6 7 use FluentSupport\App\Http\Requests\TicketResponseRequest;
7 8 use FluentSupport\App\Models\Product;
8 9 use FluentSupport\App\Models\Ticket;
9 10 use FluentSupport\App\Services\CustomerPortalService;
@@ -27,14 +28,9 @@
27 28 */
28 29 public function getTickets(Request $request)
29 30 {
30 31
31 - $onBehalf = $request->get('on_behalf', []);
32 - if ($onBehalf) {
33 - $onBehalf = array_map(function ($item) {
34 - return sanitize_text_field($item);
35 - }, $onBehalf);
36 - }
32 + $onBehalf = $this->sanitizeOnBehalf($request);
37 33
38 34 $userIP = $request->getIp();
39 35 $requestedStatus = $request->getSafe('filter_type', 'sanitize_text_field');
40 36 $ticketOptions = $request->getSafe([
@@ -59,9 +55,9 @@
59 55 ]
60 56 ];
61 57 }
62 58
63 - if ($customer->status !== 'active') {
59 + if (!$customer->canAccessPortal()) {
64 60 return $this->sendError([
65 61 'message' => __('Your account is not active. Please contact support.', 'fluent-support'),
66 62 'error_type' => '403'
67 63 ], 403);
@@ -113,8 +109,22 @@
113 109 * @return array | \WP_REST_Response
114 110 */
115 111 public function createTicket(Request $request)
116 112 {
113 + if (ReCaptchaHandler::isRecaptchaApplicable('ticket_form')) {
114 + $captchaResponse = $request->getSafe('g-recaptcha-response', 'sanitize_text_field');
115 + $isValidCaptcha = $captchaResponse && ReCaptchaHandler::validateRecaptcha(
116 + $captchaResponse, null, null, 'create_ticket'
117 + );
118 +
119 + if (!$isValidCaptcha) {
120 + return $this->sendError([
121 + 'message' => __('Your recaptcha is not verified', 'fluent-support'),
122 + 'error_type' => '422'
123 + ], 422);
124 + }
125 + }
126 +
117 127 $dataRules = $this->app->applyCustomFilters('custom_field_required_before_ticket_create', [
118 128 'required_fields' => [
119 129 'title' => 'required',
120 130 'content' => 'required'
@@ -168,20 +178,15 @@
168 178 $data = $this->validate($request->get(), $dataRules['required_fields'], $dataRules['error_messages']);
169 179
170 180 $data['title'] = sanitize_text_field($data['title']);
171 181 $data['content'] = wp_kses_post($data['content']);
182 + $data['custom_data'] = $customData;
172 183
173 - $onBehalf = $request->get('on_behalf', []);
184 + $onBehalf = $this->sanitizeOnBehalf($request);
174 185 $userIP = $request->getIp();
175 186
176 - if ($onBehalf) {
177 - $onBehalf = array_map(function ($item) {
178 - return sanitize_text_field($item);
179 - }, $onBehalf);
180 -
181 - if (!empty($onBehalf['last_ip_address'])) {
182 - $userIP = $onBehalf['last_ip_address'];
183 - }
187 + if (!empty($onBehalf['last_ip_address'])) {
188 + $userIP = $onBehalf['last_ip_address'];
184 189 }
185 190
186 191 try {
187 192 $customer = (new CustomerPortalService())->resolveCustomer($onBehalf, $userIP, true);
@@ -351,9 +356,9 @@
351 356 * @return array
352 357 */
353 358 public function getPublicOptions()
354 359 {
355 - $products = Product::select(['id', 'title'])->get();
360 + $products = Product::select(['id', 'title'])->orderedByTitle()->get();
356 361
357 362 return [
358 363 'support_products' => $products,
359 364 'customer_ticket_priorities' => Helper::customerTicketPriorities()
@@ -393,20 +398,42 @@
393 398
394 399 private function getCustomerAdditionalData($request)
395 400 {
396 401
397 - $onBehalf = $request->get('on_behalf', []);
398 - if ($onBehalf) {
399 - $onBehalf = array_map(function ($item) {
400 - return sanitize_text_field($item);
401 - }, $onBehalf);
402 - }
403 -
404 402 $customerAdditionalData = [
405 403 'intended_ticket_hash' => $request->getSafe('intended_ticket_hash', 'sanitize_text_field'),
406 - 'on_behalf' => $onBehalf,
404 + 'on_behalf' => $this->sanitizeOnBehalf($request),
407 405 'user_ip' => $request->getIp()
408 406 ];
409 407
410 408 return $customerAdditionalData;
409 + }
410 +
411 + /**
412 + * Read the `on_behalf` identity payload from the request in a predictable shape.
413 + * Only an array of scalars is accepted; anything else (a scalar, or nested
414 + * arrays) is discarded so callers can never hand a non-string to
415 + * sanitize_text_field(). An empty result makes resolveCustomer() fall back to
416 + * the logged-in user instead of a request-supplied identity.
417 + *
418 + * @param Request $request
419 + * @return array
420 + */
421 + private function sanitizeOnBehalf($request)
422 + {
423 + $onBehalf = $request->get('on_behalf', []);
424 +
425 + if (!is_array($onBehalf)) {
426 + return [];
427 + }
428 +
429 + $sanitized = [];
430 +
431 + foreach ($onBehalf as $key => $value) {
432 + if (is_scalar($value)) {
433 + $sanitized[sanitize_text_field($key)] = sanitize_text_field($value);
434 + }
435 + }
436 +
437 + return $sanitized;
411 438 }
412 439 }