Some more changes for Docker
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user