Import postgresql plugin
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
<?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();
|
||||
|
||||
$databases = $ctx->pg->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->pg->roleExists($role)) {
|
||||
throw new RuntimeException('Użytkownik PostgreSQL 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();
|
||||
}
|
||||
|
||||
$globalHostEntries = [['host' => 'localhost', 'note' => '']];
|
||||
$remoteHostEntry = null;
|
||||
if ($showRemoteHosts) {
|
||||
$remoteHostRaw = trim($ctx->postString('remote_host'));
|
||||
if ($remoteHostRaw !== '') {
|
||||
$remoteHost = NamePolicy::normalizeRemoteIpv4AccessPattern($remoteHostRaw);
|
||||
$remoteComment = NamePolicy::normalizeHostComment($ctx->postString('remote_comment'));
|
||||
$remoteHostEntry = ['host' => $remoteHost, 'note' => $remoteComment];
|
||||
}
|
||||
}
|
||||
if ($remoteHostEntry !== null && empty($selectedDbs)) {
|
||||
throw new RuntimeException('Host zdalny można dodać tylko dla wybranej bazy.');
|
||||
}
|
||||
|
||||
$ctx->pg->createRole($role, $password);
|
||||
try {
|
||||
$ctx->pg->replaceRoleHostsWithNotes($daUser, $role, $globalHostEntries);
|
||||
|
||||
foreach ($selectedDbs as $dbName) {
|
||||
$ctx->pg->grantPrivileges($dbName, $role, $privileges);
|
||||
if ($remoteHostEntry !== null) {
|
||||
$ctx->pg->replaceRoleHostsWithNotes($daUser, $role, [$remoteHostEntry], $dbName);
|
||||
}
|
||||
}
|
||||
|
||||
$sync = $ctx->pg->syncHbaRules();
|
||||
if (!$sync['ok']) {
|
||||
$errors[] = 'Użytkownik został utworzony, ale synchronizacja pg_hba 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->pg->revokePrivileges($dbName, $role);
|
||||
}
|
||||
$ctx->pg->deleteRoleHosts($daUser, $role);
|
||||
$ctx->pg->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/CIDR</label><input type="text" name="remote_host" placeholder="203.0.113.10 lub 203.0.113.0/24"></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 PostgreSQL</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>';
|
||||
|
||||
$body .= '<div class="row">';
|
||||
$body .= '<div><label>Domyślny dostęp</label><p class="muted">`localhost` jest dodawany automatycznie.</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 PostgreSQL', $body, $ok, $errors);
|
||||
};
|
||||
Reference in New Issue
Block a user