Files
2026-07-04 16:00:04 +02:00

159 lines
6.4 KiB
PHP

<?php
declare(strict_types=1);
return static function (AppContext $ctx): void {
$ok = [];
$errors = [];
$daUser = $ctx->daUser->username();
$prefix = $ctx->daUser->prefix();
$availableRoles = array_map(static fn(array $r): string => $r['name'], $ctx->pg->listRolesForUser($daUser));
$selectedRoles = $ctx->postArray('roles');
if (empty($selectedRoles)) {
$queryRole = $ctx->queryString('role');
if ($queryRole !== '') {
$selectedRoles = [$queryRole];
}
}
$selectedRoles = array_values(array_unique(array_filter($selectedRoles, static fn(string $v): bool => $v !== '')));
$confirmDelete = $ctx->postString('confirm_delete') === '1';
if ($ctx->isPost() && !$confirmDelete) {
try {
$ctx->requireCsrf('select_delete_users');
} catch (Throwable $e) {
$errors[] = $e->getMessage();
$selectedRoles = [];
}
}
if ($ctx->isPost() && $confirmDelete) {
try {
$ctx->requireCsrf('delete_users_confirm');
if (empty($selectedRoles)) {
throw new RuntimeException('Nie wybrano użytkowników do usunięcia.');
}
$deleted = [];
$skipped = [];
foreach ($selectedRoles as $rawRole) {
try {
$role = NamePolicy::normalizeRoleName($rawRole, $prefix);
if (!in_array($role, $availableRoles, true)) {
$skipped[] = $role . ' (nie istnieje)';
continue;
}
$owned = $ctx->pg->roleOwnedDatabases($role, $daUser);
if (!empty($owned)) {
$skipped[] = $role . ' (właściciel baz: ' . implode(', ', $owned) . ')';
continue;
}
$assigned = $ctx->pg->roleAssignedDatabases($role, $daUser);
foreach ($assigned as $dbName) {
$owner = $ctx->pg->getDatabaseOwner($dbName);
if ($owner !== null && $owner !== $role) {
$ctx->pg->reassignOwnedObjects($dbName, $role, $owner);
}
$ctx->pg->revokePrivileges($dbName, $role);
}
$ctx->pg->deleteRoleHosts($daUser, $role);
$ctx->pg->dropRole($role);
$deleted[] = $role;
} catch (Throwable $inner) {
$skipped[] = $rawRole . ' (' . $inner->getMessage() . ')';
}
}
$sync = $ctx->pg->syncHbaRules();
if (!$sync['ok']) {
$errors[] = 'Usuwanie wykonane, ale synchronizacja pg_hba nie powiodła się: ' . $sync['output'];
}
if (!empty($deleted)) {
$ok[] = 'Usunięto użytkowników: ' . implode(', ', $deleted);
}
if (!empty($skipped)) {
$errors[] = 'Nie usunięto: ' . implode('; ', $skipped);
}
$selectedRoles = [];
$availableRoles = array_map(static fn(array $r): string => $r['name'], $ctx->pg->listRolesForUser($daUser));
} catch (Throwable $e) {
$errors[] = $e->getMessage();
}
}
if (empty($selectedRoles)) {
$rows = '';
foreach ($availableRoles as $roleName) {
$assigned = $ctx->pg->roleAssignedDatabases($roleName, $daUser);
$owned = $ctx->pg->roleOwnedDatabases($roleName, $daUser);
$rows .= '<tr>';
$rows .= '<td><input type="checkbox" name="roles[]" value="' . AppContext::e($roleName) . '"></td>';
$rows .= '<td>' . AppContext::e($roleName) . '</td>';
$rows .= '<td>' . AppContext::e(implode(', ', $assigned)) . '</td>';
$rows .= '<td>' . AppContext::e(implode(', ', $owned)) . '</td>';
$rows .= '</tr>';
}
if ($rows === '') {
$rows = '<tr><td colspan="4" class="muted">Brak użytkowników do usunięcia.</td></tr>';
}
$body = '';
$body .= '<form method="post">';
$body .= $ctx->csrfField('select_delete_users');
$body .= '<table><thead><tr><th></th><th>Użytkownik</th><th>Przypisane bazy</th><th>Bazy, których jest właścicielem</th></tr></thead><tbody>' . $rows . '</tbody></table>';
$body .= '<div class="actions"><button class="danger" type="submit">Usuń zaznaczonych użytkowników</button></div>';
$body .= '</form>';
$ctx->renderPage('Usuwanie Użytkowników', $body, $ok, $errors);
return;
}
$confirmRows = '';
foreach ($selectedRoles as $rawRole) {
try {
$role = NamePolicy::normalizeRoleName($rawRole, $prefix);
$assigned = $ctx->pg->roleAssignedDatabases($role, $daUser);
$owned = $ctx->pg->roleOwnedDatabases($role, $daUser);
$confirmRows .= '<tr>';
$confirmRows .= '<td>' . AppContext::e($role) . '<input type="hidden" name="roles[]" value="' . AppContext::e($role) . '"></td>';
$confirmRows .= '<td>' . AppContext::e(implode(', ', $assigned)) . '</td>';
$confirmRows .= '<td>' . AppContext::e(implode(', ', $owned)) . '</td>';
$confirmRows .= '</tr>';
} catch (Throwable $e) {
$errors[] = $rawRole . ': ' . $e->getMessage();
}
}
if ($confirmRows === '') {
$ctx->renderPage('Usuwanie Użytkowników', '<p class="muted">Brak poprawnych użytkowników do usunięcia.</p>', $ok, $errors);
return;
}
$body = '';
$body .= '<p>Potwierdź usunięcie zaznaczonych użytkowników PostgreSQL. Operacja jest nieodwracalna.</p>';
$body .= '<form method="post">';
$body .= $ctx->csrfField('delete_users_confirm');
$body .= '<input type="hidden" name="confirm_delete" value="1">';
$body .= '<table><thead><tr><th>Użytkownik</th><th>Przypisane bazy</th><th>Bazy, których jest właścicielem</th></tr></thead><tbody>';
$body .= $confirmRows;
$body .= '</tbody></table>';
$body .= '<div class="actions">';
$body .= '<button class="danger" type="submit">Potwierdź usunięcie</button>';
$body .= '<a class="btn" href="' . AppContext::e($ctx->url('delete_users.html')) . '">Anuluj</a>';
$body .= '</div>';
$body .= '</form>';
$ctx->renderPage('Potwierdzenie Usuwania Użytkowników', $body, $ok, $errors);
};