Initial commit
This commit is contained in:
@@ -21,7 +21,6 @@ class DatabaseModel
|
||||
|
||||
$databases = $query->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
// Filter out system databases
|
||||
$system_dbs = ['information_schema', 'performance_schema', 'mysql', 'sys'];
|
||||
return array_diff($databases, $system_dbs);
|
||||
}
|
||||
@@ -35,7 +34,7 @@ class DatabaseModel
|
||||
{
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
$sql = "SHOW TABLES FROM " . $database_name;
|
||||
$sql = "SHOW TABLES FROM `" . $database_name . "`";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
@@ -54,7 +53,7 @@ class DatabaseModel
|
||||
$table_details = array();
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$sql = "SHOW TABLE STATUS FROM " . $database_name . " LIKE :table_name";
|
||||
$sql = "SHOW TABLE STATUS FROM `" . $database_name . "` LIKE :table_name";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute(array(':table_name' => $table));
|
||||
|
||||
@@ -87,7 +86,7 @@ class DatabaseModel
|
||||
$tables = self::getTablesInDatabase($database_name);
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$sql = "DESCRIBE " . $database_name . "." . $table;
|
||||
$sql = "DESCRIBE `" . $database_name . "`.`" . $table . "`";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
@@ -152,13 +151,106 @@ class DatabaseModel
|
||||
{
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
$sql = "SHOW COLUMNS FROM " . $database_name . "." . $table_name;
|
||||
$sql = "SHOW COLUMNS FROM `" . $database_name . "`.`" . $table_name . "`";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export database as SQL dump
|
||||
* @param string $database_name
|
||||
* @return string
|
||||
*/
|
||||
public static function exportDatabase($database_name)
|
||||
{
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
$output = "-- Database Export: " . $database_name . "\n";
|
||||
$output .= "-- Generated: " . date('Y-m-d H:i:s') . "\n\n";
|
||||
$output .= "SET FOREIGN_KEY_CHECKS=0;\n";
|
||||
$output .= "SET SQL_MODE = \"NO_AUTO_VALUE_ON_ZERO\";\n\n";
|
||||
|
||||
$tables = self::getTablesInDatabase($database_name);
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$sql = "SHOW CREATE TABLE `" . $database_name . "`.`" . $table . "`";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute();
|
||||
$row = $query->fetch(PDO::FETCH_NUM);
|
||||
|
||||
$output .= "DROP TABLE IF EXISTS `" . $table . "`;\n";
|
||||
$output .= $row[1] . ";\n\n";
|
||||
|
||||
$sql = "SELECT * FROM `" . $database_name . "`.`" . $table . "`";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute();
|
||||
$rows = $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!empty($rows)) {
|
||||
foreach ($rows as $dataRow) {
|
||||
$columns = array_keys($dataRow);
|
||||
$values = array_map(function($val) use ($database) {
|
||||
if ($val === null) {
|
||||
return 'NULL';
|
||||
}
|
||||
return $database->quote($val);
|
||||
}, array_values($dataRow));
|
||||
|
||||
$output .= "INSERT INTO `" . $table . "` (`" . implode("`, `", $columns) . "`) VALUES (" . implode(", ", $values) . ");\n";
|
||||
}
|
||||
$output .= "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$output .= "SET FOREIGN_KEY_CHECKS=1;\n";
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export single table as SQL dump
|
||||
* @param string $database_name
|
||||
* @param string $table_name
|
||||
* @return string
|
||||
*/
|
||||
public static function exportTable($database_name, $table_name)
|
||||
{
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
$output = "-- Table Export: " . $table_name . " from " . $database_name . "\n";
|
||||
$output .= "-- Generated: " . date('Y-m-d H:i:s') . "\n\n";
|
||||
$output .= "SET FOREIGN_KEY_CHECKS=0;\n\n";
|
||||
|
||||
$sql = "SHOW CREATE TABLE `" . $database_name . "`.`" . $table_name . "`";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute();
|
||||
$row = $query->fetch(PDO::FETCH_NUM);
|
||||
|
||||
$output .= "DROP TABLE IF EXISTS `" . $table_name . "`;\n";
|
||||
$output .= $row[1] . ";\n\n";
|
||||
|
||||
$sql = "SELECT * FROM `" . $database_name . "`.`" . $table_name . "`";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute();
|
||||
$rows = $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!empty($rows)) {
|
||||
foreach ($rows as $dataRow) {
|
||||
$columns = array_keys($dataRow);
|
||||
$values = array_map(function($val) use ($database) {
|
||||
if ($val === null) {
|
||||
return 'NULL';
|
||||
}
|
||||
return $database->quote($val);
|
||||
}, array_values($dataRow));
|
||||
|
||||
$output .= "INSERT INTO `" . $table_name . "` (`" . implode("`, `", $columns) . "`) VALUES (" . implode(", ", $values) . ");\n";
|
||||
}
|
||||
}
|
||||
|
||||
$output .= "\nSET FOREIGN_KEY_CHECKS=1;\n";
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format bytes to human readable format
|
||||
* @param int $bytes
|
||||
|
||||
202
application/model/DbUserModel.php
Normal file
202
application/model/DbUserModel.php
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class DbUserModel
|
||||
*
|
||||
* Model for managing MySQL database users
|
||||
*/
|
||||
class DbUserModel
|
||||
{
|
||||
/**
|
||||
* Get all database users
|
||||
* @return array
|
||||
*/
|
||||
public static function getAllUsers()
|
||||
{
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
try {
|
||||
$sql = "SELECT User, Host FROM mysql.user ORDER BY User, Host";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_OBJ);
|
||||
} catch (PDOException $e) {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user details
|
||||
* @param string $username
|
||||
* @param string $host
|
||||
* @return object|null
|
||||
*/
|
||||
public static function getUserDetails($username, $host)
|
||||
{
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
try {
|
||||
$sql = "SELECT * FROM mysql.user WHERE User = :username AND Host = :host";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute(array(':username' => $username, ':host' => $host));
|
||||
|
||||
return $query->fetch(PDO::FETCH_OBJ);
|
||||
} catch (PDOException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user privileges
|
||||
* @param string $username
|
||||
* @param string $host
|
||||
* @return array
|
||||
*/
|
||||
public static function getUserPrivileges($username, $host)
|
||||
{
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
try {
|
||||
// Escape username and host for SHOW GRANTS
|
||||
$sql = "SHOW GRANTS FOR " . $database->quote($username) . "@" . $database->quote($host);
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
$grants = array();
|
||||
while ($row = $query->fetch(PDO::FETCH_NUM)) {
|
||||
$grants[] = $row[0];
|
||||
}
|
||||
|
||||
return $grants;
|
||||
} catch (PDOException $e) {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new database user
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $host
|
||||
* @return bool
|
||||
*/
|
||||
public static function createUser($username, $password, $host)
|
||||
{
|
||||
if (!self::validateUsername($username) || empty($password) || empty($host)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
try {
|
||||
$sql = "CREATE USER " . $database->quote($username) . "@" . $database->quote($host) .
|
||||
" IDENTIFIED BY " . $database->quote($password);
|
||||
$database->exec($sql);
|
||||
|
||||
return true;
|
||||
} catch (PDOException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user password
|
||||
* @param string $username
|
||||
* @param string $host
|
||||
* @param string $password
|
||||
* @return bool
|
||||
*/
|
||||
public static function updateUserPassword($username, $host, $password)
|
||||
{
|
||||
if (empty($password)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
try {
|
||||
$sql = "ALTER USER " . $database->quote($username) . "@" . $database->quote($host) .
|
||||
" IDENTIFIED BY " . $database->quote($password);
|
||||
$database->exec($sql);
|
||||
|
||||
return true;
|
||||
} catch (PDOException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user privileges
|
||||
* @param string $username
|
||||
* @param string $host
|
||||
* @param array $privileges
|
||||
* @return bool
|
||||
*/
|
||||
public static function updateUserPrivileges($username, $host, $privileges)
|
||||
{
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
try {
|
||||
$sql = "REVOKE ALL PRIVILEGES, GRANT OPTION FROM " .
|
||||
$database->quote($username) . "@" . $database->quote($host);
|
||||
$database->exec($sql);
|
||||
|
||||
if (!empty($privileges) && is_array($privileges)) {
|
||||
if (in_array('ALL PRIVILEGES', $privileges)) {
|
||||
$sql = "GRANT ALL PRIVILEGES ON *.* TO " .
|
||||
$database->quote($username) . "@" . $database->quote($host);
|
||||
$database->exec($sql);
|
||||
} else {
|
||||
$valid_privs = array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP', 'ALTER', 'INDEX',
|
||||
'REFERENCES', 'CREATE TEMPORARY TABLES', 'LOCK TABLES', 'EXECUTE',
|
||||
'CREATE VIEW', 'SHOW VIEW', 'CREATE ROUTINE', 'ALTER ROUTINE', 'EVENT', 'TRIGGER');
|
||||
$privileges = array_intersect($privileges, $valid_privs);
|
||||
|
||||
if (!empty($privileges)) {
|
||||
$priv_string = implode(', ', $privileges);
|
||||
$sql = "GRANT " . $priv_string . " ON *.* TO " .
|
||||
$database->quote($username) . "@" . $database->quote($host);
|
||||
$database->exec($sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$database->exec("FLUSH PRIVILEGES");
|
||||
|
||||
return true;
|
||||
} catch (PDOException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a database user
|
||||
* @param string $username
|
||||
* @param string $host
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteUser($username, $host)
|
||||
{
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
try {
|
||||
$sql = "DROP USER " . $database->quote($username) . "@" . $database->quote($host);
|
||||
$database->exec($sql);
|
||||
|
||||
return true;
|
||||
} catch (PDOException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate username format
|
||||
* @param string $username
|
||||
* @return bool
|
||||
*/
|
||||
private static function validateUsername($username)
|
||||
{
|
||||
return !empty($username) && preg_match('/^[a-zA-Z0-9_]+$/', $username);
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,6 @@ class TableModel
|
||||
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
// Build column definitions
|
||||
$column_definitions = array();
|
||||
foreach ($columns as $column) {
|
||||
$definition = "`" . $column['name'] . "` " . $column['type'];
|
||||
@@ -151,7 +150,6 @@ class TableModel
|
||||
$column_definitions[] = $definition;
|
||||
}
|
||||
|
||||
// Handle primary key
|
||||
foreach ($columns as $column) {
|
||||
if (isset($column['key']) && $column['key'] === 'PRI') {
|
||||
$column_definitions[] = "PRIMARY KEY (`" . $column['name'] . "`)";
|
||||
@@ -260,6 +258,169 @@ class TableModel
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the primary key column name for a table
|
||||
* @param string $database_name
|
||||
* @param string $table_name
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getPrimaryKeyColumn($database_name, $table_name)
|
||||
{
|
||||
$columns = self::getTableColumns($database_name, $table_name);
|
||||
foreach ($columns as $column) {
|
||||
if ($column['Key'] === 'PRI') {
|
||||
return $column['Field'];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single row by primary key
|
||||
* @param string $database_name
|
||||
* @param string $table_name
|
||||
* @param mixed $pk_value
|
||||
* @return array|null
|
||||
*/
|
||||
public static function getRow($database_name, $table_name, $pk_value)
|
||||
{
|
||||
$pk_column = self::getPrimaryKeyColumn($database_name, $table_name);
|
||||
if (!$pk_column) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
$sql = "SELECT * FROM `" . $database_name . "`.`" . $table_name . "` WHERE `" . $pk_column . "` = :pk_value LIMIT 1";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute(array(':pk_value' => $pk_value));
|
||||
|
||||
return $query->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a row in the table
|
||||
* @param string $database_name
|
||||
* @param string $table_name
|
||||
* @param mixed $pk_value
|
||||
* @param array $data - associative array of column => value
|
||||
* @return bool
|
||||
*/
|
||||
public static function updateRow($database_name, $table_name, $pk_value, $data)
|
||||
{
|
||||
if (!$database_name || !$table_name || !$pk_value || empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pk_column = self::getPrimaryKeyColumn($database_name, $table_name);
|
||||
if (!$pk_column) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
$set_parts = array();
|
||||
$params = array();
|
||||
$i = 0;
|
||||
foreach ($data as $column => $value) {
|
||||
if ($column === $pk_column) {
|
||||
continue;
|
||||
}
|
||||
$param_name = ':param_' . $i;
|
||||
$set_parts[] = "`" . $column . "` = " . $param_name;
|
||||
$params[$param_name] = $value === '' ? null : $value;
|
||||
$i++;
|
||||
}
|
||||
|
||||
if (empty($set_parts)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$params[':pk_value'] = $pk_value;
|
||||
|
||||
try {
|
||||
$sql = "UPDATE `" . $database_name . "`.`" . $table_name . "` SET " . implode(', ', $set_parts) . " WHERE `" . $pk_column . "` = :pk_value";
|
||||
$query = $database->prepare($sql);
|
||||
return $query->execute($params);
|
||||
} catch (PDOException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a row from the table
|
||||
* @param string $database_name
|
||||
* @param string $table_name
|
||||
* @param mixed $pk_value
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteRow($database_name, $table_name, $pk_value)
|
||||
{
|
||||
if (!$database_name || !$table_name || !$pk_value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pk_column = self::getPrimaryKeyColumn($database_name, $table_name);
|
||||
if (!$pk_column) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
try {
|
||||
$sql = "DELETE FROM `" . $database_name . "`.`" . $table_name . "` WHERE `" . $pk_column . "` = :pk_value";
|
||||
$query = $database->prepare($sql);
|
||||
return $query->execute(array(':pk_value' => $pk_value));
|
||||
} catch (PDOException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new row into the table
|
||||
* @param string $database_name
|
||||
* @param string $table_name
|
||||
* @param array $data - associative array of column => value
|
||||
* @return bool|int - returns insert ID on success, false on failure
|
||||
*/
|
||||
public static function insertRow($database_name, $table_name, $data)
|
||||
{
|
||||
if (!$database_name || !$table_name || empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$database = DatabaseFactory::getFactory()->getConnection();
|
||||
|
||||
$columns = array();
|
||||
$placeholders = array();
|
||||
$params = array();
|
||||
$i = 0;
|
||||
|
||||
foreach ($data as $column => $value) {
|
||||
if ($value === '' || $value === null) {
|
||||
continue;
|
||||
}
|
||||
$columns[] = "`" . $column . "`";
|
||||
$param_name = ':param_' . $i;
|
||||
$placeholders[] = $param_name;
|
||||
$params[$param_name] = $value;
|
||||
$i++;
|
||||
}
|
||||
|
||||
if (empty($columns)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$sql = "INSERT INTO `" . $database_name . "`.`" . $table_name . "` (" . implode(', ', $columns) . ") VALUES (" . implode(', ', $placeholders) . ")";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute($params);
|
||||
return $database->lastInsertId();
|
||||
} catch (PDOException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format bytes to human readable format
|
||||
* @param int $bytes
|
||||
|
||||
Reference in New Issue
Block a user