blob: 46d6e35c24d43a70c7f65db76a380fd31e0a1aff [file] [log] [blame]
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +01001<?php
2/*
3 see /api
4*/
5
6header('Content-Type: application/json');
7require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
8error_reporting(0);
9
10function api_log($_data) {
11 global $redis;
12 $data_var = array();
13 foreach ($_data as $data => &$value) {
14 if ($data == 'csrf_token') {
15 continue;
16 }
17 if ($value = json_decode($value, true)) {
18 unset($value["csrf_token"]);
19 foreach ($value as $key => &$val) {
20 if(preg_match("/pass/i", $key)) {
21 $val = '*';
22 }
23 }
24 $value = json_encode($value);
25 }
26 $data_var[] = $data . "='" . $value . "'";
27 }
28 try {
29 $log_line = array(
30 'time' => time(),
31 'uri' => $_SERVER['REQUEST_URI'],
32 'method' => $_SERVER['REQUEST_METHOD'],
33 'remote' => get_remote_ip(),
34 'data' => implode(', ', $data_var)
35 );
36 $redis->lPush('API_LOG', json_encode($log_line));
37 }
38 catch (RedisException $e) {
39 $_SESSION['return'][] = array(
40 'type' => 'danger',
41 'msg' => 'Redis: '.$e
42 );
43 return false;
44 }
45}
46
47if (isset($_GET['query'])) {
48
49 $query = explode('/', $_GET['query']);
50 $action = (isset($query[0])) ? $query[0] : null;
51 $category = (isset($query[1])) ? $query[1] : null;
52 $object = (isset($query[2])) ? $query[2] : null;
53 $extra = (isset($query[3])) ? $query[3] : null;
54
55 // accept json in request body
56 if(strpos($_SERVER['HTTP_CONTENT_TYPE'], 'application/json') !== false) {
57 $request = file_get_contents('php://input');
58 $requestDecoded = json_decode($request, true);
59
60 // check for valid json
61 if ($action != 'get' && $requestDecoded === null) {
62 http_response_code(400);
63 echo json_encode(array(
64 'type' => 'error',
65 'msg' => 'Request body doesn\'t contain valid json!'
66 ));
67 exit;
68 }
69
70 // add
71 if ($action == 'add') {
72 $_POST['attr'] = $request;
73 }
74
75 // edit
76 if ($action == 'edit') {
77 $_POST['attr'] = json_encode($requestDecoded['attr']);
78 $_POST['items'] = json_encode($requestDecoded['items']);
79 }
80
81 // delete
82 if ($action == 'delete') {
83 $_POST['items'] = $request;
84 }
85
86 }
87 api_log($_POST);
88
89 $request_incomplete = json_encode(array(
90 'type' => 'error',
91 'msg' => 'Cannot find attributes in post data'
92 ));
93
94 switch ($action) {
95 case "add":
96 if ($_SESSION['mailcow_cc_api_access'] == 'ro' || isset($_SESSION['pending_mailcow_cc_username'])) {
97 http_response_code(403);
98 echo json_encode(array(
99 'type' => 'error',
100 'msg' => 'API read/write access denied'
101 ));
102 exit();
103 }
104 function process_add_return($return) {
105 $generic_failure = json_encode(array(
106 'type' => 'error',
107 'msg' => 'Cannot add item'
108 ));
109 $generic_success = json_encode(array(
110 'type' => 'success',
111 'msg' => 'Task completed'
112 ));
113 if ($return === false) {
114 echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_failure;
115 }
116 else {
117 echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_success;
118 }
119 }
120 if (!isset($_POST['attr']) && $category != "fido2-registration") {
121 echo $request_incomplete;
122 exit;
123 }
124 else {
125 if ($category != "fido2-registration") {
126 $attr = (array)json_decode($_POST['attr'], true);
127 }
128 unset($attr['csrf_token']);
129 }
130 // only allow POST requests to POST API endpoints
131 if ($_SERVER['REQUEST_METHOD'] != 'POST') {
132 http_response_code(405);
133 echo json_encode(array(
134 'type' => 'error',
135 'msg' => 'only POST method is allowed'
136 ));
137 exit();
138 }
139
140 switch ($category) {
141 // fido2-registration via POST
142 case "fido2-registration":
143 header('Content-Type: application/json');
144 if (isset($_SESSION["mailcow_cc_role"]) && ($_SESSION["mailcow_cc_role"] == "admin" || $_SESSION["mailcow_cc_role"] == "domainadmin")) {
145 $post = trim(file_get_contents('php://input'));
146 if ($post) {
147 $post = json_decode($post);
148 }
149 $clientDataJSON = base64_decode($post->clientDataJSON);
150 $attestationObject = base64_decode($post->attestationObject);
151 $challenge = $_SESSION['challenge'];
152 try {
153 $data = $WebAuthn->processCreate($clientDataJSON, $attestationObject, $challenge, $GLOBALS['FIDO2_UV_FLAG_REGISTER'], $GLOBALS['FIDO2_USER_PRESENT_FLAG']);
154 }
155 catch (Throwable $ex) {
156 $return = new stdClass();
157 $return->success = false;
158 $return->msg = $ex->getMessage();
159 echo json_encode($return);
160 exit;
161 }
162 fido2(array("action" => "register", "registration" => $data));
163 $return = new stdClass();
164 $return->success = true;
165 echo json_encode($return);
166 exit;
167 }
168 else {
169 echo $request_incomplete;
170 exit;
171 }
172 break;
173 case "time_limited_alias":
174 process_add_return(mailbox('add', 'time_limited_alias', $attr));
175 break;
176 case "relayhost":
177 process_add_return(relayhost('add', $attr));
178 break;
179 case "transport":
180 process_add_return(transport('add', $attr));
181 break;
182 case "rsetting":
183 process_add_return(rsettings('add', $attr));
184 break;
185 case "mailbox":
186 process_add_return(mailbox('add', 'mailbox', $attr));
187 break;
188 case "oauth2-client":
189 process_add_return(oauth2('add', 'client', $attr));
190 break;
191 case "domain":
192 process_add_return(mailbox('add', 'domain', $attr));
193 break;
194 case "resource":
195 process_add_return(mailbox('add', 'resource', $attr));
196 break;
197 case "alias":
198 process_add_return(mailbox('add', 'alias', $attr));
199 break;
200 case "filter":
201 process_add_return(mailbox('add', 'filter', $attr));
202 break;
203 case "global-filter":
204 process_add_return(mailbox('add', 'global_filter', $attr));
205 break;
206 case "domain-policy":
207 process_add_return(policy('add', 'domain', $attr));
208 break;
209 case "mailbox-policy":
210 process_add_return(policy('add', 'mailbox', $attr));
211 break;
212 case "alias-domain":
213 process_add_return(mailbox('add', 'alias_domain', $attr));
214 break;
215 case "fwdhost":
216 process_add_return(fwdhost('add', $attr));
217 break;
218 case "dkim":
219 process_add_return(dkim('add', $attr));
220 break;
221 case "dkim_duplicate":
222 process_add_return(dkim('duplicate', $attr));
223 break;
224 case "dkim_import":
225 process_add_return(dkim('import', $attr));
226 break;
227 case "domain-admin":
228 process_add_return(domain_admin('add', $attr));
229 break;
230 case "admin":
231 process_add_return(admin('add', $attr));
232 break;
233 case "syncjob":
234 process_add_return(mailbox('add', 'syncjob', $attr));
235 break;
236 case "bcc":
237 process_add_return(bcc('add', $attr));
238 break;
239 case "recipient_map":
240 process_add_return(recipient_map('add', $attr));
241 break;
242 case "tls-policy-map":
243 process_add_return(tls_policy_maps('add', $attr));
244 break;
245 case "app-passwd":
246 process_add_return(app_passwd('add', $attr));
247 break;
248 // return no route found if no case is matched
249 default:
250 http_response_code(404);
251 echo json_encode(array(
252 'type' => 'error',
253 'msg' => 'route not found'
254 ));
255 exit();
256 }
257 break;
258 case "process":
259 // only allow POST requests to process API endpoints
260 if ($_SERVER['REQUEST_METHOD'] != 'POST') {
261 http_response_code(405);
262 echo json_encode(array(
263 'type' => 'error',
264 'msg' => 'only POST method is allowed'
265 ));
266 exit();
267 }
268 switch ($category) {
269 case "fido2-args":
270 header('Content-Type: application/json');
271 $post = trim(file_get_contents('php://input'));
272 if ($post) {
273 $post = json_decode($post);
274 }
275 $clientDataJSON = base64_decode($post->clientDataJSON);
276 $authenticatorData = base64_decode($post->authenticatorData);
277 $signature = base64_decode($post->signature);
278 $id = base64_decode($post->id);
279 $challenge = $_SESSION['challenge'];
280 $process_fido2 = fido2(array("action" => "get_by_b64cid", "cid" => $post->id));
281 if ($process_fido2['pub_key'] === false) {
282 $return = new stdClass();
283 $return->success = false;
284 echo json_encode($return);
285 exit;
286 }
287 try {
288 $WebAuthn->processGet($clientDataJSON, $authenticatorData, $signature, $process_fido2['pub_key'], $challenge, null, $GLOBALS['FIDO2_UV_FLAG_LOGIN'], $GLOBALS['FIDO2_USER_PRESENT_FLAG']);
289 }
290 catch (Throwable $ex) {
291 unset($process_fido2);
292 $return = new stdClass();
293 $return->success = false;
294 echo json_encode($return);
295 exit;
296 }
297 $return = new stdClass();
298 $return->success = true;
299 $stmt = $pdo->prepare("SELECT `superadmin` FROM `admin` WHERE `username` = :username");
300 $stmt->execute(array(':username' => $process_fido2['username']));
301 $obj_props = $stmt->fetch(PDO::FETCH_ASSOC);
302 if ($obj_props['superadmin'] === 1) {
303 $_SESSION["mailcow_cc_role"] = "admin";
304 }
305 else {
306 $_SESSION["mailcow_cc_role"] = "domainadmin";
307 }
308 $_SESSION["mailcow_cc_username"] = $process_fido2['username'];
309 $_SESSION['mailcow_cc_last_login'] = last_login($process_fido2['username']);
310 $_SESSION["fido2_cid"] = $process_fido2['cid'];
311 unset($_SESSION["challenge"]);
312 $_SESSION['return'][] = array(
313 'type' => 'success',
314 'log' => array("fido2_login"),
315 'msg' => array('logged_in_as', $process_fido2['username'])
316 );
317 echo json_encode($return);
318 break;
319 }
320 break;
321 case "get":
322 function process_get_return($data) {
323 echo (!isset($data) || empty($data)) ? '{}' : json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
324 }
325 // only allow GET requests to GET API endpoints
326 if ($_SERVER['REQUEST_METHOD'] != 'GET') {
327 http_response_code(405);
328 echo json_encode(array(
329 'type' => 'error',
330 'msg' => 'only GET method is allowed'
331 ));
332 exit();
333 }
334 switch ($category) {
335 case "u2f-registration":
336 header('Content-Type: application/javascript');
337 if (isset($_SESSION["mailcow_cc_role"]) &&
338 ($_SESSION["mailcow_cc_role"] == "admin" || $_SESSION["mailcow_cc_role"] == "domainadmin") &&
339 $_SESSION["mailcow_cc_username"] == $object) {
340 list($req, $sigs) = $u2f->getRegisterData(get_u2f_registrations($object));
341 $_SESSION['regReq'] = json_encode($req);
342 $_SESSION['regSigs'] = json_encode($sigs);
343 echo 'var req = ' . json_encode($req) . ';';
344 echo 'var registeredKeys = ' . json_encode($sigs) . ';';
345 echo 'var appId = req.appId;';
346 echo 'var registerRequests = [{version: req.version, challenge: req.challenge}];';
347 return;
348 }
349 else {
350 return;
351 }
352 break;
353 // fido2-registration via GET
354 case "fido2-registration":
355 header('Content-Type: application/json');
356 if (isset($_SESSION["mailcow_cc_role"]) &&
357 ($_SESSION["mailcow_cc_role"] == "admin" || $_SESSION["mailcow_cc_role"] == "domainadmin") &&
358 $_SESSION["mailcow_cc_username"] == $object) {
359 // Exclude existing CredentialIds, if any
360 $excludeCredentialIds = fido2(array("action" => "get_user_cids"));
361 $createArgs = $WebAuthn->getCreateArgs($_SESSION["mailcow_cc_username"], $_SESSION["mailcow_cc_username"], $_SESSION["mailcow_cc_username"], 30, true, $GLOBALS['FIDO2_UV_FLAG_REGISTER'], $excludeCredentialIds);
362 print(json_encode($createArgs));
363 $_SESSION['challenge'] = $WebAuthn->getChallenge();
364 return;
365 }
366 else {
367 return;
368 }
369 break;
370 case "u2f-authentication":
371 header('Content-Type: application/javascript');
372 if (isset($_SESSION['pending_mailcow_cc_username']) && $_SESSION['pending_mailcow_cc_username'] == $object) {
373 $auth_data = $u2f->getAuthenticateData(get_u2f_registrations($object));
374 $challenge = $auth_data[0]->challenge;
375 $appId = $auth_data[0]->appId;
376 foreach ($auth_data as $each) {
377 $key = array(); // Empty array
378 $key['version'] = $each->version;
379 $key['keyHandle'] = $each->keyHandle;
380 $registeredKey[] = $key;
381 }
382 $_SESSION['authReq'] = json_encode($auth_data);
383 echo 'var appId = "' . $appId . '";';
384 echo 'var challenge = ' . json_encode($challenge) . ';';
385 echo 'var registeredKeys = ' . json_encode($registeredKey) . ';';
386 return;
387 }
388 else {
389 return;
390 }
391 break;
392 case "fido2-get-args":
393 header('Content-Type: application/json');
394 // Login without username, no ids!
395 // $ids = fido2(array("action" => "get_all_cids"));
396 // if (count($ids) == 0) {
397 // return;
398 // }
399 $ids = NULL;
400 $getArgs = $WebAuthn->getGetArgs($ids, 30, true, true, true, true, $GLOBALS['FIDO2_UV_FLAG_LOGIN']);
401 print(json_encode($getArgs));
402 $_SESSION['challenge'] = $WebAuthn->getChallenge();
403 return;
404 break;
405 }
406 if (isset($_SESSION['mailcow_cc_role'])) {
407 switch ($category) {
408 case "rspamd":
409 switch ($object) {
410 case "actions":
411 $data = rspamd_actions();
412 if ($data) {
413 echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
414 }
415 else {
416 echo '{}';
417 }
418 break;
419 }
420 break;
421
422 case "domain":
423 switch ($object) {
424 case "all":
425 $domains = mailbox('get', 'domains');
426 if (!empty($domains)) {
427 foreach ($domains as $domain) {
428 if ($details = mailbox('get', 'domain_details', $domain)) {
429 $data[] = $details;
430 }
431 else {
432 continue;
433 }
434 }
435 process_get_return($data);
436 }
437 else {
438 echo '{}';
439 }
440 break;
441
442 default:
443 $data = mailbox('get', 'domain_details', $object);
444 process_get_return($data);
445 break;
446 }
447 break;
448
449 case "app-passwd":
450 switch ($object) {
451 case "all":
452 if (empty($extra)) {
453 $app_passwds = app_passwd('get');
454 }
455 else {
456 $app_passwds = app_passwd('get', array('username' => $extra));
457 }
458 if (!empty($app_passwds)) {
459 foreach ($app_passwds as $app_passwd) {
460 $details = app_passwd('details', array('id' => $app_passwd['id']));
461 if ($details !== false) {
462 $data[] = $details;
463 }
464 else {
465 continue;
466 }
467 }
468 process_get_return($data);
469 }
470 else {
471 echo '{}';
472 }
473 break;
474
475 default:
476 $data = app_passwd('details', array('id' => $object['id']));
477 process_get_return($data);
478 break;
479 }
480 break;
481
482 case "mailq":
483 switch ($object) {
484 case "all":
485 $mailq = mailq('get');
486 if (!empty($mailq)) {
487 echo $mailq;
488 }
489 else {
490 echo '[]';
491 }
492 break;
493 }
494 break;
495
496 case "postcat":
497 switch ($object) {
498 default:
499 $data = mailq('cat', array('qid' => $object));
500 echo $data;
501 break;
502 }
503 break;
504
505 case "global_filters":
506 $global_filters = mailbox('get', 'global_filter_details');
507 switch ($object) {
508 case "all":
509 if (!empty($global_filters)) {
510 process_get_return($global_filters);
511 }
512 else {
513 echo '{}';
514 }
515 break;
516 case "prefilter":
517 if (!empty($global_filters['prefilter'])) {
518 process_get_return($global_filters['prefilter']);
519 }
520 else {
521 echo '{}';
522 }
523 break;
524 case "postfilter":
525 if (!empty($global_filters['postfilter'])) {
526 process_get_return($global_filters['postfilter']);
527 }
528 else {
529 echo '{}';
530 }
531 break;
532 }
533 break;
534
535 case "rl-domain":
536 switch ($object) {
537 case "all":
538 $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
539 if (!empty($domains)) {
540 foreach ($domains as $domain) {
541 if ($details = ratelimit('get', 'domain', $domain)) {
542 $details['domain'] = $domain;
543 $data[] = $details;
544 }
545 else {
546 continue;
547 }
548 }
549 process_get_return($data);
550 }
551 else {
552 echo '{}';
553 }
554 break;
555
556 default:
557 $data = ratelimit('get', 'domain', $object);
558 process_get_return($data);
559 break;
560 }
561 break;
562
563 case "rl-mbox":
564 switch ($object) {
565 case "all":
566 $domains = mailbox('get', 'domains');
567 if (!empty($domains)) {
568 foreach ($domains as $domain) {
569 $mailboxes = mailbox('get', 'mailboxes', $domain);
570 if (!empty($mailboxes)) {
571 foreach ($mailboxes as $mailbox) {
572 if ($details = ratelimit('get', 'mailbox', $mailbox)) {
573 $details['mailbox'] = $mailbox;
574 $data[] = $details;
575 }
576 else {
577 continue;
578 }
579 }
580 }
581 }
582 process_get_return($data);
583 }
584 else {
585 echo '{}';
586 }
587 break;
588
589 default:
590 $data = ratelimit('get', 'mailbox', $object);
591 process_get_return($data);
592 break;
593 }
594 break;
595
596 case "relayhost":
597 switch ($object) {
598 case "all":
599 $relayhosts = relayhost('get');
600 if (!empty($relayhosts)) {
601 foreach ($relayhosts as $relayhost) {
602 if ($details = relayhost('details', $relayhost['id'])) {
603 $data[] = $details;
604 }
605 else {
606 continue;
607 }
608 }
609 process_get_return($data);
610 }
611 else {
612 echo '{}';
613 }
614 break;
615
616 default:
617 $data = relayhost('details', $object);
618 process_get_return($data);
619 break;
620 }
621 break;
622
623 case "transport":
624 switch ($object) {
625 case "all":
626 $transports = transport('get');
627 if (!empty($transports)) {
628 foreach ($transports as $transport) {
629 if ($details = transport('details', $transport['id'])) {
630 $data[] = $details;
631 }
632 else {
633 continue;
634 }
635 }
636 process_get_return($data);
637 }
638 else {
639 echo '{}';
640 }
641 break;
642
643 default:
644 $data = transport('details', $object);
645 process_get_return($data);
646 break;
647 }
648 break;
649
650 case "rsetting":
651 switch ($object) {
652 case "all":
653 $rsettings = rsettings('get');
654 if (!empty($rsettings)) {
655 foreach ($rsettings as $rsetting) {
656 if ($details = rsettings('details', $rsetting['id'])) {
657 $data[] = $details;
658 }
659 else {
660 continue;
661 }
662 }
663 process_get_return($data);
664 }
665 else {
666 echo '{}';
667 }
668 break;
669
670 default:
671 $data = rsettings('details', $object);
672 process_get_return($data);
673 break;
674 }
675 break;
676
677 case "oauth2-client":
678 switch ($object) {
679 case "all":
680 $clients = oauth2('get', 'clients');
681 if (!empty($clients)) {
682 foreach ($clients as $client) {
683 if ($details = oauth2('details', 'client', $client)) {
684 $data[] = $details;
685 }
686 else {
687 continue;
688 }
689 }
690 process_get_return($data);
691 }
692 else {
693 echo '{}';
694 }
695 break;
696
697 default:
698 $data = oauth2('details', 'client', $object);
699 process_get_return($data);
700 break;
701 }
702 break;
703
704 case "logs":
705 switch ($object) {
706 case "dovecot":
707 // 0 is first record, so empty is fine
708 if (isset($extra)) {
709 $extra = preg_replace('/[^\d\-]/i', '', $extra);
710 $logs = get_logs('dovecot-mailcow', $extra);
711 }
712 else {
713 $logs = get_logs('dovecot-mailcow');
714 }
715 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
716 break;
717 case "ratelimited":
718 // 0 is first record, so empty is fine
719 if (isset($extra)) {
720 $extra = preg_replace('/[^\d\-]/i', '', $extra);
721 $logs = get_logs('ratelimited', $extra);
722 }
723 else {
724 $logs = get_logs('ratelimited');
725 }
726 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
727 break;
728 case "netfilter":
729 // 0 is first record, so empty is fine
730 if (isset($extra)) {
731 $extra = preg_replace('/[^\d\-]/i', '', $extra);
732 $logs = get_logs('netfilter-mailcow', $extra);
733 }
734 else {
735 $logs = get_logs('netfilter-mailcow');
736 }
737 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
738 break;
739 case "postfix":
740 // 0 is first record, so empty is fine
741 if (isset($extra)) {
742 $extra = preg_replace('/[^\d\-]/i', '', $extra);
743 $logs = get_logs('postfix-mailcow', $extra);
744 }
745 else {
746 $logs = get_logs('postfix-mailcow');
747 }
748 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
749 break;
750 case "autodiscover":
751 // 0 is first record, so empty is fine
752 if (isset($extra)) {
753 $extra = preg_replace('/[^\d\-]/i', '', $extra);
754 $logs = get_logs('autodiscover-mailcow', $extra);
755 }
756 else {
757 $logs = get_logs('autodiscover-mailcow');
758 }
759 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
760 break;
761 case "sogo":
762 // 0 is first record, so empty is fine
763 if (isset($extra)) {
764 $extra = preg_replace('/[^\d\-]/i', '', $extra);
765 $logs = get_logs('sogo-mailcow', $extra);
766 }
767 else {
768 $logs = get_logs('sogo-mailcow');
769 }
770 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
771 break;
772 case "ui":
773 // 0 is first record, so empty is fine
774 if (isset($extra)) {
775 $extra = preg_replace('/[^\d\-]/i', '', $extra);
776 $logs = get_logs('mailcow-ui', $extra);
777 }
778 else {
779 $logs = get_logs('mailcow-ui');
780 }
781 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
782 break;
783 case "watchdog":
784 // 0 is first record, so empty is fine
785 if (isset($extra)) {
786 $extra = preg_replace('/[^\d\-]/i', '', $extra);
787 $logs = get_logs('watchdog-mailcow', $extra);
788 }
789 else {
790 $logs = get_logs('watchdog-mailcow');
791 }
792 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
793 break;
794 case "acme":
795 // 0 is first record, so empty is fine
796 if (isset($extra)) {
797 $extra = preg_replace('/[^\d\-]/i', '', $extra);
798 $logs = get_logs('acme-mailcow', $extra);
799 }
800 else {
801 $logs = get_logs('acme-mailcow');
802 }
803 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
804 break;
805 case "api":
806 // 0 is first record, so empty is fine
807 if (isset($extra)) {
808 $extra = preg_replace('/[^\d\-]/i', '', $extra);
809 $logs = get_logs('api-mailcow', $extra);
810 }
811 else {
812 $logs = get_logs('api-mailcow');
813 }
814 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
815 break;
816 case "rspamd-history":
817 // 0 is first record, so empty is fine
818 if (isset($extra)) {
819 $extra = preg_replace('/[^\d\-]/i', '', $extra);
820 $logs = get_logs('rspamd-history', $extra);
821 }
822 else {
823 $logs = get_logs('rspamd-history');
824 }
825 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
826 break;
827 case "rspamd-stats":
828 $logs = get_logs('rspamd-stats');
829 echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
830 break;
831 // return no route found if no case is matched
832 default:
833 http_response_code(404);
834 echo json_encode(array(
835 'type' => 'error',
836 'msg' => 'route not found'
837 ));
838 exit();
839 }
840 break;
841 case "mailbox":
842 switch ($object) {
843 case "all":
844 if (empty($extra)) {
845 $domains = mailbox('get', 'domains');
846 }
847 else {
848 $domains = array($extra);
849 }
850 if (!empty($domains)) {
851 foreach ($domains as $domain) {
852 $mailboxes = mailbox('get', 'mailboxes', $domain);
853 if (!empty($mailboxes)) {
854 foreach ($mailboxes as $mailbox) {
855 if ($details = mailbox('get', 'mailbox_details', $mailbox)) {
856 $data[] = $details;
857 }
858 else {
859 continue;
860 }
861 }
862 }
863 }
864 process_get_return($data);
865 }
866 else {
867 echo '{}';
868 }
869 break;
870
871 default:
872 $data = mailbox('get', 'mailbox_details', $object);
873 process_get_return($data);
874 break;
875 }
876 break;
877 case "syncjobs":
878 switch ($object) {
879 case "all":
880 $domains = mailbox('get', 'domains');
881 if (!empty($domains)) {
882 foreach ($domains as $domain) {
883 $mailboxes = mailbox('get', 'mailboxes', $domain);
884 if (!empty($mailboxes)) {
885 foreach ($mailboxes as $mailbox) {
886 $syncjobs = mailbox('get', 'syncjobs', $mailbox);
887 if (!empty($syncjobs)) {
888 foreach ($syncjobs as $syncjob) {
889 if (isset($extra)) {
890 $details = mailbox('get', 'syncjob_details', $syncjob, explode(',', $extra));
891 }
892 else {
893 $details = mailbox('get', 'syncjob_details', $syncjob);
894 }
895 if ($details) {
896 $data[] = $details;
897 }
898 else {
899 continue;
900 }
901 }
902 }
903 }
904 }
905 }
906 process_get_return($data);
907 }
908 else {
909 echo '{}';
910 }
911 break;
912
913 default:
914 $syncjobs = mailbox('get', 'syncjobs', $object);
915 if (!empty($syncjobs)) {
916 foreach ($syncjobs as $syncjob) {
917 if (isset($extra)) {
918 $details = mailbox('get', 'syncjob_details', $syncjob, explode(',', $extra));
919 }
920 else {
921 $details = mailbox('get', 'syncjob_details', $syncjob);
922 }
923 if ($details) {
924 $data[] = $details;
925 }
926 else {
927 continue;
928 }
929 }
930 }
931 process_get_return($data);
932 break;
933 }
934 break;
935 case "active-user-sieve":
936 if (isset($object)) {
937 $sieve_filter = mailbox('get', 'active_user_sieve', $object);
938 if (!empty($sieve_filter)) {
939 $data[] = $sieve_filter;
940 }
941 }
942 process_get_return($data);
943 break;
944 case "filters":
945 switch ($object) {
946 case "all":
947 $domains = mailbox('get', 'domains');
948 if (!empty($domains)) {
949 foreach ($domains as $domain) {
950 $mailboxes = mailbox('get', 'mailboxes', $domain);
951 if (!empty($mailboxes)) {
952 foreach ($mailboxes as $mailbox) {
953 $filters = mailbox('get', 'filters', $mailbox);
954 if (!empty($filters)) {
955 foreach ($filters as $filter) {
956 if ($details = mailbox('get', 'filter_details', $filter)) {
957 $data[] = $details;
958 }
959 else {
960 continue;
961 }
962 }
963 }
964 }
965 }
966 }
967 process_get_return($data);
968 }
969 else {
970 echo '{}';
971 }
972 break;
973
974 default:
975 $filters = mailbox('get', 'filters', $object);
976 if (!empty($filters)) {
977 foreach ($filters as $filter) {
978 if ($details = mailbox('get', 'filter_details', $filter)) {
979 $data[] = $details;
980 }
981 else {
982 continue;
983 }
984 }
985 }
986 process_get_return($data);
987 break;
988 }
989 break;
990 case "bcc":
991 switch ($object) {
992 case "all":
993 $bcc_items = bcc('get');
994 if (!empty($bcc_items)) {
995 foreach ($bcc_items as $bcc_item) {
996 if ($details = bcc('details', $bcc_item)) {
997 $data[] = $details;
998 }
999 else {
1000 continue;
1001 }
1002 }
1003 }
1004 process_get_return($data);
1005 break;
1006 default:
1007 $data = bcc('details', $object);
1008 if (!empty($data)) {
1009 $data[] = $details;
1010 }
1011 process_get_return($data);
1012 break;
1013 }
1014 break;
1015 case "recipient_map":
1016 switch ($object) {
1017 case "all":
1018 $recipient_map_items = recipient_map('get');
1019 if (!empty($recipient_map_items)) {
1020 foreach ($recipient_map_items as $recipient_map_item) {
1021 if ($details = recipient_map('details', $recipient_map_item)) {
1022 $data[] = $details;
1023 }
1024 else {
1025 continue;
1026 }
1027 }
1028 }
1029 process_get_return($data);
1030 break;
1031 default:
1032 $data = recipient_map('details', $object);
1033 if (!empty($data)) {
1034 $data[] = $details;
1035 }
1036 process_get_return($data);
1037 break;
1038 }
1039 break;
1040 case "tls-policy-map":
1041 switch ($object) {
1042 case "all":
1043 $tls_policy_maps_items = tls_policy_maps('get');
1044 if (!empty($tls_policy_maps_items)) {
1045 foreach ($tls_policy_maps_items as $tls_policy_maps_item) {
1046 if ($details = tls_policy_maps('details', $tls_policy_maps_item)) {
1047 $data[] = $details;
1048 }
1049 else {
1050 continue;
1051 }
1052 }
1053 }
1054 process_get_return($data);
1055 break;
1056 default:
1057 $data = tls_policy_maps('details', $object);
1058 if (!empty($data)) {
1059 $data[] = $details;
1060 }
1061 process_get_return($data);
1062 break;
1063 }
1064 break;
1065 case "policy_wl_mailbox":
1066 switch ($object) {
1067 default:
1068 $data = policy('get', 'mailbox', $object)['whitelist'];
1069 process_get_return($data);
1070 break;
1071 }
1072 break;
1073 case "policy_bl_mailbox":
1074 switch ($object) {
1075 default:
1076 $data = policy('get', 'mailbox', $object)['blacklist'];
1077 process_get_return($data);
1078 break;
1079 }
1080 break;
1081 case "policy_wl_domain":
1082 switch ($object) {
1083 default:
1084 $data = policy('get', 'domain', $object)['whitelist'];
1085 process_get_return($data);
1086 break;
1087 }
1088 break;
1089 case "policy_bl_domain":
1090 switch ($object) {
1091 default:
1092 $data = policy('get', 'domain', $object)['blacklist'];
1093 process_get_return($data);
1094 break;
1095 }
1096 break;
1097 case "time_limited_aliases":
1098 switch ($object) {
1099 default:
1100 $data = mailbox('get', 'time_limited_aliases', $object);
1101 process_get_return($data);
1102 break;
1103 }
1104 break;
1105 case "fail2ban":
1106 switch ($object) {
1107 default:
1108 $data = fail2ban('get');
1109 process_get_return($data);
1110 break;
1111 }
1112 break;
1113 case "resource":
1114 switch ($object) {
1115 case "all":
1116 $domains = mailbox('get', 'domains');
1117 if (!empty($domains)) {
1118 foreach ($domains as $domain) {
1119 $resources = mailbox('get', 'resources', $domain);
1120 if (!empty($resources)) {
1121 foreach ($resources as $resource) {
1122 if ($details = mailbox('get', 'resource_details', $resource)) {
1123 $data[] = $details;
1124 }
1125 else {
1126 continue;
1127 }
1128 }
1129 }
1130 }
1131 process_get_return($data);
1132 }
1133 else {
1134 echo '{}';
1135 }
1136 break;
1137 default:
1138 $data = mailbox('get', 'resource_details', $object);
1139 process_get_return($data);
1140 break;
1141 }
1142 break;
1143 case "fwdhost":
1144 switch ($object) {
1145 case "all":
1146 process_get_return(fwdhost('get'));
1147 break;
1148 default:
1149 process_get_return(fwdhost('details', $object));
1150 break;
1151 }
1152 break;
1153 case "quarantine":
1154 // "all" will not print details
1155 switch ($object) {
1156 case "all":
1157 process_get_return(quarantine('get'));
1158 break;
1159 default:
1160 process_get_return(quarantine('details', $object));
1161 break;
1162 }
1163 break;
1164 case "alias-domain":
1165 switch ($object) {
1166 case "all":
1167 $alias_domains = mailbox('get', 'alias_domains');
1168 if (!empty($alias_domains)) {
1169 foreach ($alias_domains as $alias_domain) {
1170 if ($details = mailbox('get', 'alias_domain_details', $alias_domain)) {
1171 $data[] = $details;
1172 }
1173 else {
1174 continue;
1175 }
1176 }
1177 }
1178 process_get_return($data);
1179 break;
1180 default:
1181 process_get_return(mailbox('get', 'alias_domain_details', $object));
1182 break;
1183 }
1184 break;
1185 case "alias":
1186 switch ($object) {
1187 case "all":
1188 if (empty($extra)) {
1189 $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
1190 }
1191 else {
1192 $domains = array($extra);
1193 }
1194 if (!empty($domains)) {
1195 foreach ($domains as $domain) {
1196 $aliases = mailbox('get', 'aliases', $domain);
1197 if (!empty($aliases)) {
1198 foreach ($aliases as $alias) {
1199 if ($details = mailbox('get', 'alias_details', $alias)) {
1200 $data[] = $details;
1201 }
1202 else {
1203 continue;
1204 }
1205 }
1206 }
1207 }
1208 process_get_return($data);
1209 }
1210 else {
1211 echo '{}';
1212 }
1213 break;
1214
1215 default:
1216 process_get_return(mailbox('get', 'alias_details', $object));
1217 break;
1218 }
1219 break;
1220 case "domain-admin":
1221 switch ($object) {
1222 case "all":
1223 $domain_admins = domain_admin('get');
1224 if (!empty($domain_admins)) {
1225 foreach ($domain_admins as $domain_admin) {
1226 if ($details = domain_admin('details', $domain_admin)) {
1227 $data[] = $details;
1228 }
1229 else {
1230 continue;
1231 }
1232 }
1233 process_get_return($data);
1234 }
1235 else {
1236 echo '{}';
1237 }
1238 break;
1239
1240 default:
1241 process_get_return(domain_admin('details', $object));
1242 break;
1243 }
1244 break;
1245 case "admin":
1246 switch ($object) {
1247 case "all":
1248 $admins = admin('get');
1249 if (!empty($admins)) {
1250 foreach ($admins as $admin) {
1251 if ($details = admin('details', $admin)) {
1252 $data[] = $details;
1253 }
1254 else {
1255 continue;
1256 }
1257 }
1258 process_get_return($data);
1259 }
1260 else {
1261 echo '{}';
1262 }
1263 break;
1264
1265 default:
1266 process_get_return(admin('details', $object));
1267 break;
1268 }
1269 break;
1270 case "dkim":
1271 switch ($object) {
1272 default:
1273 $data = dkim('details', $object);
1274 process_get_return($data);
1275 break;
1276 }
1277 break;
1278 case "presets":
1279 switch ($object) {
1280 case "rspamd":
1281 process_get_return(presets('get', 'rspamd'));
1282 break;
1283 case "sieve":
1284 process_get_return(presets('get', 'sieve'));
1285 break;
1286 }
1287 break;
1288 case "status":
1289 if ($_SESSION['mailcow_cc_role'] == "admin") {
1290 switch ($object) {
1291 case "containers":
1292 $containers = (docker('info'));
1293 foreach ($containers as $container => $container_info) {
1294 $container . ' (' . $container_info['Config']['Image'] . ')';
1295 $containerstarttime = ($container_info['State']['StartedAt']);
1296 $containerstate = ($container_info['State']['Status']);
1297 $containerimage = ($container_info['Config']['Image']);
1298 $temp[$container] = array(
1299 'type' => 'info',
1300 'container' => $container,
1301 'state' => $containerstate,
1302 'started_at' => $containerstarttime,
1303 'image' => $containerimage
1304 );
1305 }
1306 echo json_encode($temp, JSON_UNESCAPED_SLASHES);
1307 break;
1308 case "vmail":
1309 $exec_fields_vmail = array('cmd' => 'system', 'task' => 'df', 'dir' => '/var/vmail');
1310 $vmail_df = explode(',', json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields_vmail), true));
1311 $temp = array(
1312 'type' => 'info',
1313 'disk' => $vmail_df[0],
1314 'used' => $vmail_df[2],
1315 'total'=> $vmail_df[1],
1316 'used_percent' => $vmail_df[4]
1317 );
1318 echo json_encode($temp, JSON_UNESCAPED_SLASHES);
1319 break;
1320 case "solr":
1321 $solr_status = solr_status();
1322 $solr_size = ($solr_status['status']['dovecot-fts']['index']['size']);
1323 $solr_documents = ($solr_status['status']['dovecot-fts']['index']['numDocs']);
1324 if (strtolower(getenv('SKIP_SOLR')) != 'n') {
1325 $solr_enabled = false;
1326 }
1327 else {
1328 $solr_enabled = true;
1329 }
1330 echo json_encode(array(
1331 'type' => 'info',
1332 'solr_enabled' => $solr_enabled,
1333 'solr_size' => $solr_size,
1334 'solr_documents' => $solr_documents
1335 ));
1336 break;
1337 }
1338 }
1339 break;
1340 break;
1341 // return no route found if no case is matched
1342 default:
1343 http_response_code(404);
1344 echo json_encode(array(
1345 'type' => 'error',
1346 'msg' => 'route not found'
1347 ));
1348 exit();
1349 }
1350 }
1351 break;
1352 case "delete":
1353 if ($_SESSION['mailcow_cc_api_access'] == 'ro' || isset($_SESSION['pending_mailcow_cc_username']) || !isset($_SESSION["mailcow_cc_username"])) {
1354 http_response_code(403);
1355 echo json_encode(array(
1356 'type' => 'error',
1357 'msg' => 'API read/write access denied'
1358 ));
1359 exit();
1360 }
1361 function process_delete_return($return) {
1362 $generic_failure = json_encode(array(
1363 'type' => 'error',
1364 'msg' => 'Cannot delete item'
1365 ));
1366 $generic_success = json_encode(array(
1367 'type' => 'success',
1368 'msg' => 'Task completed'
1369 ));
1370 if ($return === false) {
1371 echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_failure;
1372 }
1373 else {
1374 echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_success;
1375 }
1376 }
1377 if (!isset($_POST['items'])) {
1378 echo $request_incomplete;
1379 exit;
1380 }
1381 else {
1382 $items = (array)json_decode($_POST['items'], true);
1383 }
1384 // only allow POST requests to POST API endpoints
1385 if ($_SERVER['REQUEST_METHOD'] != 'POST') {
1386 http_response_code(405);
1387 echo json_encode(array(
1388 'type' => 'error',
1389 'msg' => 'only POST method is allowed'
1390 ));
1391 exit();
1392 }
1393 switch ($category) {
1394 case "alias":
1395 process_delete_return(mailbox('delete', 'alias', array('id' => $items)));
1396 break;
1397 case "oauth2-client":
1398 process_delete_return(oauth2('delete', 'client', array('id' => $items)));
1399 break;
1400 case "app-passwd":
1401 process_delete_return(app_passwd('delete', array('id' => $items)));
1402 break;
1403 case "relayhost":
1404 process_delete_return(relayhost('delete', array('id' => $items)));
1405 break;
1406 case "transport":
1407 process_delete_return(transport('delete', array('id' => $items)));
1408 break;
1409 case "rsetting":
1410 process_delete_return(rsettings('delete', array('id' => $items)));
1411 break;
1412 case "syncjob":
1413 process_delete_return(mailbox('delete', 'syncjob', array('id' => $items)));
1414 break;
1415 case "filter":
1416 process_delete_return(mailbox('delete', 'filter', array('id' => $items)));
1417 break;
1418 case "mailq":
1419 process_delete_return(mailq('delete', array('qid' => $items)));
1420 break;
1421 case "qitem":
1422 process_delete_return(quarantine('delete', array('id' => $items)));
1423 break;
1424 case "bcc":
1425 process_delete_return(bcc('delete', array('id' => $items)));
1426 break;
1427 case "recipient_map":
1428 process_delete_return(recipient_map('delete', array('id' => $items)));
1429 break;
1430 case "tls-policy-map":
1431 process_delete_return(tls_policy_maps('delete', array('id' => $items)));
1432 break;
1433 case "fwdhost":
1434 process_delete_return(fwdhost('delete', array('forwardinghost' => $items)));
1435 break;
1436 case "dkim":
1437 process_delete_return(dkim('delete', array('domains' => $items)));
1438 break;
1439 case "domain":
1440 file_put_contents('/tmp/dssaa', $items);
1441 process_delete_return(mailbox('delete', 'domain', array('domain' => $items)));
1442 break;
1443 case "alias-domain":
1444 process_delete_return(mailbox('delete', 'alias_domain', array('alias_domain' => $items)));
1445 break;
1446 case "mailbox":
1447 process_delete_return(mailbox('delete', 'mailbox', array('username' => $items)));
1448 break;
1449 case "resource":
1450 process_delete_return(mailbox('delete', 'resource', array('name' => $items)));
1451 break;
1452 case "mailbox-policy":
1453 process_delete_return(policy('delete', 'mailbox', array('prefid' => $items)));
1454 break;
1455 case "domain-policy":
1456 process_delete_return(policy('delete', 'domain', array('prefid' => $items)));
1457 break;
1458 case "time_limited_alias":
1459 process_delete_return(mailbox('delete', 'time_limited_alias', array('address' => $items)));
1460 break;
1461 case "eas_cache":
1462 process_delete_return(mailbox('delete', 'eas_cache', array('username' => $items)));
1463 break;
1464 case "sogo_profile":
1465 process_delete_return(mailbox('delete', 'sogo_profile', array('username' => $items)));
1466 break;
1467 case "domain-admin":
1468 process_delete_return(domain_admin('delete', array('username' => $items)));
1469 break;
1470 case "admin":
1471 process_delete_return(admin('delete', array('username' => $items)));
1472 break;
1473 case "rlhash":
1474 echo ratelimit('delete', null, implode($items));
1475 break;
1476 // return no route found if no case is matched
1477 default:
1478 http_response_code(404);
1479 echo json_encode(array(
1480 'type' => 'error',
1481 'msg' => 'route not found'
1482 ));
1483 exit();
1484 }
1485 break;
1486 case "edit":
1487 if ($_SESSION['mailcow_cc_api_access'] == 'ro' || isset($_SESSION['pending_mailcow_cc_username']) || !isset($_SESSION["mailcow_cc_username"])) {
1488 http_response_code(403);
1489 echo json_encode(array(
1490 'type' => 'error',
1491 'msg' => 'API read/write access denied'
1492 ));
1493 exit();
1494 }
1495 function process_edit_return($return) {
1496 $generic_failure = json_encode(array(
1497 'type' => 'error',
1498 'msg' => 'Cannot edit item'
1499 ));
1500 $generic_success = json_encode(array(
1501 'type' => 'success',
1502 'msg' => 'Task completed'
1503 ));
1504 if ($return === false) {
1505 echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_failure;
1506 }
1507 else {
1508 echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_success;
1509 }
1510 }
1511 if (!isset($_POST['attr'])) {
1512 echo $request_incomplete;
1513 exit;
1514 }
1515 else {
1516 $attr = (array)json_decode($_POST['attr'], true);
1517 unset($attr['csrf_token']);
1518 $items = isset($_POST['items']) ? (array)json_decode($_POST['items'], true) : null;
1519 }
1520 // only allow POST requests to POST API endpoints
1521 if ($_SERVER['REQUEST_METHOD'] != 'POST') {
1522 http_response_code(405);
1523 echo json_encode(array(
1524 'type' => 'error',
1525 'msg' => 'only POST method is allowed'
1526 ));
1527 exit();
1528 }
1529 switch ($category) {
1530 case "bcc":
1531 process_edit_return(bcc('edit', array_merge(array('id' => $items), $attr)));
1532 break;
1533 case "pushover":
1534 process_edit_return(pushover('edit', array_merge(array('username' => $items), $attr)));
1535 break;
1536 case "pushover-test":
1537 process_edit_return(pushover('test', array_merge(array('username' => $items), $attr)));
1538 break;
1539 case "oauth2-client":
1540 process_edit_return(oauth2('edit', 'client', array_merge(array('id' => $items), $attr)));
1541 break;
1542 case "recipient_map":
1543 process_edit_return(recipient_map('edit', array_merge(array('id' => $items), $attr)));
1544 break;
1545 case "app-passwd":
1546 process_edit_return(app_passwd('edit', array_merge(array('id' => $items), $attr)));
1547 break;
1548 case "tls-policy-map":
1549 process_edit_return(tls_policy_maps('edit', array_merge(array('id' => $items), $attr)));
1550 break;
1551 case "alias":
1552 process_edit_return(mailbox('edit', 'alias', array_merge(array('id' => $items), $attr)));
1553 break;
1554 case "rspamd-map":
1555 process_edit_return(rspamd_maps('edit', array_merge(array('map' => $items), $attr)));
1556 break;
1557 case "fido2-fn":
1558 process_edit_return(fido2(array('action' => 'edit_fn', 'fido2_attrs' => $attr)));
1559 break;
1560 case "app_links":
1561 process_edit_return(customize('edit', 'app_links', $attr));
1562 break;
1563 case "relayhost":
1564 process_edit_return(relayhost('edit', array_merge(array('id' => $items), $attr)));
1565 break;
1566 case "transport":
1567 process_edit_return(transport('edit', array_merge(array('id' => $items), $attr)));
1568 break;
1569 case "rsetting":
1570 process_edit_return(rsettings('edit', array_merge(array('id' => $items), $attr)));
1571 break;
1572 case "delimiter_action":
1573 process_edit_return(mailbox('edit', 'delimiter_action', array_merge(array('username' => $items), $attr)));
1574 break;
1575 case "tls_policy":
1576 process_edit_return(mailbox('edit', 'tls_policy', array_merge(array('username' => $items), $attr)));
1577 break;
1578 case "quarantine_notification":
1579 process_edit_return(mailbox('edit', 'quarantine_notification', array_merge(array('username' => $items), $attr)));
1580 break;
1581 case "quarantine_category":
1582 process_edit_return(mailbox('edit', 'quarantine_category', array_merge(array('username' => $items), $attr)));
1583 break;
1584 case "qitem":
1585 process_edit_return(quarantine('edit', array_merge(array('id' => $items), $attr)));
1586 break;
1587 case "quarantine":
1588 process_edit_return(quarantine('edit', $attr));
1589 break;
1590 case "quota_notification":
1591 process_edit_return(quota_notification('edit', $attr));
1592 break;
1593 case "mailq":
1594 process_edit_return(mailq('edit', array_merge(array('qid' => $items), $attr)));
1595 break;
1596 case "time_limited_alias":
1597 process_edit_return(mailbox('edit', 'time_limited_alias', array_merge(array('address' => $items), $attr)));
1598 break;
1599 case "mailbox":
1600 process_edit_return(mailbox('edit', 'mailbox', array_merge(array('username' => $items), $attr)));
1601 break;
1602 case "syncjob":
1603 process_edit_return(mailbox('edit', 'syncjob', array_merge(array('id' => $items), $attr)));
1604 break;
1605 case "filter":
1606 process_edit_return(mailbox('edit', 'filter', array_merge(array('id' => $items), $attr)));
1607 break;
1608 case "resource":
1609 process_edit_return(mailbox('edit', 'resource', array_merge(array('name' => $items), $attr)));
1610 break;
1611 case "domain":
1612 process_edit_return(mailbox('edit', 'domain', array_merge(array('domain' => $items), $attr)));
1613 break;
1614 case "rl-domain":
1615 process_edit_return(ratelimit('edit', 'domain', array_merge(array('object' => $items), $attr)));
1616 break;
1617 case "rl-mbox":
1618 process_edit_return(ratelimit('edit', 'mailbox', array_merge(array('object' => $items), $attr)));
1619 break;
1620 case "user-acl":
1621 process_edit_return(acl('edit', 'user', array_merge(array('username' => $items), $attr)));
1622 break;
1623 case "da-acl":
1624 process_edit_return(acl('edit', 'domainadmin', array_merge(array('username' => $items), $attr)));
1625 break;
1626 case "alias-domain":
1627 process_edit_return(mailbox('edit', 'alias_domain', array_merge(array('alias_domain' => $items), $attr)));
1628 break;
1629 case "spam-score":
1630 process_edit_return(mailbox('edit', 'spam_score', array_merge(array('username' => $items), $attr)));
1631 break;
1632 case "domain-admin":
1633 process_edit_return(domain_admin('edit', array_merge(array('username' => $items), $attr)));
1634 break;
1635 case "admin":
1636 process_edit_return(admin('edit', array_merge(array('username' => $items), $attr)));
1637 break;
1638 case "fwdhost":
1639 process_edit_return(fwdhost('edit', array_merge(array('fwdhost' => $items), $attr)));
1640 break;
1641 case "fail2ban":
1642 process_edit_return(fail2ban('edit', array_merge(array('network' => $items), $attr)));
1643 break;
1644 case "ui_texts":
1645 process_edit_return(customize('edit', 'ui_texts', $attr));
1646 break;
1647 case "self":
1648 if ($_SESSION['mailcow_cc_role'] == "domainadmin") {
1649 process_edit_return(domain_admin('edit', $attr));
1650 }
1651 elseif ($_SESSION['mailcow_cc_role'] == "user") {
1652 process_edit_return(edit_user_account($attr));
1653 }
1654 break;
1655 // return no route found if no case is matched
1656 default:
1657 http_response_code(404);
1658 echo json_encode(array(
1659 'type' => 'error',
1660 'msg' => 'route not found'
1661 ));
1662 exit();
1663 }
1664 break;
1665 // return no route found if no case is matched
1666 default:
1667 http_response_code(404);
1668 echo json_encode(array(
1669 'type' => 'error',
1670 'msg' => 'route not found'
1671 ));
1672 exit();
1673 }
1674}
1675if ($_SESSION['mailcow_cc_api'] === true) {
1676 if (isset($_SESSION['mailcow_cc_api']) && $_SESSION['mailcow_cc_api'] === true) {
1677 unset($_SESSION['return']);
1678 }
1679}