Files
alt-mysql/exec/handlers/manage_hosts.php
T
2026-07-04 15:48:19 +02:00

163 lines
6.3 KiB
PHP

<?php
declare(strict_types=1);
return static function (AppContext $ctx): void {
if (!$ctx->settings->allowRemoteHosts()) {
$ctx->renderFatal('Zarządzanie hostami zdalnymi jest wyłączone (`allow_remote_hosts=0`).', 403);
return;
}
$ok = [];
$errors = [];
$daUser = $ctx->daUser->username();
$prefix = $ctx->daUser->prefix();
$fixedHosts = array_flip($ctx->mysql->requiredAccessHosts());
if (!$ctx->isPost()) {
$sync = $ctx->mysql->syncHostRules();
if (!$sync['ok']) {
$errors[] = 'Synchronizacja zdalnych hostów MySQL nie powiodła się: ' . $sync['output'];
}
}
$roleNames = array_map(static fn(array $r): string => $r['name'], $ctx->mysql->listRolesForUser($daUser));
$selectedRole = $ctx->queryString('role');
if ($ctx->isPost()) {
$selectedRole = $ctx->postString('role_name');
try {
$ctx->requireCsrf('manage_hosts_submit');
$selectedRole = NamePolicy::normalizeRoleName($selectedRole, $prefix);
if (!in_array($selectedRole, $roleNames, true)) {
throw new RuntimeException('Użytkownik MySQL nie należy do konta DA: ' . $selectedRole);
}
$currentEntries = $ctx->mysql->getRoleHostEntries($daUser, $selectedRole);
$hostMap = [];
foreach ($currentEntries as $entry) {
$hostMap[$entry['host']] = $entry['note'];
}
$removeHosts = $ctx->postArray('remove_hosts');
$removeHosts = array_values(array_unique($removeHosts));
foreach ($removeHosts as $rawHost) {
$host = trim($rawHost);
if ($host === '' || isset($fixedHosts[$host])) {
continue;
}
if (array_key_exists($host, $hostMap)) {
unset($hostMap[$host]);
}
}
$addHostRaw = trim($ctx->postString('add_host'));
if ($addHostRaw !== '') {
$addHost = NamePolicy::normalizeRemoteIpv4Host($addHostRaw);
$addComment = NamePolicy::normalizeHostComment($ctx->postString('add_comment'));
$hostMap[$addHost] = $addComment;
}
$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.');
}
$finalEntries = [];
foreach ($hostMap as $host => $note) {
$finalEntries[] = ['host' => $host, 'note' => $note];
}
$ctx->mysql->replaceRoleHostsWithNotes($daUser, $selectedRole, $finalEntries);
$sync = $ctx->mysql->syncHostRules();
if (!$sync['ok']) {
$errors[] = 'Hosty zapisane, ale synchronizacja hostów MySQL nie powiodła się: ' . $sync['output'];
}
$ok[] = 'Zaktualizowano hosty dostępu dla użytkownika ' . $selectedRole . '.';
} catch (Throwable $e) {
$errors[] = $e->getMessage();
}
}
if ($selectedRole !== '') {
try {
$selectedRole = NamePolicy::normalizeRoleName($selectedRole, $prefix);
} catch (Throwable $e) {
$selectedRole = '';
}
}
if ($selectedRole === '' && !empty($roleNames)) {
$selectedRole = $roleNames[0];
}
$currentEntries = [];
if ($selectedRole !== '') {
$currentEntries = $ctx->mysql->getRoleHostEntries($daUser, $selectedRole);
}
$roleOptions = '<option value="">-- wybierz użytkownika --</option>';
foreach ($roleNames as $roleName) {
$sel = ($roleName === $selectedRole) ? ' selected' : '';
$roleOptions .= '<option value="' . AppContext::e($roleName) . '"' . $sel . '>' . AppContext::e($roleName) . '</option>';
}
$hostRows = '';
if (empty($currentEntries)) {
$hostRows = '<tr><td colspan="3" class="muted">Brak zapisanych hostów.</td></tr>';
} else {
foreach ($currentEntries as $entry) {
$host = $entry['host'];
$note = $entry['note'];
$canRemove = !isset($fixedHosts[$host]);
$hostRows .= '<tr>';
$hostRows .= '<td>' . AppContext::e($host) . '</td>';
$hostRows .= '<td>' . AppContext::e($note) . '</td>';
if ($canRemove) {
$hostRows .= '<td><label class="inline"><input type="checkbox" name="remove_hosts[]" value="' . AppContext::e($host) . '"> usuń</label></td>';
} else {
$hostRows .= '<td><span class="muted">host stały</span></td>';
}
$hostRows .= '</tr>';
}
}
$body = '';
$body .= '<form method="post">';
$body .= $ctx->csrfField('manage_hosts_submit');
$body .= '<div class="row">';
$body .= '<div><label>Użytkownik MySQL</label><select name="role_name" required>' . $roleOptions . '</select></div>';
$body .= '<div><label>Dodaj IPv4</label><input type="text" name="add_host" placeholder="198.51.100.12"></div>';
$body .= '</div>';
$infoText = 'Dozwolone są wyłącznie pojedyncze adresy IPv4, bez CIDR i bez nazw hostów.';
if (count($fixedHosts) > 1) {
$infoText .= ' `localhost` oraz adres IP serwera DirectAdmin sa hostami stalymi i nie mozna ich usunac.';
} else {
$infoText .= ' `localhost` jest hostem stalym i nie mozna go usunac.';
}
$body .= '<div class="row">';
$body .= '<div><label>Komentarz do nowego hosta</label><input type="text" name="add_comment" placeholder="np. serwer aplikacyjny PROD"></div>';
$body .= '<div><label>Informacja</label><p class="muted">' . $infoText . '</p></div>';
$body .= '</div>';
$body .= '<div class="panel"><h3>Aktualne hosty</h3>';
$body .= '<table><thead><tr><th>Host</th><th>Komentarz</th><th>Akcja</th></tr></thead><tbody>' . $hostRows . '</tbody></table>';
$body .= '</div>';
$body .= '<div class="actions"><button class="primary" type="submit">Zapisz hosty</button></div>';
$body .= '</form>';
$ctx->renderPage('Hosty Zdalne Użytkownika', $body, $ok, $errors);
};