PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / trunk
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration vtrunk
2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 1.41 1.45 All 41 releases
← All changes | app/Http/Controllers/WebhookController.php +266 -9 1.13trunk View file →
@@ -2,8 +2,10 @@
2 2
3 3 namespace FluentBoards\App\Http\Controllers;
4 4
5 5 use FluentBoards\App\Models\Webhook;
6 +use FluentBoards\App\Models\Meta;
7 +use FluentBoards\App\Models\Relation;
6 8 use FluentBoards\Framework\Http\Request\Request;
7 9
8 10
9 11 class WebhookController extends Controller
@@ -10,12 +12,11 @@
10 12 {
11 13 public function index(Request $request, Webhook $webhook)
12 14 {
13 15 $fields = $webhook->getFields();
14 - $search = $request->getSafe('search', '');
16 + $search = $request->getSafe('search', 'sanitize_text_field', '');
15 17
16 18 $webhooks = $webhook->latest()->get()->toArray();
17 -
18 19 if ( ! empty($search)) {
19 20 $search = strtolower($search);
20 21 $webhooks = array_map(function ($row) use ($search) {
21 22 $name = strtolower($row['value']['name']);
@@ -44,15 +45,24 @@
44 45 }
45 46
46 47 public function create(Request $request, Webhook $webhook)
47 48 {
48 - $webhook = $webhook->store(
49 - $this->validate(
50 - $request->all(),
51 - ['name' => 'required']
52 - )
53 - );
49 + $name = $request->name;
50 + $boardId = $request->getSafe('board', 'intval');
51 + $stageId = $request->getSafe('stage', 'intval');
52 + // Sanitize name field
53 + $name = sanitize_text_field($name);
54 54
55 + if(!$name || !$boardId || !$stageId) {
56 + return $this->sendError('Name, board and stage are required');
57 + }
58 +
59 + $webhook = $webhook->store([
60 + 'name' => $name,
61 + 'board' => $boardId,
62 + 'stage' => $stageId,
63 + ]);
64 +
55 65 return [
56 66 'id' => $webhook->id,
57 67 'webhook' => $webhook->value,
58 68 'webhooks' => $webhook->latest()->get(),
@@ -61,10 +71,22 @@
61 71 }
62 72
63 73 public function update(Request $request, Webhook $webhook, $id)
64 74 {
65 - $webhook->find($id)->saveChanges($request->all());
75 + $id = absint($id);
76 + $data = $request->only(['name']);
77 + // Sanitize data if needed based on webhook structure
78 + if (isset($data['name'])) {
79 + $data['name'] = sanitize_text_field($data['name']);
80 + }
66 81
82 + $foundWebhook = $webhook->find($id);
83 + if (!$foundWebhook) {
84 + return $this->sendError(__('Webhook not found', 'fluent-boards'), 404);
85 + }
86 +
87 + $foundWebhook->saveChanges($data);
88 +
67 89 return [
68 90 'webhooks' => $webhook->latest()->get(),
69 91 'message' => __('Successfully updated the webhook', 'fluent-boards'),
70 92 ];
@@ -71,12 +93,247 @@
71 93 }
72 94
73 95 public function delete(Webhook $webhook, $id)
74 96 {
97 + $id = absint($id);
75 98 $webhook->where('id', $id)->delete();
76 99
77 100 return [
78 101 'webhooks' => $webhook->latest()->get(),
79 102 'message' => __('Successfully deleted the webhook', 'fluent-boards'),
103 + ];
104 + }
105 +
106 + // Outgoing Webhook Methods
107 + public function outgoingWebhooks(Request $request, Meta $meta)
108 + {
109 + $search = $request->getSafe('search', 'sanitize_text_field', '');
110 + $boardId = $request->getSafe('board_id', 'intval');
111 +
112 + $webhooks = $meta->where('object_type', 'outgoing_webhook')
113 + ->latest()
114 + ->get()
115 + ->toArray();
116 +
117 + // Add board filtering logic
118 + if ($boardId) {
119 + $webhooks = array_filter($webhooks, function($row) use ($boardId) {
120 + if (!isset($row['value']['board_id'])) {
121 + return false;
122 + }
123 +
124 + $webhookBoardId = $row['value']['board_id'];
125 +
126 + // Handle array of board IDs
127 + if (is_array($webhookBoardId)) {
128 + return in_array($boardId, array_map('intval', $webhookBoardId));
129 + }
130 +
131 + // Handle single board ID or null (all boards)
132 + return $webhookBoardId === null || intval($webhookBoardId) === $boardId;
133 + });
134 + }
135 +
136 + if (!empty($search)) {
137 + $search = strtolower($search);
138 + $webhooks = array_map(function ($row) use ($search) {
139 + $name = strtolower($row['value']['name']);
140 + if ($row['value'] && str_contains($name, $search)) {
141 + return $row;
142 + }
143 + return null;
144 + }, $webhooks);
145 + }
146 +
147 + $rows = [];
148 + foreach ($webhooks as $row) {
149 + if ($row) {
150 + $rows[] = $row;
151 + }
152 + }
153 +
154 + return [
155 + 'webhooks' => $rows
156 + ];
157 + }
158 +
159 + public function createOutgoingWebhook(Request $request)
160 + {
161 + $data = $this->validate(
162 + $request->only(['name', 'url', 'board_id', 'triggered_events', 'header_type', 'headers']),
163 + [
164 + 'name' => 'required',
165 + 'url' => 'required',
166 + 'board_id' => 'array',
167 + 'triggered_events' => 'array',
168 + ]
169 + );
170 +
171 + $data['name'] = sanitize_text_field($data['name']);
172 + $data['url'] = sanitize_url($data['url']);
173 +
174 + // Sanitize header_type if present
175 + if (isset($data['header_type'])) {
176 + $data['header_type'] = sanitize_text_field($data['header_type']);
177 + }
178 +
179 + if(isset($data['header_type']) && $data['header_type'] == 'with_headers') {
180 + // sanitize all headers key and value
181 + if (!empty($data['headers']) && is_array($data['headers'])) {
182 + foreach ($data['headers'] as $index => $header) {
183 + if (isset($header['name'])) {
184 + $data['headers'][$index]['name'] = sanitize_text_field($header['name']);
185 + }
186 + if (isset($header['value'])) {
187 + $data['headers'][$index]['value'] = sanitize_text_field($header['value']);
188 + }
189 + }
190 + }
191 + }
192 +
193 + // events cannot be null
194 + if (!isset($data['triggered_events']) || empty($data['triggered_events'])) {
195 + return $this->sendError('At least one event must be selected for the webhook to be triggered.');
196 + }
197 +
198 + // Sanitize triggered_events array
199 + if (is_array($data['triggered_events'])) {
200 + $data['triggered_events'] = array_filter(array_map('sanitize_text_field', $data['triggered_events']));
201 + }
202 + $data['triggered_events'] = array_values($data['triggered_events']);
203 +
204 + // Sanitize board_id array to integers
205 + if (!empty($data['board_id']) && is_array($data['board_id'])) {
206 + $data['board_id'] = array_filter(array_map('intval', $data['board_id']));
207 + } else {
208 + $data['board_id'] = [];
209 + }
210 +
211 + $webhook = Meta::create([
212 + 'object_type' => 'outgoing_webhook',
213 + 'value' => $data
214 + ]);
215 +
216 + foreach ($data['board_id'] as $boardId) {
217 + $boardId = absint($boardId);
218 + Relation::create([
219 + 'object_id' => $webhook->id,
220 + 'object_type' => 'outgoing_webhook_board',
221 + 'foreign_id' => $boardId,
222 + 'settings' => \maybe_serialize($data['triggered_events'] ?? []),
223 + 'preferences' => ''
224 + ]);
225 + }
226 +
227 +
228 + return [
229 + 'id' => $webhook->id,
230 + 'webhook' => $webhook->value,
231 + 'webhooks' => Meta::where('object_type', 'outgoing_webhook')->latest()->get(),
232 + 'message' => __('Successfully Created the Outgoing WebHook', 'fluent-boards'),
233 + ];
234 + }
235 +
236 + public function updateOutgoingWebhook(Request $request, $id)
237 + {
238 + $id = absint($id);
239 + $data = $this->validate(
240 + $request->all(),
241 + [
242 + 'name' => 'required',
243 + 'url' => 'required',
244 + 'board_id' => 'array',
245 + 'triggered_events' => 'array',
246 + ]
247 + );
248 +
249 + $data['name'] = sanitize_text_field($data['name']);
250 + $data['url'] = sanitize_url($data['url']);
251 +
252 + // Sanitize header_type if present
253 + if (isset($data['header_type'])) {
254 + $data['header_type'] = sanitize_text_field($data['header_type']);
255 + }
256 +
257 + if(isset($data['header_type']) && $data['header_type'] == 'with_headers') {
258 + // sanitize all headers key and value
259 + if (!empty($data['headers']) && is_array($data['headers'])) {
260 + foreach ($data['headers'] as $index => $header) {
261 + if (isset($header['name'])) {
262 + $data['headers'][$index]['name'] = sanitize_text_field($header['name']);
263 + }
264 + if (isset($header['value'])) {
265 + $data['headers'][$index]['value'] = sanitize_text_field($header['value']);
266 + }
267 + }
268 + }
269 + }
270 +
271 + // Sanitize triggered_events array
272 + if (is_array($data['triggered_events'])) {
273 + $data['triggered_events'] = array_filter(array_map('sanitize_text_field', $data['triggered_events']));
274 + }
275 +
276 + // Sanitize board_id array to integers
277 + if (!empty($data['board_id']) && is_array($data['board_id'])) {
278 + $data['board_id'] = array_filter(array_map('intval', $data['board_id']));
279 + } else {
280 + $data['board_id'] = [];
281 + }
282 +
283 + $webhook = Meta::find($id);
284 +
285 + if (!$webhook || $webhook->object_type !== 'outgoing_webhook') {
286 + return $this->sendError('Outgoing webhook not found.', 404);
287 + }
288 +
289 + $webhook->value = $data;
290 + $webhook->save();
291 +
292 +
293 + // Update relations
294 + Relation::where('object_type', 'outgoing_webhook_board')
295 + ->where('object_id', $webhook->id)
296 + ->delete();
297 +
298 + // Recreate relations
299 + foreach ($data['board_id'] as $boardId) {
300 + $boardId = absint($boardId);
301 + Relation::create([
302 + 'object_id' => $webhook->id,
303 + 'object_type' => 'outgoing_webhook_board',
304 + 'foreign_id' => $boardId,
305 + 'settings' => \maybe_serialize($data['triggered_events'] ?? []),
306 + 'preferences' => ''
307 + ]);
308 + }
309 +
310 +
311 + return [
312 + 'webhooks' => Meta::where('object_type', 'outgoing_webhook')->latest()->get(),
313 + 'message' => __('Successfully updated the outgoing webhook', 'fluent-boards'),
314 + ];
315 + }
316 +
317 + public function deleteOutgoingWebhook($id)
318 + {
319 + $id = absint($id);
320 + $webhook = Meta::find($id);
321 +
322 + if (!$webhook || $webhook->object_type !== 'outgoing_webhook') {
323 + return $this->sendError('Outgoing webhook not found.', 404);
324 + }
325 +
326 + // Delete associated relations
327 + Relation::where('object_type', 'outgoing_webhook_board')
328 + ->where('object_id', $webhook->id)
329 + ->delete();
330 +
331 +
332 + $webhook->delete();
333 +
334 + return [
335 + 'webhooks' => Meta::where('object_type', 'outgoing_webhook')->latest()->get(),
336 + 'message' => __('Successfully deleted the outgoing webhook', 'fluent-boards'),
80 337 ];
81 338 }
82 339 }