Some more changes for Docker

This commit is contained in:
Fabio Herzig
2026-07-25 22:30:48 +02:00
parent 40a1bdd379
commit f10ff26b30
6 changed files with 957 additions and 3 deletions
+203
View File
@@ -0,0 +1,203 @@
<?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);
}
}