Przeglądaj źródła

Further migration

andryyy 8 lat temu
rodzic
commit
56a9a09e2f

+ 21 - 16
data/web/admin.php

@@ -32,7 +32,7 @@ $tfa_data = get_tfa();
     <div class="panel panel-danger">
     <div class="panel panel-danger">
       <div class="panel-heading"><?=$lang['admin']['admin_details'];?></div>
       <div class="panel-heading"><?=$lang['admin']['admin_details'];?></div>
       <div class="panel-body">
       <div class="panel-body">
-        <form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
+        <form class="form-horizontal" autocapitalize="none" data-id="admin" autocorrect="off" role="form" method="post">
         <?php $admindetails = get_admin_details(); ?>
         <?php $admindetails = get_admin_details(); ?>
           <div class="form-group">
           <div class="form-group">
             <label class="control-label col-sm-3" for="admin_user"><?=$lang['admin']['admin'];?>:</label>
             <label class="control-label col-sm-3" for="admin_user"><?=$lang['admin']['admin'];?>:</label>
@@ -55,7 +55,7 @@ $tfa_data = get_tfa();
           </div>
           </div>
           <div class="form-group">
           <div class="form-group">
             <div class="col-sm-offset-3 col-sm-9">
             <div class="col-sm-offset-3 col-sm-9">
-              <button type="submit" name="edit_admin_account" class="btn btn-default"><?=$lang['admin']['save'];?></button>
+              <button class="btn btn-default" id="edit_selected" data-id="admin" data-item="null" data-api-url='edit/admin' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
             </div>
             </div>
           </div>
           </div>
         </form>
         </form>
@@ -94,20 +94,27 @@ $tfa_data = get_tfa();
       </div>
       </div>
     </div>
     </div>
     <div class="panel panel-default">
     <div class="panel panel-default">
-    <div style="cursor:pointer;" class="panel-heading" data-toggle="collapse" data-parent="#accordion_access" data-target="#collapseDomAdmins">
-      <span class="accordion-toggle"><?=$lang['admin']['domain_admins'];?></span>
-    </div>
-      <div id="collapseDomAdmins" class="panel-collapse collapse">
+    <div class="panel-heading"><?=$lang['admin']['domain_admins'];?></div>
         <div class="panel-body">
         <div class="panel-body">
-          <form method="post">
-            <div class="table-responsive">
+          <div class="table-responsive">
             <table class="table table-striped" id="domainadminstable"></table>
             <table class="table table-striped" id="domainadminstable"></table>
+          </div>
+          <div class="mass-actions-admin">
+            <div class="btn-group">
+              <a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="domain_admins" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
+              <a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
+              <ul class="dropdown-menu">
+                <li><a id="edit_selected" data-id="domain_admins" data-api-url='edit/domain_admin' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
+                <li><a id="edit_selected" data-id="domain_admins" data-api-url='edit/domain_admin' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
+                <li role="separator" class="divider"></li>
+                <li><a id="edit_selected" data-id="domain_admins" data-api-url='edit/domain_admin' data-api-attr='{"disable_tfa":"1"}' href="#"><?=$lang['tfa']['disable_tfa'];?></a></li>
+                <li role="separator" class="divider"></li>
+                <li><a id="delete_selected" data-id="domain_admins" data-api-url='delete/domain_admin' href="#"><?=$lang['mailbox']['remove'];?></a></li>
+              </ul>
             </div>
             </div>
-          </form>
-          <small>
+          </div>
           <legend><?=$lang['admin']['add_domain_admin'];?></legend>
           <legend><?=$lang['admin']['add_domain_admin'];?></legend>
-          <form class="form-horizontal" role="form" method="post">
-            <input type="hidden" value="0" name="active">
+          <form class="form-horizontal" data-id="domain_admin" role="form" method="post">
             <div class="form-group">
             <div class="form-group">
               <label class="control-label col-sm-2" for="username"><?=$lang['admin']['username'];?>:</label>
               <label class="control-label col-sm-2" for="username"><?=$lang['admin']['username'];?>:</label>
               <div class="col-sm-10">
               <div class="col-sm-10">
@@ -118,7 +125,7 @@ $tfa_data = get_tfa();
             <div class="form-group">
             <div class="form-group">
               <label class="control-label col-sm-2" for="name"><?=$lang['admin']['admin_domains'];?>:</label>
               <label class="control-label col-sm-2" for="name"><?=$lang['admin']['admin_domains'];?>:</label>
               <div class="col-sm-10">
               <div class="col-sm-10">
-                <select title="<?=$lang['admin']['search_domain_da'];?>" style="width:100%" name="domain[]" size="5" multiple>
+                <select title="<?=$lang['admin']['search_domain_da'];?>" style="width:100%" name="domains" size="5" multiple>
                 <?php
                 <?php
                 foreach (mailbox('get', 'domains') as $domain) {
                 foreach (mailbox('get', 'domains') as $domain) {
                   echo "<option>".htmlspecialchars($domain)."</option>";
                   echo "<option>".htmlspecialchars($domain)."</option>";
@@ -148,13 +155,11 @@ $tfa_data = get_tfa();
             </div>
             </div>
             <div class="form-group">
             <div class="form-group">
               <div class="col-sm-offset-2 col-sm-10">
               <div class="col-sm-offset-2 col-sm-10">
-                <button type="submit" name="add_domain_admin" class="btn btn-default"><?=$lang['admin']['add'];?></button>
+                <button class="btn btn-default" id="add_item" data-id="domain_admin" data-api-url='add/domain_admin' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
               </div>
               </div>
             </div>
             </div>
           </form>
           </form>
-          </small>
         </div>
         </div>
-      </div>
     </div>
     </div>
   </div>
   </div>
 
 

+ 5 - 5
data/web/edit.php

@@ -68,17 +68,17 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 				<br />
 				<br />
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
 					<input type="hidden" value="0" name="active">
 					<input type="hidden" value="0" name="active">
-					<input type="hidden" name="username_now" value="<?=htmlspecialchars($domain_admin);?>">
+					<input type="hidden" name="username" value="<?=htmlspecialchars($domain_admin);?>">
 					<div class="form-group">
 					<div class="form-group">
-						<label class="control-label col-sm-2" for="username"><?=$lang['edit']['username'];?></label>
+						<label class="control-label col-sm-2" for="username_new"><?=$lang['edit']['username'];?></label>
 						<div class="col-sm-10">
 						<div class="col-sm-10">
-              <input class="form-control" type="text" name="username" value="<?=htmlspecialchars($domain_admin);?>" />
+              <input class="form-control" type="text" name="username_new" value="<?=htmlspecialchars($domain_admin);?>" />
 						</div>
 						</div>
 					</div>
 					</div>
 					<div class="form-group">
 					<div class="form-group">
-						<label class="control-label col-sm-2" for="domain"><?=$lang['edit']['domains'];?></label>
+						<label class="control-label col-sm-2" for="domains"><?=$lang['edit']['domains'];?></label>
 						<div class="col-sm-10">
 						<div class="col-sm-10">
-							<select id="domain" name="domain[]" multiple>
+							<select id="domains" name="domains[]" multiple required>
 							<?php
 							<?php
 							foreach ($result['selected_domains'] as $domain):
 							foreach ($result['selected_domains'] as $domain):
 							?>
 							?>

+ 160 - 147
data/web/inc/functions.inc.php

@@ -193,11 +193,10 @@ function edit_admin_account($postarray) {
 		);
 		);
 		return false;
 		return false;
 	}
 	}
-	$username       = $postarray['admin_user'];
 	$username_now   = $_SESSION['mailcow_cc_username'];
 	$username_now   = $_SESSION['mailcow_cc_username'];
+	$username       = $postarray['admin_user'];
   $password       = $postarray['admin_pass'];
   $password       = $postarray['admin_pass'];
   $password2      = $postarray['admin_pass2'];
   $password2      = $postarray['admin_pass2'];
-
 	if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username)) || empty ($username)) {
 	if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username)) || empty ($username)) {
 		$_SESSION['return'] = array(
 		$_SESSION['return'] = array(
 			'type' => 'danger',
 			'type' => 'danger',
@@ -425,7 +424,8 @@ function add_domain_admin($postarray) {
 	$username		= strtolower(trim($postarray['username']));
 	$username		= strtolower(trim($postarray['username']));
 	$password		= $postarray['password'];
 	$password		= $postarray['password'];
 	$password2  = $postarray['password2'];
 	$password2  = $postarray['password2'];
-  $active  = intval($postarray['active']);
+	$domains    = (array)$postarray['domains'];
+  $active     = intval($postarray['active']);
 
 
 	if ($_SESSION['mailcow_cc_role'] != "admin") {
 	if ($_SESSION['mailcow_cc_role'] != "admin") {
 		$_SESSION['return'] = array(
 		$_SESSION['return'] = array(
@@ -434,7 +434,7 @@ function add_domain_admin($postarray) {
 		);
 		);
 		return false;
 		return false;
 	}
 	}
-	if (empty($postarray['domain'])) {
+	if (empty($domains)) {
 		$_SESSION['return'] = array(
 		$_SESSION['return'] = array(
 			'type' => 'danger',
 			'type' => 'danger',
 			'msg' => sprintf($lang['danger']['domain_invalid'])
 			'msg' => sprintf($lang['danger']['domain_invalid'])
@@ -496,7 +496,7 @@ function add_domain_admin($postarray) {
 			return false;
 			return false;
 		}
 		}
 		$password_hashed = hash_password($password);
 		$password_hashed = hash_password($password);
-		foreach ($postarray['domain'] as $domain) {
+		foreach ($domains as $domain) {
 			if (!is_valid_domain_name($domain)) {
 			if (!is_valid_domain_name($domain)) {
 				$_SESSION['return'] = array(
 				$_SESSION['return'] = array(
 					'type' => 'danger',
 					'type' => 'danger',
@@ -562,35 +562,37 @@ function delete_domain_admin($postarray) {
 		);
 		);
 		return false;
 		return false;
 	}
 	}
-	$username = $postarray['username'];
-	if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['username_invalid'])
-		);
-		return false;
-	}
-	try {
-		$stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
-		$stmt->execute(array(
-			':username' => $username,
-		));
-		$stmt = $pdo->prepare("DELETE FROM `admin` WHERE `username` = :username");
-		$stmt->execute(array(
-			':username' => $username,
-		));
-	}
-	catch (PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
-	}
-	$_SESSION['return'] = array(
-		'type' => 'success',
-		'msg' => sprintf($lang['success']['domain_admin_removed'], htmlspecialchars($username))
-	);
+	$usernames = (array)$postarray['username'];
+  foreach ($usernames as $username) {
+    if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['username_invalid'])
+      );
+      return false;
+    }
+    try {
+      $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
+      $stmt->execute(array(
+        ':username' => $username,
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `admin` WHERE `username` = :username");
+      $stmt->execute(array(
+        ':username' => $username,
+      ));
+    }
+    catch (PDOException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'MySQL: '.$e
+      );
+      return false;
+    }
+  }
+  $_SESSION['return'] = array(
+    'type' => 'success',
+    'msg' => sprintf($lang['success']['domain_admin_removed'], htmlspecialchars(implode(', ', $usernames)))
+  );
 }
 }
 function get_domain_admins() {
 function get_domain_admins() {
 	global $pdo;
 	global $pdo;
@@ -1069,116 +1071,63 @@ function edit_domain_admin($postarray) {
 	}
 	}
 	// Administrator
 	// Administrator
   if ($_SESSION['mailcow_cc_role'] == "admin") {
   if ($_SESSION['mailcow_cc_role'] == "admin") {
-    $username     = $postarray['username'];
-    $username_now = $postarray['username_now'];
-    $password     = $postarray['password'];
-    $password2    = $postarray['password2'];
-    $active       = intval($postarray['active']);
-
-    if(isset($postarray['domain'])) {
-      foreach ($postarray['domain'] as $domain) {
-        if (!is_valid_domain_name($domain)) {
-          $_SESSION['return'] = array(
-            'type' => 'danger',
-            'msg' => sprintf($lang['danger']['domain_invalid'])
-          );
-          return false;
-        }
-      }
-    }
-
-    if (empty($postarray['domain'])) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => sprintf($lang['danger']['domain_invalid'])
-      );
-      return false;
+    if (!is_array($postarray['username'])) {
+      $usernames = array();
+      $usernames[] = $postarray['username'];
     }
     }
-
-    if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => sprintf($lang['danger']['username_invalid'])
-      );
-      return false;
+    else {
+      $usernames = $postarray['username'];
     }
     }
-    if ($username != $username_now) {
-      if (empty(get_domain_admin_details($username_now)['username']) || !empty(get_domain_admin_details($username)['username'])) {
+    foreach ($usernames as $username) {
+      $is_now = get_domain_admin_details($username);
+      $domains = (isset($postarray['domains'])) ? (array)$postarray['domains'] : null;
+      if (!empty($is_now)) {
+        $active = (isset($postarray['active'])) ? $postarray['active'] : $is_now['active_int'];
+        $domains = (!empty($domains)) ? $domains : $is_now['selected_domains'];
+        $username_new = (!empty($postarray['username_new'])) ? $postarray['username_new'] : $is_now['username'];
+      }
+      else {
         $_SESSION['return'] = array(
         $_SESSION['return'] = array(
           'type' => 'danger',
           'type' => 'danger',
-          'msg' => sprintf($lang['danger']['username_invalid'])
+          'msg' => sprintf($lang['danger']['access_denied'])
         );
         );
         return false;
         return false;
       }
       }
-    }
-    try {
-      $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
-      $stmt->execute(array(
-        ':username' => $username_now,
-      ));
-    }
-    catch (PDOException $e) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => 'MySQL: '.$e
-      );
-      return false;
-    }
+      $password     = $postarray['password'];
+      $password2    = $postarray['password2'];
 
 
-    if (isset($postarray['domain'])) {
-      foreach ($postarray['domain'] as $domain) {
-        try {
-          $stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
-            VALUES (:username, :domain, :created, :active)");
-          $stmt->execute(array(
-            ':username' => $username,
-            ':domain' => $domain,
-            ':created' => date('Y-m-d H:i:s'),
-            ':active' => $active
-          ));
-        }
-        catch (PDOException $e) {
-          $_SESSION['return'] = array(
-            'type' => 'danger',
-            'msg' => 'MySQL: '.$e
-          );
-          return false;
+      if (!empty($domains)) {
+        foreach ($domains as $domain) {
+          if (!is_valid_domain_name($domain)) {
+            $_SESSION['return'] = array(
+              'type' => 'danger',
+              'msg' => sprintf($lang['danger']['domain_invalid'])
+            );
+            return false;
+          }
         }
         }
       }
       }
-    }
-
-    if (!empty($password) && !empty($password2)) {
-      if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
+      if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username_new))) {
         $_SESSION['return'] = array(
         $_SESSION['return'] = array(
           'type' => 'danger',
           'type' => 'danger',
-          'msg' => sprintf($lang['danger']['password_complexity'])
+          'msg' => sprintf($lang['danger']['username_invalid'])
         );
         );
         return false;
         return false;
       }
       }
-      if ($password != $password2) {
-        $_SESSION['return'] = array(
-          'type' => 'danger',
-          'msg' => sprintf($lang['danger']['password_mismatch'])
-        );
-        return false;
+      if ($username_new != $username) {
+        if (!empty(get_domain_admin_details($username_new)['username'])) {
+          $_SESSION['return'] = array(
+            'type' => 'danger',
+            'msg' => sprintf($lang['danger']['username_invalid'])
+          );
+          return false;
+        }
       }
       }
-      $password_hashed = hash_password($password);
       try {
       try {
-        $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username1, `active` = :active, `password` = :password_hashed WHERE `username` = :username2");
+        $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
         $stmt->execute(array(
         $stmt->execute(array(
-          ':password_hashed' => $password_hashed,
-          ':username1' => $username,
-          ':username2' => $username_now,
-          ':active' => $active
+          ':username' => $username,
         ));
         ));
-        if (isset($postarray['disable_tfa'])) {
-          $stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
-          $stmt->execute(array(':username' => $username_now));
-        }
-        else {
-          $stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username WHERE `username` = :username_now");
-          $stmt->execute(array(':username' => $username, ':username_now' => $username_now));
-        }
       }
       }
       catch (PDOException $e) {
       catch (PDOException $e) {
         $_SESSION['return'] = array(
         $_SESSION['return'] = array(
@@ -1187,35 +1136,99 @@ function edit_domain_admin($postarray) {
         );
         );
         return false;
         return false;
       }
       }
-    }
-    else {
-      try {
-        $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username1, `active` = :active WHERE `username` = :username2");
-        $stmt->execute(array(
-          ':username1' => $username,
-          ':username2' => $username_now,
-          ':active' => $active
-        ));
-        if (isset($postarray['disable_tfa'])) {
-          $stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
-          $stmt->execute(array(':username' => $username));
+
+      if (!empty($domains)) {
+        foreach ($domains as $domain) {
+          try {
+            $stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
+              VALUES (:username_new, :domain, :created, :active)");
+            $stmt->execute(array(
+              ':username_new' => $username_new,
+              ':domain' => $domain,
+              ':created' => date('Y-m-d H:i:s'),
+              ':active' => $active
+            ));
+          }
+          catch (PDOException $e) {
+            $_SESSION['return'] = array(
+              'type' => 'danger',
+              'msg' => 'MySQL: '.$e
+            );
+            return false;
+          }
         }
         }
-        else {
-          $stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username WHERE `username` = :username_now");
-          $stmt->execute(array(':username' => $username, ':username_now' => $username_now));
+      }
+
+      if (!empty($password) && !empty($password2)) {
+        if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
+          $_SESSION['return'] = array(
+            'type' => 'danger',
+            'msg' => sprintf($lang['danger']['password_complexity'])
+          );
+          return false;
+        }
+        if ($password != $password2) {
+          $_SESSION['return'] = array(
+            'type' => 'danger',
+            'msg' => sprintf($lang['danger']['password_mismatch'])
+          );
+          return false;
+        }
+        $password_hashed = hash_password($password);
+        try {
+          $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
+          $stmt->execute(array(
+            ':password_hashed' => $password_hashed,
+            ':username_new' => $username_new,
+            ':username' => $username,
+            ':active' => $active
+          ));
+          if (isset($postarray['disable_tfa'])) {
+            $stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
+            $stmt->execute(array(':username' => $username));
+          }
+          else {
+            $stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username_new WHERE `username` = :username");
+            $stmt->execute(array(':username_new' => $username_new, ':username' => $username));
+          }
+        }
+        catch (PDOException $e) {
+          $_SESSION['return'] = array(
+            'type' => 'danger',
+            'msg' => 'MySQL: '.$e
+          );
+          return false;
         }
         }
       }
       }
-      catch (PDOException $e) {
-        $_SESSION['return'] = array(
-          'type' => 'danger',
-          'msg' => 'MySQL: '.$e
-        );
-        return false;
+      else {
+        try {
+          $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active WHERE `username` = :username");
+          $stmt->execute(array(
+            ':username_new' => $username_new,
+            ':username' => $username,
+            ':active' => $active
+          ));
+          if (isset($postarray['disable_tfa'])) {
+            $stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
+            $stmt->execute(array(':username' => $username));
+          }
+          else {
+            $stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username_new WHERE `username` = :username");
+            $stmt->execute(array(':username_new' => $username_new, ':username' => $username));
+          }
+        }
+        catch (PDOException $e) {
+          $_SESSION['return'] = array(
+            'type' => 'danger',
+            'msg' => 'MySQL: '.$e
+          );
+          return false;
+        }
       }
       }
     }
     }
     $_SESSION['return'] = array(
     $_SESSION['return'] = array(
       'type' => 'success',
       'type' => 'success',
-      'msg' => sprintf($lang['success']['domain_admin_modified'], htmlspecialchars($username))
+      'msg' => sprintf($lang['success']['domain_admin_modified'], htmlspecialchars(implode(', ', $usernames)))
     );
     );
   }
   }
   // Domain administrator
   // Domain administrator

+ 0 - 6
data/web/inc/triggers.inc.php

@@ -63,12 +63,6 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi
 	if (isset($_POST["dkim_add_key"])) {
 	if (isset($_POST["dkim_add_key"])) {
 		dkim_add_key($_POST);
 		dkim_add_key($_POST);
 	}
 	}
-	if (isset($_POST["add_domain_admin"])) {
-		add_domain_admin($_POST);
-	}
-	if (isset($_POST["delete_domain_admin"])) {
-		delete_domain_admin($_POST);
-	}
 	if (isset($_POST["add_forwarding_host"])) {
 	if (isset($_POST["add_forwarding_host"])) {
 		add_forwarding_host($_POST);
 		add_forwarding_host($_POST);
 	}
 	}

+ 3 - 2
data/web/js/admin.js

@@ -175,6 +175,7 @@ jQuery(function($){
   function draw_domain_admins() {
   function draw_domain_admins() {
     ft_domainadmins = FooTable.init('#domainadminstable', {
     ft_domainadmins = FooTable.init('#domainadminstable', {
       "columns": [
       "columns": [
+        {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
         {"sorted": true,"name":"username","title":lang.username,"style":{"width":"250px"}},
         {"sorted": true,"name":"username","title":lang.username,"style":{"width":"250px"}},
         {"name":"selected_domains","title":lang.admin_domains,"breakpoints":"xs sm"},
         {"name":"selected_domains","title":lang.admin_domains,"breakpoints":"xs sm"},
         {"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"}},
         {"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"}},
@@ -190,9 +191,9 @@ jQuery(function($){
         },
         },
         success: function (data) {
         success: function (data) {
           $.each(data, function (i, item) {
           $.each(data, function (i, item) {
+            item.chkbox = '<input type="checkbox" data-id="domain_admins" name="multi_select" value="' + item.username + '" />';
             item.action = '<div class="btn-group">' +
             item.action = '<div class="btn-group">' +
               '<a href="/edit.php?domainadmin=' + encodeURI(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
               '<a href="/edit.php?domainadmin=' + encodeURI(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
-              '<a href="/delete.php?domainadmin=' + encodeURI(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
               '</div>';
               '</div>';
           });
           });
         }
         }
@@ -214,7 +215,7 @@ jQuery(function($){
     });
     });
   }
   }
   function draw_fwd_hosts() {
   function draw_fwd_hosts() {
-    ft_domainadmins = FooTable.init('#forwardinghoststable', {
+    ft_forwardinghoststable = FooTable.init('#forwardinghoststable', {
       "columns": [
       "columns": [
         {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
         {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
         {"name":"host","type":"text","title":lang.host,"style":{"width":"250px"}},
         {"name":"host","type":"text","title":lang.host,"style":{"width":"250px"}},

+ 45 - 32
data/web/js/api.js

@@ -1,4 +1,19 @@
 $(document).ready(function() {
 $(document).ready(function() {
+  $.fn.serializeObject = function() {
+    var o = {};
+    var a = this.serializeArray();
+    $.each(a, function() {
+      if (o[this.name]) {
+        if (!o[this.name].push) {
+          o[this.name] = [o[this.name]];
+        }
+        o[this.name].push(this.value || '');
+      } else {
+        o[this.name] = this.value || '';
+      }
+    });
+    return o;
+  };
   // Collect values of input fields with name "multi_select" an same data-id to js array multi_data[data-id]
   // Collect values of input fields with name "multi_select" an same data-id to js array multi_data[data-id]
   var multi_data = [];
   var multi_data = [];
   $(document).on('change', 'input[name=multi_select]:checkbox', function() {
   $(document).on('change', 'input[name=multi_select]:checkbox', function() {
@@ -43,10 +58,7 @@ $(document).ready(function() {
     // If clicked element #edit_selected is in a form with the same data-id as the button,
     // If clicked element #edit_selected is in a form with the same data-id as the button,
     // we merge all input fields by {"name":"value"} into api-attr
     // we merge all input fields by {"name":"value"} into api-attr
     if ($(this).closest("form").data('id') == id) {
     if ($(this).closest("form").data('id') == id) {
-      var attr_to_merge = {};
-      $.each($(this).closest("form").serializeArray(), function(i, field) {
-          attr_to_merge[field.name] = field.value;
-      });
+      var attr_to_merge = $(this).closest("form").serializeObject();
       var api_attr = $.extend(api_attr, attr_to_merge)
       var api_attr = $.extend(api_attr, attr_to_merge)
     }
     }
     // If clicked element #edit_selected has data-item attribute, it is added to "items"
     // If clicked element #edit_selected has data-item attribute, it is added to "items"
@@ -59,6 +71,7 @@ $(document).ready(function() {
     }
     }
     if (typeof multi_data[id] == "undefined") return;
     if (typeof multi_data[id] == "undefined") return;
     api_items = multi_data[id];
     api_items = multi_data[id];
+
     if (Object.keys(api_items).length !== 0) {
     if (Object.keys(api_items).length !== 0) {
       $.ajax({
       $.ajax({
         type: "POST",
         type: "POST",
@@ -85,10 +98,7 @@ $(document).ready(function() {
     // If clicked button is in a form with the same data-id as the button,
     // If clicked button is in a form with the same data-id as the button,
     // we merge all input fields by {"name":"value"} into api-attr
     // we merge all input fields by {"name":"value"} into api-attr
     if ($(this).closest("form").data('id') == id) {
     if ($(this).closest("form").data('id') == id) {
-      var attr_to_merge = {};
-      $.each($(this).closest("form").serializeArray(), function(i, field) {
-          attr_to_merge[field.name] = field.value;
-      });
+      var attr_to_merge = $(this).closest("form").serializeObject();
       var api_attr = $.extend(api_attr, attr_to_merge)
       var api_attr = $.extend(api_attr, attr_to_merge)
     }
     }
     $.ajax({
     $.ajax({
@@ -125,30 +135,33 @@ $(document).ready(function() {
     if (typeof multi_data[id] == "undefined" || multi_data[id] == "") return;
     if (typeof multi_data[id] == "undefined" || multi_data[id] == "") return;
     data_array = multi_data[id];
     data_array = multi_data[id];
     api_url = $(this).data('api-url');
     api_url = $(this).data('api-url');
-      $(document).on('show.bs.modal','#ConfirmDeleteModal', function () {
-        $("#ItemsToDelete").empty();
-        for (var i in data_array) {
-          $("#ItemsToDelete").append("<li>" + data_array[i] + "</li>");
+    $(document).on('show.bs.modal','#ConfirmDeleteModal', function () {
+      $("#ItemsToDelete").empty();
+      for (var i in data_array) {
+        $("#ItemsToDelete").append("<li>" + data_array[i] + "</li>");
+      }
+    })
+    $('#ConfirmDeleteModal').modal({
+      backdrop: 'static',
+      keyboard: false
+    })
+    .one('click', '#IsConfirmed', function(e) {
+      $.ajax({
+        type: "POST",
+        dataType: "json",
+        cache: false,
+        data: { "items": JSON.stringify(data_array), "csrf_token": csrf_token },
+        url: '/api/v1/' + api_url,
+        jsonp: false,
+        complete: function (data) {
+          window.location = window.location.href.split("#")[0];
         }
         }
-      })
-      $('#ConfirmDeleteModal').modal({
-        backdrop: 'static',
-        keyboard: false
-      })
-      .one('click', '#IsConfirmed', function(e) {
-        $.ajax({
-          type: "POST",
-          dataType: "json",
-          data: { "items": JSON.stringify(data_array), "csrf_token": csrf_token },
-          url: '/api/v1/' + api_url,
-          jsonp: false,
-          complete: function (data) {
-            window.location = window.location.href.split("#")[0];
-          }
-        });
-      })
-      .one('click', '#isCanceled', function(e) {
-        $('#ConfirmDeleteModal').modal('hide');
-      });;
+      });
+    })
+    .one('click', '#isCanceled', function(e) {
+      // Remove event handler to allow to close modal and restart dialog without multiple submits
+      $('#ConfirmDeleteModal').off();
+      $('#ConfirmDeleteModal').modal('hide');
+    });
   });
   });
 });
 });

+ 153 - 0
data/web/json_api.php

@@ -60,6 +60,39 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
               ));
               ));
             }
             }
           break;
           break;
+          case "domain_admin":
+            if (isset($_POST['attr'])) {
+              $attr = (array)json_decode($_POST['attr'], true);
+              if (add_domain_admin($attr) === false) {
+                if (isset($_SESSION['return'])) {
+                  echo json_encode($_SESSION['return']);
+                }
+                else {
+                  echo json_encode(array(
+                    'type' => 'error',
+                    'msg' => 'Cannot add item'
+                  ));
+                }
+              }
+              else {
+                if (isset($_SESSION['return'])) {
+                  echo json_encode($_SESSION['return']);
+                }
+                else {
+                  echo json_encode(array(
+                    'type' => 'success',
+                    'msg' => 'Task completed'
+                  ));
+                }
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Cannot find attributes in post data'
+              ));
+            }
+          break;
         }
         }
       break;
       break;
       case "get":
       case "get":
@@ -947,6 +980,47 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
               ));
               ));
             }
             }
           break;
           break;
+          case "domain_admin":
+            if (isset($_POST['items'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              if (is_array($items)) {
+                if (delete_domain_admin(array('username' => $items)) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Task failed'
+                    ));
+                  }
+                }
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Cannot find name array in post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Cannot find items in post data'
+              ));
+            }
+          break;
         }
         }
       break;
       break;
       case "edit":
       case "edit":
@@ -1391,6 +1465,85 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
               ));
               ));
             }
             }
           break;
           break;
+          case "domain_admin":
+            if (isset($_POST['items']) && isset($_POST['attr'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              $attr = (array)json_decode($_POST['attr'], true);
+              $postarray = array_merge(array('username' => $items), $attr);
+              if (is_array($postarray['username'])) {
+                if (edit_domain_admin($postarray) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Edit failed'
+                    ));
+                  }
+                  exit();
+                }
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Incomplete post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Incomplete post data'
+              ));
+            }
+          break;
+          case "admin":
+            // No items as there is only one admin
+            if (isset($_POST['attr'])) {
+              $attr = (array)json_decode($_POST['attr'], true);
+              if (edit_admin_account($attr) === false) {
+                if (isset($_SESSION['return'])) {
+                  echo json_encode($_SESSION['return']);
+                }
+                else {
+                  echo json_encode(array(
+                    'type' => 'error',
+                    'msg' => 'Edit failed'
+                  ));
+                }
+                exit();
+              }
+              else {
+                if (isset($_SESSION['return'])) {
+                  echo json_encode($_SESSION['return']);
+                }
+                else {
+                  echo json_encode(array(
+                    'type' => 'success',
+                    'msg' => 'Task completed'
+                  ));
+                }
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Incomplete post data'
+              ));
+            }
+          break;
         }
         }
       break;
       break;
     }
     }

+ 1 - 1
data/web/user.php

@@ -31,7 +31,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'doma
               foreach ($tfa_data['additional'] as $key_info): ?>
               foreach ($tfa_data['additional'] as $key_info): ?>
                 <form style="display:inline;" method="post">
                 <form style="display:inline;" method="post">
                 <input type="hidden" name="unset_tfa_key" value="<?=$key_info['id'];?>" />
                 <input type="hidden" name="unset_tfa_key" value="<?=$key_info['id'];?>" />
-                <div class="label label-default">?? <?=$key_info['key_id'];?> <a href="#" style="font-weight:bold;color:white" onClick="$(this).closest('form').submit()">[<?=strtolower($lang['admin']['remove']);?>]</a></div>
+                <div class="label label-default">🔑 <?=$key_info['key_id'];?> <a href="#" style="font-weight:bold;color:white" onClick="$(this).closest('form').submit()">[<?=strtolower($lang['admin']['remove']);?>]</a></div>
               </form>
               </form>
               <?php endforeach;
               <?php endforeach;
               endif;?>
               endif;?>