PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.1.2
Fluent Support – Helpdesk & Customer Support Ticket System v2.1.2
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/CustomerController.php +167 -14 1.10.32.1.2 View file →
@@ -3,10 +3,12 @@
3 3 namespace FluentSupport\App\Http\Controllers;
4 4
5 5 use FluentCrm\App\Models\Subscriber;
6 6 use FluentSupport\App\Models\Customer;
7 -use FluentSupport\Framework\Request\Request;
7 +use FluentSupport\Framework\Http\Request\Request;
8 8 use FluentSupport\App\Services\AvatarUploder;
9 +use FluentSupport\App\Services\Helper;
10 +use FluentSupport\Framework\Support\Arr;
9 11
10 12 /**
11 13 * CustomerController class for REST API
12 14 * This class is responsible for getting data for all request related to customer
@@ -30,9 +32,9 @@
30 32 }
31 33
32 34 public function customerField (Request $request,Customer $customer, $customer_id) {
33 35
34 - $userID = intval($request->get('user_id'));
36 + $userID = $request->getSafe('user_id', 'intval');
35 37 return[
36 38 'customerField' => $customer->getCustomerField($customer_id,$userID)
37 39 ];
38 40 }
@@ -47,9 +49,12 @@
47 49 * @return array
48 50 */
49 51 public function getCustomer(Request $request, Customer $customer, $customer_id)
50 52 {
51 - return $customer->getCustomer($customer_id, $request->getSafe('with',null,[]));
53 + $with = $request->get('with', null);
54 + $with = is_array($with) ? array_map('sanitize_key', $with) : [];
55 +
56 + return $customer->getCustomer($customer_id, $with);
52 57 }
53 58
54 59 /**
55 60 * Create method will create new customer
@@ -59,15 +64,59 @@
59 64 * @throws \FluentSupport\Framework\Validator\ValidationException
60 65 */
61 66 public function create(Request $request, Customer $customer)
62 67 {
63 - $this->validate($request->get(), [
64 - 'email' => 'required|email|unique:fs_persons'
68 + // Define expected fields with their sanitizers
69 + $fields = [
70 + 'id' => 'intval',
71 + 'customer_id' => 'intval',
72 + 'avatar' => 'esc_url_raw',
73 + 'person_type' => 'sanitize_text_field',
74 + 'hash' => 'sanitize_text_field',
75 + 'description' => 'sanitize_text_field',
76 + 'photo' => 'esc_url_raw',
77 + 'email' => 'sanitize_email',
78 + 'first_name' => 'sanitize_text_field',
79 + 'last_name' => 'sanitize_text_field',
80 + 'title' => 'sanitize_text_field',
81 + 'user_id' => 'intval',
82 + 'remote_uid' => 'sanitize_text_field',
83 + 'status' => 'sanitize_text_field',
84 + 'address_line_1' => 'sanitize_textarea_field',
85 + 'address_line_2' => 'sanitize_textarea_field',
86 + 'city' => 'sanitize_text_field',
87 + 'state' => 'sanitize_text_field',
88 + 'zip' => 'sanitize_text_field',
89 + 'country' => 'sanitize_text_field',
90 + 'note' => 'sanitize_textarea_field',
91 + 'ip_address' => 'sanitize_text_field',
92 + 'last_ip_address' => 'sanitize_text_field',
93 + ];
94 +
95 + $data = $this->sanitizeRequestData($request, $fields);
96 +
97 + $data = $this->validate($data, [
98 + 'email' => 'required|email|unique:fs_persons',
99 + 'first_name' => 'required',
100 + 'last_name' => 'nullable|string',
101 + 'title' => 'nullable|string',
102 + 'user_id' => 'nullable|integer',
103 + 'remote_uid' => 'nullable|string',
104 + 'status' => 'nullable|string',
105 + 'address_line_1' => 'nullable|string',
106 + 'address_line_2' => 'nullable|string',
107 + 'city' => 'nullable|string',
108 + 'state' => 'nullable|string',
109 + 'zip' => 'nullable|string',
110 + 'country' => 'nullable|string',
111 + 'note' => 'nullable|string',
112 + 'ip_address' => 'nullable|string',
113 + 'last_ip_address' => 'nullable|string',
65 114 ]);
66 115
67 116 return [
68 117 'message' => __('Customer has been added', 'fluent-support'),
69 - 'customer' => $customer->createCustomer($request->get())
118 + 'customer' => $customer->createCustomer($data)
70 119 ];
71 120 }
72 121
73 122 /**
@@ -79,11 +128,54 @@
79 128 * @throws \FluentSupport\Framework\Validator\ValidationException
80 129 */
81 130 public function update(Request $request, Customer $customer, $customer_id)
82 131 {
83 - $data = $this->validate($request->get(), [
132 + // Sanitize only allowed fields and also sanitize any extra fields from hooks
133 + $fields = [
134 + 'id' => 'intval',
135 + 'customer_id' => 'intval',
136 + 'avatar' => 'esc_url_raw',
137 + 'person_type' => 'sanitize_text_field',
138 + 'hash' => 'sanitize_text_field',
139 + 'description' => 'sanitize_text_field',
140 + 'photo' => 'esc_url_raw',
141 + 'email' => 'sanitize_email',
142 + 'first_name' => 'sanitize_text_field',
143 + 'last_name' => 'sanitize_text_field',
144 + 'title' => 'sanitize_text_field',
145 + 'user_id' => 'intval',
146 + 'remote_uid' => 'sanitize_text_field',
147 + 'status' => 'sanitize_text_field',
148 + 'address_line_1' => 'sanitize_textarea_field',
149 + 'address_line_2' => 'sanitize_textarea_field',
150 + 'city' => 'sanitize_text_field',
151 + 'state' => 'sanitize_text_field',
152 + 'zip' => 'sanitize_text_field',
153 + 'country' => 'sanitize_text_field',
154 + 'note' => 'sanitize_textarea_field',
155 + 'ip_address' => 'sanitize_text_field',
156 + 'last_ip_address' => 'sanitize_text_field',
157 + ];
158 +
159 + $data = $this->sanitizeRequestData($request, $fields);
160 +
161 + $data = $this->validate($data, [
84 162 'email' => 'required|email',
85 - 'first_name' => 'required'
163 + 'first_name' => 'required',
164 + 'last_name' => 'nullable|string',
165 + 'title' => 'nullable|string',
166 + 'user_id' => 'nullable|integer',
167 + 'remote_uid' => 'nullable|string',
168 + 'status' => 'nullable|string',
169 + 'address_line_1' => 'nullable|string',
170 + 'address_line_2' => 'nullable|string',
171 + 'city' => 'nullable|string',
172 + 'state' => 'nullable|string',
173 + 'zip' => 'nullable|string',
174 + 'country' => 'nullable|string',
175 + 'note' => 'nullable|string',
176 + 'ip_address' => 'nullable|string',
177 + 'last_ip_address' => 'nullable|string',
86 178 ]);
87 179
88 180 try {
89 181 return [
@@ -91,9 +183,9 @@
91 183 'customer' => $customer->updateCustomer($customer_id, $data)
92 184 ];
93 185 } catch (\Exception $e) {
94 186 return $this->sendError([
95 - 'message' => $e->getMessage(),
187 + 'message' => Helper::getSafeErrorMessage($e),
96 188 'errors' => [
97 189 'email' => [
98 190 'unique' => __('Email address has been assigned to other customer', 'fluent-support'),
99 191 ]
@@ -114,8 +206,33 @@
114 206 return $customer->deleteCustomer($customer_id);
115 207 }
116 208
117 209 /**
210 + * bulkDelete method will delete multiple customers and all their tickets
211 + * @param Request $request
212 + * @param Customer $customer
213 + * @return array
214 + */
215 + public function bulkDelete(Request $request, Customer $customer)
216 + {
217 + // Get and sanitize customer_ids before validation
218 + $customerIds = $request->get('customer_ids', []);
219 + $customerIds = is_array($customerIds) ? array_map('intval', $customerIds) : [];
220 +
221 + // Filter out any zero values (from invalid input)
222 + $customerIds = array_filter($customerIds, function ($id) {
223 + return $id > 0;
224 + });
225 +
226 + $this->validate(['customer_ids' => $customerIds], [
227 + 'customer_ids' => 'required|array|min:1',
228 + 'customer_ids.*' => 'required|integer|exists:fs_persons,id'
229 + ]);
230 +
231 + return $customer->bulkDeleteCustomers($customerIds);
232 + }
233 +
234 + /**
118 235 * addOrUpdateProfileImage method will update a customer avatar
119 236 * For a successful upload it's required to send file object, customer id and the user type(customer)
120 237 * @param Request $request
121 238 * @return array
@@ -125,9 +242,9 @@
125 242 try {
126 243 return $avatarUploder->addOrUpdateProfileImage($request->files(), $request->getSafe('customer_id', 'intval'), 'customer');
127 244 } catch (\Exception $e) {
128 245 return $this->sendError([
129 - 'message' => $e->getMessage(),
246 + 'message' => Helper::getSafeErrorMessage($e),
130 247 ],
131 248 $e->getCode()
132 249 );
133 250 }
@@ -139,12 +256,12 @@
139 256 * @param Request $request
140 257 * @param $id
141 258 * @return array
142 259 */
143 - public function resetAvatar(Customer $customer, $customer_id)
260 + public function resetAvatar(Customer $customer)
144 261 {
145 262 try {
146 - $customer->restoreAvatar($customer, $customer_id);
263 + $customer->restoreAvatar();
147 264
148 265 return [
149 266 'message' => __('Customer avatar reset to gravatar default', 'fluent-support'),
150 267 ];
@@ -149,9 +266,9 @@
149 266 'message' => __('Customer avatar reset to gravatar default', 'fluent-support'),
150 267 ];
151 268 } catch (\Exception $e) {
152 269 return [
153 - 'message' => $e->getMessage()
270 + 'message' => Helper::getSafeErrorMessage($e)
154 271 ];
155 272 }
156 273 }
157 274
@@ -159,9 +276,9 @@
159 276 {
160 277 $search = $request->getSafe('search', 'sanitize_text_field');
161 278 if (!$search) {
162 279 return $this->sendError([
163 - 'message' => 'Please provide search string'
280 + 'message' => __('Please provide search string', 'fluent-support')
164 281 ]);
165 282 }
166 283
167 284 $isEmail = is_email($search);
@@ -245,6 +362,42 @@
245 362 'data' => [],
246 363 'is_email' => $isEmail
247 364 ];
248 365
366 + }
367 +
368 + /**
369 + * Sanitize request data for given fields. Uses Request::getSafe for known fields
370 + * and falls back to sanitize_text_field for any other keys present in the raw request
371 + * (useful when hooks inject extra data).
372 + *
373 + * @param Request $request
374 + * @param array $fieldsMap associative array field => sanitizer callable name
375 + * @return array
376 + */
377 + private function sanitizeRequestData(Request $request, array $fieldsMap)
378 + {
379 + $sanitized = [];
380 +
381 + // Use getSafe for known fields
382 + foreach ($fieldsMap as $field => $sanitizer) {
383 + $sanitized[$field] = $request->getSafe($field, $sanitizer);
384 + }
385 +
386 + // Now sanitize any other incoming keys to avoid unsanitized data
387 + $raw = $request->get();
388 + foreach ($raw as $key => $value) {
389 + if (array_key_exists($key, $sanitized)) {
390 + continue;
391 + }
392 +
393 + if (is_array($value)) {
394 + $sanitized[$key] = array_map('sanitize_text_field', $value);
395 + } else {
396 + // Fallback sanitizer for unknown fields
397 + $sanitized[$key] = is_string($value) ? sanitize_text_field($value) : $value;
398 + }
399 + }
400 +
401 + return $sanitized;
249 402 }
250 403 }