Import alt-mysql plugin

This commit is contained in:
Marek Miklewicz
2026-07-04 15:48:19 +02:00
commit d71fcf9ace
101 changed files with 18635 additions and 0 deletions
+150
View File
@@ -0,0 +1,150 @@
<?php
declare(strict_types=1);
return static function (AppContext $ctx): void {
$ok = [];
$errors = [];
$daUser = $ctx->daUser->username();
$prefix = $ctx->daUser->prefix();
$showRemoteHosts = $ctx->settings->allowRemoteHosts();
$fixedHosts = array_flip($ctx->mysql->requiredAccessHosts());
$databases = $ctx->mysql->listDatabasesForUser($daUser);
$dbNames = array_map(static fn(array $db): string => $db['name'], $databases);
if ($ctx->isPost()) {
try {
$ctx->requireCsrf('create_user_submit');
$role = NamePolicy::normalizeRoleName($ctx->postString('role_name'), $prefix);
if ($ctx->mysql->roleExists($role)) {
throw new RuntimeException('Użytkownik MySQL już istnieje: ' . $role);
}
$password = $ctx->postString('password');
if (strlen($password) < 12) {
throw new RuntimeException('Hasło użytkownika musi mieć co najmniej 12 znaków.');
}
$selectedDbsRaw = $ctx->postArray('databases');
$selectedDbs = [];
foreach ($selectedDbsRaw as $db) {
$normalizedDb = NamePolicy::normalizeDatabaseName($db, $prefix);
if (!in_array($normalizedDb, $dbNames, true)) {
throw new RuntimeException('Nieprawidłowa baza do przypisania: ' . $normalizedDb);
}
$selectedDbs[] = $normalizedDb;
}
$selectedDbs = array_values(array_unique($selectedDbs));
$privileges = NamePolicy::sanitizePrivileges($ctx->postArray('privileges'));
if (empty($privileges)) {
$privileges = NamePolicy::defaultPrivileges();
}
$hostMap = [];
if ($showRemoteHosts) {
$remoteHostRaw = trim($ctx->postString('remote_host'));
if ($remoteHostRaw !== '') {
$remoteHost = NamePolicy::normalizeRemoteIpv4Host($remoteHostRaw);
$remoteComment = NamePolicy::normalizeHostComment($ctx->postString('remote_comment'));
$hostMap[$remoteHost] = $remoteComment;
}
}
$customHostsCount = 0;
foreach (array_keys($hostMap) as $host) {
if (!isset($fixedHosts[$host])) {
$customHostsCount++;
}
}
if ($customHostsCount > $ctx->settings->maxHostsPerUser()) {
throw new RuntimeException('Przekroczono limit hostów dla użytkownika MySQL.');
}
$hostEntries = [];
foreach ($hostMap as $host => $note) {
$hostEntries[] = ['host' => $host, 'note' => $note];
}
$ctx->mysql->createRole($role, $password);
try {
$ctx->mysql->replaceRoleHostsWithNotes($daUser, $role, $hostEntries);
foreach ($selectedDbs as $dbName) {
$ctx->mysql->grantPrivileges($dbName, $role, $privileges);
}
$sync = $ctx->mysql->syncHostRules();
if (!$sync['ok']) {
$errors[] = 'Użytkownik został utworzony, ale synchronizacja hostów MySQL nie powiodła się: ' . $sync['output'];
}
$ok[] = 'Utworzono użytkownika ' . $role . ' i przypisano ' . count($selectedDbs) . ' baz(y).';
} catch (Throwable $inner) {
try {
foreach ($selectedDbs as $dbName) {
$ctx->mysql->revokePrivileges($dbName, $role);
}
$ctx->mysql->deleteRoleHosts($daUser, $role);
$ctx->mysql->dropRole($role);
} catch (Throwable $ignored) {
}
throw $inner;
}
} catch (Throwable $e) {
$errors[] = $e->getMessage();
}
}
$dbCheckboxes = '';
foreach ($dbNames as $dbName) {
$dbCheckboxes .= '<label class="inline"><input type="checkbox" name="databases[]" value="' . AppContext::e($dbName) . '"> ' . AppContext::e($dbName) . '</label>';
}
if ($dbCheckboxes === '') {
$dbCheckboxes = '<p class="muted">Brak baz do przypisania.</p>';
}
$privCheckboxes = '';
foreach (NamePolicy::PRIVILEGE_LABELS as $code => $label) {
$checked = ($code === 'ALL') ? ' checked' : '';
$privCheckboxes .= '<label class="inline"><input type="checkbox" name="privileges[]" value="' . AppContext::e($code) . '"' . $checked . '> ' . AppContext::e($label) . '</label>';
}
$remoteFields = '';
if ($showRemoteHosts) {
$remoteFields .= '<div class="row">';
$remoteFields .= '<div><label>Dodatkowy host IPv4</label><input type="text" name="remote_host" placeholder="203.0.113.10"></div>';
$remoteFields .= '<div><label>Komentarz hosta</label><input type="text" name="remote_comment" placeholder="np. Laptop administratora"></div>';
$remoteFields .= '</div>';
} else {
$remoteFields .= '<p class="muted">Hosty zdalne są wyłączone w konfiguracji pluginu (`allow_remote_hosts=0`).</p>';
}
$body = '';
$body .= '<form method="post">';
$body .= $ctx->csrfField('create_user_submit');
$body .= '<div class="row">';
$body .= '<div><label>Nazwa użytkownika MySQL</label><input type="text" name="role_name" placeholder="' . AppContext::e($prefix) . 'app_user" required></div>';
$body .= '<div><label>Hasło</label><input type="password" name="password" placeholder="min. 12 znaków" required></div>';
$body .= '</div>';
$defaultAccessText = '`localhost` jest dodawany automatycznie.';
if (count($fixedHosts) > 1) {
$defaultAccessText .= ' Przy zdalnym serwerze MySQL plugin dodaje tez adres IP serwera DirectAdmin.';
}
$body .= '<div class="row">';
$body .= '<div><label>Domyślny dostęp</label><p class="muted">' . $defaultAccessText . '</p></div>';
$body .= '<div><label>Przypisz do baz</label><div>' . $dbCheckboxes . '</div></div>';
$body .= '</div>';
$body .= $remoteFields;
$body .= '<div class="panel"><h3>Uprawnienia dla przypisywanych baz</h3><div class="privileges-group" data-privileges-group>' . $privCheckboxes . '</div></div>';
$body .= '<div class="actions"><button class="primary" type="submit">Utwórz użytkownika</button></div>';
$body .= '</form>';
$ctx->renderPage('Tworzenie Użytkownika MySQL', $body, $ok, $errors);
};