Files
Froxlor/lib/Froxlor/Database/DbManager.php
2023-02-08 12:36:38 +01:00

204 lines
5.9 KiB
PHP

<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can also view it online at
* https://files.froxlor.org/misc/COPYING.txt
*
* @copyright the authors
* @author Froxlor team <team@froxlor.org>
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/
namespace Froxlor\Database;
use Froxlor\Database\Manager\DbManagerMySQL;
use Froxlor\Froxlor;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
use PDO;
/**
* Class DbManager
*
* Wrapper-class for database-management like creating
* and removing databases, users and permissions
*/
class DbManager
{
/**
* FroxlorLogger object
*
* @var object
*/
private $log = null;
/**
* Manager object
*
* @var object
*/
private $manager = null;
/**
* main constructor
*
* @param FroxlorLogger $log
*/
public function __construct($log = null)
{
$this->log = $log;
$this->setManager();
}
/**
* set manager-object by type of
* dbms: mysql only for now
*
* sets private $_manager variable
*/
private function setManager()
{
// TODO read different dbms from settings later
$this->manager = new DbManagerMySQL($this->log);
}
/**
* function called when the mysql-access-host setting changes
*
* @param array $mysql_access_host_array
*
* @return void
* @throws \Exception
*/
public static function correctMysqlUsers(array $mysql_access_host_array)
{
// get all databases for all dbservers
$databases = [];
$databases_result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
ORDER BY `dbserver` ASC
");
Database::pexecute($databases_result_stmt);
while ($databases_row = $databases_result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (!isset($databases[$databases_row['dbserver']])) {
$databases[$databases_row['dbserver']] = [];
}
$databases[$databases_row['dbserver']][] = $databases_row['databasename'];
}
$dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`");
while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) {
// require privileged access for target db-server
Database::needRoot(true, $dbserver['dbserver'], false);
$dbm = new DbManager(FroxlorLogger::getInstanceOf());
$users = $dbm->getManager()->getAllSqlUsers(false);
foreach ($databases[$dbserver['dbserver']] as $username) {
if (isset($users[$username]) && is_array($users[$username]) && isset($users[$username]['hosts']) && is_array($users[$username]['hosts'])) {
$password = [
'password' => $users[$username]['password'],
'plugin' => $users[$username]['plugin']
];
foreach ($mysql_access_host_array as $mysql_access_host) {
$mysql_access_host = trim($mysql_access_host);
if (!in_array($mysql_access_host, $users[$username]['hosts'])) {
$dbm->getManager()->grantPrivilegesTo($username, $password, $mysql_access_host, true);
}
}
foreach ($users[$username]['hosts'] as $mysql_access_host) {
if (!in_array($mysql_access_host, $mysql_access_host_array)) {
$dbm->getManager()->deleteUser($username, $mysql_access_host);
}
}
}
}
$dbm->getManager()->flushPrivileges();
Database::needRoot(false);
}
}
/**
* creates a new database and a user with the
* same name with all privileges granted on the db.
* DB-name and user-name are being generated and
* the password for the user will be set
*
* @param ?string $loginname
* @param ?string $password
* @param int $dbserver
* @param int $last_accnumber
*
* @return string|bool $username if successful or false of username is equal to the password
*/
public function createDatabase(string $loginname = null, string $password = null, int $dbserver = 0, int $last_accnumber = 0)
{
Database::needRoot(true, $dbserver, false);
// check whether we shall create a random username
if (strtoupper(Settings::Get('customer.mysqlprefix')) == 'RANDOM') {
// get all usernames from db-manager
$allsqlusers = $this->getManager()->getAllSqlUsers();
// generate random username
$username = $loginname . '-' . substr(Froxlor::genSessionId(), 20, 3);
// check whether it exists on the DBMS
while (in_array($username, $allsqlusers)) {
$username = $loginname . '-' . substr(Froxlor::genSessionId(), 20, 3);
}
} elseif (strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME') {
$username = $loginname;
} else {
$username = $loginname . Settings::Get('customer.mysqlprefix') . (intval($last_accnumber) + 1);
}
// don't use a password that is the same as the username
if ($username == $password) {
return false;
}
// now create the database itself
$this->getManager()->createDatabase($username);
// and give permission to the user on every access-host we have
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
$this->getManager()->grantPrivilegesTo($username, $password, $mysql_access_host);
}
$this->getManager()->flushPrivileges();
Database::needRoot(false);
$this->log->logAction(FroxlorLogger::USR_ACTION, LOG_INFO, "created database '" . $username . "'");
return $username;
}
/**
* returns the manager-object
* from where we can control it
*/
public function getManager()
{
return $this->manager;
}
}