check for given customer loginname/id before anything happens in Mysqls.add/update/delete when called as admin; fixes #749

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann
2019-11-07 15:53:30 +01:00
parent 6efe500cee
commit dfedc478f7

View File

@@ -34,7 +34,9 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param bool $sendinfomail * @param bool $sendinfomail
* optional, send created resource-information to customer, default: false * optional, send created resource-information to customer, default: false
* @param int $customerid * @param int $customerid
* required when called as admin, not needed when called as customer * optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -42,53 +44,50 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*/ */
public function add() public function add()
{ {
if ($this->getUserDetail('mysqls_used') < $this->getUserDetail('mysqls') || $this->getUserDetail('mysqls') == '-1') { // required paramters
$password = $this->getParam('mysql_password');
// required paramters // parameters
$password = $this->getParam('mysql_password'); $dbserver = $this->getParam('mysql_server', true, 0);
$databasedescription = $this->getParam('description', true, '');
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData('mysqls');
// parameters // validation
$dbserver = $this->getParam('mysql_server', true, 0); $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$databasedescription = $this->getParam('description', true, ''); $password = \Froxlor\System\Crypt::validatePassword($password, true);
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0); $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true);
// validation // validate whether the dbserver exists
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); $dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true);
$password = \Froxlor\System\Crypt::validatePassword($password, true); Database::needRoot(true, $dbserver);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true); Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
if (! isset($sql_root) || ! is_array($sql_root)) {
throw new \Exception("Database server with index #" . $dbserver . " is unknown", 404);
}
// validate whether the dbserver exists if ($sendinfomail != 1) {
$dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true); $sendinfomail = 0;
Database::needRoot(true, $dbserver); }
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
if (! isset($sql_root) || ! is_array($sql_root)) {
throw new \Exception("Database server with index #" . $dbserver . " is unknown", 404);
}
if ($sendinfomail != 1) { $newdb_params = array(
$sendinfomail = 0; 'loginname' => ($this->isAdmin() ? $customer['loginname'] : $this->getUserDetail('loginname')),
} 'mysql_lastaccountnumber' => ($this->isAdmin() ? $customer['mysql_lastaccountnumber'] : $this->getUserDetail('mysql_lastaccountnumber'))
);
// create database, user, set permissions, etc.pp.
$dbm = new \Froxlor\Database\DbManager($this->logger());
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']);
// get needed customer info to reduce the mysql-usage-counter by one // we've checked against the password in dbm->createDatabase
$customer = $this->getCustomerData('mysqls'); if ($username == false) {
\Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true);
}
$newdb_params = array( // add database info to froxlor
'loginname' => ($this->isAdmin() ? $customer['loginname'] : $this->getUserDetail('loginname')), $stmt = Database::prepare("
'mysql_lastaccountnumber' => ($this->isAdmin() ? $customer['mysql_lastaccountnumber'] : $this->getUserDetail('mysql_lastaccountnumber'))
);
// create database, user, set permissions, etc.pp.
$dbm = new \Froxlor\Database\DbManager($this->logger());
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']);
// we've checked against the password in dbm->createDatabase
if ($username == false) {
\Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true);
}
// add database info to froxlor
$stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_DATABASES . "` INSERT INTO `" . TABLE_PANEL_DATABASES . "`
SET SET
`customerid` = :customerid, `customerid` = :customerid,
@@ -96,79 +95,77 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`description` = :description, `description` = :description,
`dbserver` = :dbserver `dbserver` = :dbserver
"); ");
$params = array( $params = array(
"customerid" => $customer['customerid'], "customerid" => $customer['customerid'],
"databasename" => $username, "databasename" => $username,
"description" => $databasedescription, "description" => $databasedescription,
"dbserver" => $dbserver "dbserver" => $dbserver
); );
Database::pexecute($stmt, $params, true, true); Database::pexecute($stmt, $params, true, true);
$databaseid = Database::lastInsertId(); $databaseid = Database::lastInsertId();
$params['id'] = $databaseid; $params['id'] = $databaseid;
// update customer usage // update customer usage
Customers::increaseUsage($customer['customerid'], 'mysqls_used'); Customers::increaseUsage($customer['customerid'], 'mysqls_used');
Customers::increaseUsage($customer['customerid'], 'mysql_lastaccountnumber'); Customers::increaseUsage($customer['customerid'], 'mysql_lastaccountnumber');
// send info-mail? // send info-mail?
if ($sendinfomail == 1) { if ($sendinfomail == 1) {
$pma = $this->lng['admin']['notgiven']; $pma = $this->lng['admin']['notgiven'];
if (Settings::Get('panel.phpmyadmin_url') != '') { if (Settings::Get('panel.phpmyadmin_url') != '') {
$pma = Settings::Get('panel.phpmyadmin_url'); $pma = Settings::Get('panel.phpmyadmin_url');
}
Database::needRoot(true, $dbserver);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
$userinfo = $customer;
$replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo),
'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility
'DB_NAME' => $username,
'DB_PASS' => $password,
'DB_DESC' => $databasedescription,
'DB_SRV' => $sql_root['host'],
'PMA_URI' => $pma
);
// get template for mail subject
$mail_subject = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_subject', $replace_arr, $this->lng['mails']['new_database_by_customer']['subject']);
// get template for mail body
$mail_body = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_mailbody', $replace_arr, $this->lng['mails']['new_database_by_customer']['mailbody']);
$_mailerror = false;
$mailerr_msg = "";
try {
$this->mailer()->Subject = $mail_subject;
$this->mailer()->AltBody = $mail_body;
$this->mailer()->msgHTML(str_replace("\n", "<br />", $mail_body));
$this->mailer()->addAddress($userinfo['email'], \Froxlor\User::getCorrectUserSalutation($userinfo));
$this->mailer()->send();
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg);
\Froxlor\UI\Response::standard_error('errorsendingmail', $userinfo['email'], true);
}
$this->mailer()->clearAddresses();
} }
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'");
$result = $this->apiCall('Mysqls.get', array( Database::needRoot(true, $dbserver);
'dbname' => $username Database::needSqlData();
)); $sql_root = Database::getSqlData();
return $this->response(200, "successfull", $result); Database::needRoot(false);
$userinfo = $customer;
$replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo),
'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility
'DB_NAME' => $username,
'DB_PASS' => $password,
'DB_DESC' => $databasedescription,
'DB_SRV' => $sql_root['host'],
'PMA_URI' => $pma
);
// get template for mail subject
$mail_subject = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_subject', $replace_arr, $this->lng['mails']['new_database_by_customer']['subject']);
// get template for mail body
$mail_body = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_mailbody', $replace_arr, $this->lng['mails']['new_database_by_customer']['mailbody']);
$_mailerror = false;
$mailerr_msg = "";
try {
$this->mailer()->Subject = $mail_subject;
$this->mailer()->AltBody = $mail_body;
$this->mailer()->msgHTML(str_replace("\n", "<br />", $mail_body));
$this->mailer()->addAddress($userinfo['email'], \Froxlor\User::getCorrectUserSalutation($userinfo));
$this->mailer()->send();
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg);
\Froxlor\UI\Response::standard_error('errorsendingmail', $userinfo['email'], true);
}
$this->mailer()->clearAddresses();
} }
throw new \Exception("No more resources available", 406); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'");
$result = $this->apiCall('Mysqls.get', array(
'dbname' => $username
));
return $this->response(200, "successfull", $result);
} }
/** /**
@@ -276,6 +273,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, update password for the database * optional, update password for the database
* @param string $description * @param string $description
* optional, description for database * optional, description for database
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -287,6 +288,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$dn_optional = ($id <= 0 ? false : true); $dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, ''); $dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1); $dbserver = $this->getParam('mysql_server', true, - 1);
$customer = $this->getCustomerData();
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) {
throw new \Exception("You cannot access this resource", 405); throw new \Exception("You cannot access this resource", 405);
@@ -307,9 +309,6 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true); $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData();
if ($password != '') { if ($password != '') {
// validate password // validate password
$password = \Froxlor\System\Crypt::validatePassword($password, true); $password = \Froxlor\System\Crypt::validatePassword($password, true);
@@ -367,7 +366,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional specify offset for resultset * optional specify offset for resultset
* @param array $sql_orderby * @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
* @return string json-encoded array count|list * @return string json-encoded array count|list
@@ -380,8 +379,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$query_fields = array(); $query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DATABASES . "` SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
WHERE `customerid`= :customerid AND `dbserver` = :dbserver". $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit() WHERE `customerid`= :customerid AND `dbserver` = :dbserver" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
);
if ($dbserver < 0) { if ($dbserver < 0) {
// use all dbservers // use all dbservers
$dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`"); $dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`");
@@ -432,7 +430,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, admin-only, select dbs of a specific customer by id * optional, admin-only, select dbs of a specific customer by id
* @param string $loginname * @param string $loginname
* optional, admin-only, select dbs of a specific customer by loginname * optional, admin-only, select dbs of a specific customer by loginname
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
* @return string json-encoded array * @return string json-encoded array
@@ -459,6 +457,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, the databasename * optional, the databasename
* @param int $mysql_server * @param int $mysql_server
* optional, specify database-server, default is none * optional, specify database-server, default is none
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -470,6 +472,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$dn_optional = ($id <= 0 ? false : true); $dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, ''); $dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1); $dbserver = $this->getParam('mysql_server', true, - 1);
$customer = $this->getCustomerData();
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) {
throw new \Exception("You cannot access this resource", 405); throw new \Exception("You cannot access this resource", 405);
@@ -496,7 +499,6 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
), true, true); ), true, true);
// get needed customer info to reduce the mysql-usage-counter by one // get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData();
$mysql_used = $customer['mysqls_used']; $mysql_used = $customer['mysqls_used'];
// reduce mysql-usage-counter // reduce mysql-usage-counter