git subrepo commit (merge) mailcow/src/mailcow-dockerized

subrepo: subdir:   "mailcow/src/mailcow-dockerized"
  merged:   "f83239ed"
upstream: origin:   "https://github.com/mailcow/mailcow-dockerized.git"
  branch:   "master"
  commit:   "7627a7a9"
git-subrepo: version:  "0.4.6"
  origin:   "???"
  commit:   "???"
Change-Id: I88e430779f11ac9848e81a9e4eae549100ed1f94
diff --git a/mailcow/src/mailcow-dockerized/data/web/json_api.php b/mailcow/src/mailcow-dockerized/data/web/json_api.php
index b375bc8..28f8cac 100644
--- a/mailcow/src/mailcow-dockerized/data/web/json_api.php
+++ b/mailcow/src/mailcow-dockerized/data/web/json_api.php
@@ -15,7 +15,7 @@
       continue;

     }

 

-    $value = json_decode($value, true);     

+    $value = json_decode($value, true);

     if ($value) {

       if (is_array($value)) unset($value["csrf_token"]);

       foreach ($value as $key => &$val) {

@@ -23,7 +23,7 @@
           $val = '*';

         }

       }

-      $value = json_encode($value);  

+      $value = json_encode($value);

     }

     $data_var[] = $data . "='" . $value . "'";

   }

@@ -44,7 +44,7 @@
       'msg' => 'Redis: '.$e

     );

     return false;

-  }     

+  }

 }

 

 if (isset($_GET['query'])) {

@@ -178,12 +178,12 @@
               // parse post data

               $post = trim(file_get_contents('php://input'));

               if ($post) $post = json_decode($post);

-              

+

               // process registration data from authenticator

               try {

                 // decode base64 strings

                 $clientDataJSON = base64_decode($post->clientDataJSON);

-                $attestationObject = base64_decode($post->attestationObject);   

+                $attestationObject = base64_decode($post->attestationObject);

 

                 // processCreate($clientDataJSON, $attestationObject, $challenge, $requireUserVerification=false, $requireUserPresent=true, $failIfRootMismatch=true)

                 $data = $WebAuthn->processCreate($clientDataJSON, $attestationObject, $_SESSION['challenge'], false, true);

@@ -250,7 +250,7 @@
             default:

               process_add_return(mailbox('add', 'domain', $attr));

             break;

-          }  

+          }

         break;

         case "resource":

           process_add_return(mailbox('add', 'resource', $attr));

@@ -470,7 +470,7 @@
               //        false, if only internal is allowed

               //        null, if internal and cross-platform is allowed

               $createArgs = $WebAuthn->getCreateArgs($_SESSION["mailcow_cc_username"], $_SESSION["mailcow_cc_username"], $_SESSION["mailcow_cc_username"], 30, false, $GLOBALS['WEBAUTHN_UV_FLAG_REGISTER'], null, $excludeCredentialIds);

-              

+

               print(json_encode($createArgs));

               $_SESSION['challenge'] = $WebAuthn->getChallenge();

               return;

@@ -503,6 +503,16 @@
           print(json_encode($getArgs));

           $_SESSION['challenge'] = $WebAuthn->getChallenge();

           return;

+        break;          

+        case "fail2ban":

+          if (!isset($_SESSION['mailcow_cc_role'])){

+            switch ($object) {

+              case 'banlist':

+                header('Content-Type: text/plain');

+                echo fail2ban('banlist', 'get', $extra);

+              break;

+            }

+          }

         break;

       }

       if (isset($_SESSION['mailcow_cc_role'])) {

@@ -523,9 +533,50 @@
 

           case "domain":

             switch ($object) {

+              case "datatables":

+                $table = ['domain', 'd'];

+                $primaryKey = 'domain';

+                $columns = [

+                  ['db' => 'domain', 'dt' => 2],

+                  ['db' => 'aliases', 'dt' => 3, 'order_subquery' => "SELECT COUNT(*) FROM `alias` WHERE (`domain`= `d`.`domain` OR `domain` IN (SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = `d`.`domain`)) AND `address` NOT IN (SELECT `username` FROM `mailbox`)"],

+                  ['db' => 'mailboxes', 'dt' => 4, 'order_subquery' => "SELECT COUNT(*) FROM `mailbox` WHERE `mailbox`.`domain` = `d`.`domain` AND (`mailbox`.`kind` = '' OR `mailbox`.`kind` = NULL)"],

+                  ['db' => 'quota', 'dt' => 5, 'order_subquery' => "SELECT COALESCE(SUM(`mailbox`.`quota`), 0) FROM `mailbox` WHERE `mailbox`.`domain` = `d`.`domain` AND (`mailbox`.`kind` = '' OR `mailbox`.`kind` = NULL)"],

+                  ['db' => 'stats', 'dt' => 6, 'dummy' => true, 'order_subquery' => "SELECT SUM(bytes) FROM `quota2` WHERE `quota2`.`username` IN (SELECT `username` FROM `mailbox` WHERE `domain` = `d`.`domain`)"],

+                  ['db' => 'defquota', 'dt' => 7],

+                  ['db' => 'maxquota', 'dt' => 8],

+                  ['db' => 'backupmx', 'dt' => 10],

+                  ['db' => 'tags', 'dt' => 14, 'dummy' => true, 'search' => ['join' => 'LEFT JOIN `tags_domain` AS `td` ON `td`.`domain` = `d`.`domain`', 'where_column' => '`td`.`tag_name`']],

+                  ['db' => 'active', 'dt' => 15],

+                ];

+

+                require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/ssp.class.php';

+                global $pdo;

+                if($_SESSION['mailcow_cc_role'] === 'admin') {

+                  $data = SSP::simple($_GET, $pdo, $table, $primaryKey, $columns);

+                } elseif ($_SESSION['mailcow_cc_role'] === 'domainadmin') {

+                  $data = SSP::complex($_GET, $pdo, $table, $primaryKey, $columns,

+                    'INNER JOIN domain_admins as da ON da.domain = d.domain',

+                    [

+                      'condition' => 'da.active = 1 and da.username = :username',

+                      'bindings' => ['username' => $_SESSION['mailcow_cc_username']]

+                    ]);

+                }

+

+                if (!empty($data['data'])) {

+                  $domainsData = [];

+                  foreach ($data['data'] as $domain) {

+                    if ($details = mailbox('get', 'domain_details', $domain[2])) {

+                      $domainsData[] = $details;

+                    }

+                  }

+                  $data['data'] = $domainsData;

+                }

+

+                process_get_return($data);

+              break;

               case "all":

                 $tags = null;

-                if (isset($_GET['tags']) && $_GET['tags'] != '') 

+                if (isset($_GET['tags']) && $_GET['tags'] != '')

                   $tags = explode(',', $_GET['tags']);

 

                 $domains = mailbox('get', 'domains', null, $tags);

@@ -1011,10 +1062,49 @@
           break;

           case "mailbox":

             switch ($object) {

+              case "datatables":

+                $table = ['mailbox', 'm'];

+                $primaryKey = 'username';

+                $columns = [

+                  ['db' => 'username', 'dt' => 2],

+                  ['db' => 'quota', 'dt' => 3],

+                  ['db' => 'last_mail_login', 'dt' => 4, 'dummy' => true, 'order_subquery' => "SELECT MAX(`datetime`) FROM `sasl_log` WHERE `service` != 'SSO' AND `username` = `m`.`username`"],

+                  ['db' => 'last_pw_change', 'dt' => 5, 'dummy' => true, 'order_subquery' => "JSON_EXTRACT(attributes, '$.passwd_update')"],

+                  ['db' => 'in_use', 'dt' => 6, 'dummy' => true, 'order_subquery' => "(SELECT SUM(bytes) FROM `quota2` WHERE `quota2`.`username` = `m`.`username`) / `m`.`quota`"],

+                  ['db' => 'messages', 'dt' => 17, 'dummy' => true, 'order_subquery' => "SELECT SUM(messages) FROM `quota2` WHERE `quota2`.`username` = `m`.`username`"],

+                  ['db' => 'tags', 'dt' => 20, 'dummy' => true, 'search' => ['join' => 'LEFT JOIN `tags_mailbox` AS `tm` ON `tm`.`username` = `m`.`username`', 'where_column' => '`tm`.`tag_name`']],

+                  ['db' => 'active', 'dt' => 21]

+                ];

+

+                require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/ssp.class.php';

+                global $pdo;

+                if($_SESSION['mailcow_cc_role'] === 'admin') {

+                  $data = SSP::complex($_GET, $pdo, $table, $primaryKey, $columns, null, "(`m`.`kind` = '' OR `m`.`kind` = NULL)");

+                } elseif ($_SESSION['mailcow_cc_role'] === 'domainadmin') {

+                  $data = SSP::complex($_GET, $pdo, $table, $primaryKey, $columns,

+                    'INNER JOIN domain_admins as da ON da.domain = m.domain',

+                    [

+                      'condition' => "(`m`.`kind` = '' OR `m`.`kind` = NULL) AND `da`.`active` = 1 AND `da`.`username` = :username",

+                      'bindings' => ['username' => $_SESSION['mailcow_cc_username']]

+                    ]);

+                }

+

+                if (!empty($data['data'])) {

+                  $mailboxData = [];

+                  foreach ($data['data'] as $mailbox) {

+                    if ($details = mailbox('get', 'mailbox_details', $mailbox[2])) {

+                      $mailboxData[] = $details;

+                    }

+                  }

+                  $data['data'] = $mailboxData;

+                }

+

+                process_get_return($data);

+              break;

               case "all":

               case "reduced":

                 $tags = null;

-                if (isset($_GET['tags']) && $_GET['tags'] != '') 

+                if (isset($_GET['tags']) && $_GET['tags'] != '')

                   $tags = explode(',', $_GET['tags']);

 

                 if (empty($extra)) $domains = mailbox('get', 'domains');

@@ -1048,7 +1138,7 @@
               break;

               default:

                 $tags = null;

-                if (isset($_GET['tags']) && $_GET['tags'] != '') 

+                if (isset($_GET['tags']) && $_GET['tags'] != '')

                   $tags = explode(',', $_GET['tags']);

 

                 if ($tags === null) {

@@ -1058,7 +1148,7 @@
                   $mailboxes = mailbox('get', 'mailboxes', $object, $tags);

                   if (is_array($mailboxes)) {

                     foreach ($mailboxes as $mailbox) {

-                      if ($details = mailbox('get', 'mailbox_details', $mailbox)) 

+                      if ($details = mailbox('get', 'mailbox_details', $mailbox))

                         $data[] = $details;

                     }

                   }

@@ -1324,6 +1414,10 @@
           break;

           case "fail2ban":

             switch ($object) {

+              case 'banlist':

+                header('Content-Type: text/plain');

+                echo fail2ban('banlist', 'get', $extra);

+              break;

               default:

                 $data = fail2ban('get');

                 process_get_return($data);

@@ -1557,15 +1651,15 @@
                     'solr_size' => $solr_size,

                     'solr_documents' => $solr_documents

                   ));

-                break;  

+                break;

                 case "host":

                   if (!$extra){

                     $stats = docker("host_stats");

                     echo json_encode($stats);

-                  } 

+                  }

                   else if ($extra == "ip") {

                     // get public ips

-                    

+

                     $curl = curl_init();

                     curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

                     curl_setopt($curl, CURLOPT_POST, 0);

@@ -1591,6 +1685,12 @@
               }

             }

           break;

+          case "spam-score":

+            $score = mailbox('get', 'spam_score', $object);

+            if ($score)

+              $score = array("score" => preg_replace("/\s+/", "", $score));

+            process_get_return($score);

+          break;

         break;

         // return no route found if no case is matched

         default:

@@ -1867,8 +1967,6 @@
         case "quota_notification_bcc":

           process_edit_return(quota_notification_bcc('edit', $attr));

         break;

-        case "domain-wide-footer":

-          process_edit_return(mailbox('edit', 'domain_wide_footer', $attr));

         break;

         case "mailq":

           process_edit_return(mailq('edit', array_merge(array('qid' => $items), $attr)));

@@ -1881,6 +1979,9 @@
             case "template":

               process_edit_return(mailbox('edit', 'mailbox_templates', array_merge(array('ids' => $items), $attr)));

             break;

+            case "custom-attribute":

+              process_edit_return(mailbox('edit', 'mailbox_custom_attribute', array_merge(array('mailboxes' => $items), $attr)));

+            break;

             default:

               process_edit_return(mailbox('edit', 'mailbox', array_merge(array('username' => $items), $attr)));

             break;

@@ -1900,6 +2001,9 @@
             case "template":

               process_edit_return(mailbox('edit', 'domain_templates', array_merge(array('ids' => $items), $attr)));

             break;

+            case "footer":

+              process_edit_return(mailbox('edit', 'domain_wide_footer', array_merge(array('domains' => $items), $attr)));

+            break;

             default:

               process_edit_return(mailbox('edit', 'domain', array_merge(array('domain' => $items), $attr)));

             break;

@@ -1933,7 +2037,14 @@
           process_edit_return(fwdhost('edit', array_merge(array('fwdhost' => $items), $attr)));

         break;

         case "fail2ban":

-          process_edit_return(fail2ban('edit', array_merge(array('network' => $items), $attr)));

+          switch ($object) {

+            case 'banlist':

+              process_edit_return(fail2ban('banlist', 'refresh', $items));

+            break;

+            default:

+              process_edit_return(fail2ban('edit', array_merge(array('network' => $items), $attr)));

+            break;

+          }

         break;

         case "ui_texts":

           process_edit_return(customize('edit', 'ui_texts', $attr));

@@ -1972,7 +2083,7 @@
       exit();

   }

 }

-if ($_SESSION['mailcow_cc_api'] === true) {

+if (array_key_exists('mailcow_cc_api', $_SESSION) && $_SESSION['mailcow_cc_api'] === true) {

   if (isset($_SESSION['mailcow_cc_api']) && $_SESSION['mailcow_cc_api'] === true) {

     unset($_SESSION['return']);

   }