204 lines
7.3 KiB
PHP
204 lines
7.3 KiB
PHP
<?php
|
|
|
|
/**
|
|
* WKVS Database User Generator & Manager Script
|
|
*
|
|
* Functions:
|
|
* 1. Reads database configuration from config/.env.db, config/.env.db-wkvs-user, config/.env.db-guest
|
|
* 2. Connects to MariaDB/MySQL using Root credentials
|
|
* 3. Auto-creates or updates DB users (Normal User with CRUD & Guest User with Read-only)
|
|
* 4. Updates the respective .env files so PHP application stays in sync
|
|
*
|
|
* Can be run via CLI: php setup/database/generate-users.php
|
|
* Or included in web endpoints to change user credentials dynamically.
|
|
*/
|
|
|
|
// Helper to parse simple key=value .env files without requiring composer packages
|
|
function parse_env_file_simple(string $filepath): array {
|
|
$env = [];
|
|
if (!file_exists($filepath)) {
|
|
return $env;
|
|
}
|
|
$lines = file($filepath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
foreach ($lines as $line) {
|
|
$line = trim($line);
|
|
if (empty($line) || str_starts_with($line, '#')) {
|
|
continue;
|
|
}
|
|
$parts = explode('=', $line, 2);
|
|
if (count($parts) === 2) {
|
|
$key = trim($parts[0]);
|
|
$val = trim($parts[1], " \t\n\r\0\x0B\"'");
|
|
$env[$key] = $val;
|
|
}
|
|
}
|
|
return $env;
|
|
}
|
|
|
|
// Helper to write key=value pairs back to a .env file safely
|
|
function write_env_file_simple(string $filepath, array $data): bool {
|
|
$content = "";
|
|
foreach ($data as $key => $val) {
|
|
$content .= "{$key}={$val}\n";
|
|
}
|
|
return file_put_contents($filepath, $content) !== false;
|
|
}
|
|
|
|
// Main logic wrapped in a reusable function
|
|
function sync_and_create_db_users(
|
|
?string $overrideUser = null,
|
|
?string $overrideUserPass = null,
|
|
?string $overrideGuest = null,
|
|
?string $overrideGuestPass = null
|
|
): array {
|
|
$baseDir = dirname(__DIR__, 2);
|
|
$configDir = $baseDir . '/config';
|
|
|
|
$dbEnvFile = $configDir . '/.env.db';
|
|
$userEnvFile = $configDir . '/.env.db-wkvs-user';
|
|
$guestEnvFile = $configDir . '/.env.db-guest';
|
|
|
|
// 1. Load Root DB config
|
|
$dbEnv = parse_env_file_simple($dbEnvFile);
|
|
$rootPass = $dbEnv['MYSQL_ROOT_PASSWORD'] ?? '';
|
|
$dbName = $dbEnv['MYSQL_DATABASE'] ?? 'devdb_';
|
|
|
|
// Target host for MySQL connection from PHP script
|
|
// If running inside Docker container or host, determine host
|
|
$dbHost = getenv('DB_HOST') ?: ($dbEnv['DB_HOST'] ?? 'mariadb');
|
|
$dbPort = (int)($dbEnv['DB_PORT'] ?? 3306);
|
|
|
|
// Fallback connection attempt hosts
|
|
$hostsToTry = [$dbHost, '127.0.0.1', 'mariadb', 'localhost'];
|
|
|
|
$mysqli = null;
|
|
$connectedHost = null;
|
|
|
|
foreach ($hostsToTry as $tryHost) {
|
|
try {
|
|
$testConn = @new mysqli($tryHost, 'root', $rootPass, '', $dbPort);
|
|
if (!$testConn->connect_error) {
|
|
$mysqli = $testConn;
|
|
$connectedHost = $tryHost;
|
|
break;
|
|
}
|
|
} catch (Throwable $e) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!$mysqli) {
|
|
return [
|
|
'success' => false,
|
|
'message' => "Konnte keine Verbindung als 'root' zu MariaDB herstellen. Bitte prüfen Sie MYSQL_ROOT_PASSWORD in config/.env.db."
|
|
];
|
|
}
|
|
|
|
// 2. Load existing user env files or generate defaults
|
|
$userEnv = parse_env_file_simple($userEnvFile);
|
|
$guestEnv = parse_env_file_simple($guestEnvFile);
|
|
|
|
// Prefix helper for usernames if creating new
|
|
$dbUser = $overrideUser ?: ($userEnv['DB_USER'] ?? 'wkvs_user');
|
|
$dbPass = $overrideUserPass ?: ($userEnv['DB_PASSWORD'] ?? bin2hex(random_bytes(16)));
|
|
|
|
$dbGuestUser = $overrideGuest ?: ($guestEnv['DB_GUEST_USER'] ?? 'wkvs_guest');
|
|
$dbGuestPass = $overrideGuestPass?: ($guestEnv['DB_GUEST_PASSWORD'] ?? bin2hex(random_bytes(16)));
|
|
|
|
$appDbHost = $userEnv['DB_HOST'] ?? 'mariadb';
|
|
$appDbPort = $userEnv['DB_PORT'] ?? 3306;
|
|
|
|
// 3. Create database if it does not exist
|
|
$mysqli->query("CREATE DATABASE IF NOT EXISTS `$dbName` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
|
|
|
// 4. Create or Update Normal User (SELECT, INSERT, UPDATE, DELETE)
|
|
// Access is isolated to the Docker network container level via compose.yaml
|
|
$escapedUser = $mysqli->real_escape_string($dbUser);
|
|
$escapedPass = $mysqli->real_escape_string($dbPass);
|
|
$escapedDb = $mysqli->real_escape_string($dbName);
|
|
|
|
// Clean up legacy per-host entries if present
|
|
$mysqli->query("DROP USER IF EXISTS '{$escapedUser}'@'%'");
|
|
|
|
|
|
// Normal User (1 user entry)
|
|
$mysqli->query("CREATE USER IF NOT EXISTS '{$escapedUser}'@'%' IDENTIFIED BY '{$escapedPass}'");
|
|
$mysqli->query("ALTER USER '{$escapedUser}'@'%' IDENTIFIED BY '{$escapedPass}'");
|
|
$mysqli->query("GRANT SELECT, INSERT, UPDATE, DELETE ON `{$escapedDb}`.* TO '{$escapedUser}'@'%'");
|
|
|
|
// Guest User (SELECT only)
|
|
$escapedGuest = $mysqli->real_escape_string($dbGuestUser);
|
|
$escapedGuestPass = $mysqli->real_escape_string($dbGuestPass);
|
|
|
|
// Clean up legacy per-host entries if present
|
|
foreach (['127.0.0.1', 'localhost', '172.%.%.%', '10.%.%.%', '192.168.%.%.%'] as $oldHost) {
|
|
$mysqli->query("DROP USER IF EXISTS '{$escapedGuest}'@'{$oldHost}'");
|
|
}
|
|
|
|
// Guest User (1 user entry)
|
|
$mysqli->query("CREATE USER IF NOT EXISTS '{$escapedGuest}'@'%' IDENTIFIED BY '{$escapedGuestPass}'");
|
|
$mysqli->query("ALTER USER '{$escapedGuest}'@'%' IDENTIFIED BY '{$escapedGuestPass}'");
|
|
$mysqli->query("GRANT SELECT ON `{$escapedDb}`.* TO '{$escapedGuest}'@'%'");
|
|
|
|
$mysqli->query("FLUSH PRIVILEGES");
|
|
$mysqli->close();
|
|
|
|
// 5. Update .env files
|
|
$newUserEnvData = [
|
|
'DB_USER' => $dbUser,
|
|
'DB_PASSWORD' => $dbPass,
|
|
'DB_NAME' => $dbName,
|
|
'DB_HOST' => $appDbHost,
|
|
'DB_PORT' => $appDbPort,
|
|
];
|
|
|
|
$newGuestEnvData = [
|
|
'DB_GUEST_USER' => $dbGuestUser,
|
|
'DB_GUEST_PASSWORD' => $dbGuestPass,
|
|
'DB_NAME' => $dbName,
|
|
'DB_HOST' => $appDbHost,
|
|
'DB_PORT' => $appDbPort,
|
|
];
|
|
|
|
write_env_file_simple($userEnvFile, $newUserEnvData);
|
|
write_env_file_simple($guestEnvFile, $newGuestEnvData);
|
|
|
|
return [
|
|
'success' => true,
|
|
'message' => 'Datenbank-Benutzer erfolgreich erstellt/aktualisiert.',
|
|
'normal_user' => [
|
|
'username' => $dbUser,
|
|
'password' => $dbPass,
|
|
],
|
|
'guest_user' => [
|
|
'username' => $dbGuestUser,
|
|
'password' => $dbGuestPass,
|
|
]
|
|
];
|
|
}
|
|
|
|
// If invoked directly from CLI
|
|
if (php_sapi_name() === 'cli' && realpath($argv[0] ?? '') === __FILE__) {
|
|
echo "=== WKVS Database User Auto-Generator ===\n";
|
|
|
|
$user = $argv[1] ?? null;
|
|
$userPass = $argv[2] ?? null;
|
|
$guest = $argv[3] ?? null;
|
|
$guestPass = $argv[4] ?? null;
|
|
|
|
$result = sync_and_create_db_users($user, $userPass, $guest, $guestPass);
|
|
|
|
if ($result['success']) {
|
|
echo "✓ " . $result['message'] . "\n\n";
|
|
echo "Normal User (SELECT, INSERT, UPDATE, DELETE):\n";
|
|
echo " Benutzername: " . $result['normal_user']['username'] . "\n";
|
|
echo " Passwort: " . $result['normal_user']['password'] . "\n\n";
|
|
echo "Guest User (SELECT only):\n";
|
|
echo " Benutzername: " . $result['guest_user']['username'] . "\n";
|
|
echo " Passwort: " . $result['guest_user']['password'] . "\n";
|
|
} else {
|
|
echo "❌ Fehler: " . $result['message'] . "\n";
|
|
exit(1);
|
|
}
|
|
}
|