BastionGuard/webui/web_users.php
specialworld83 f0f913a209 Release 2.0
2026-07-15 10:52:22 +02:00

197 lines
11 KiB
PHP

<?php
include 'auth.php';
bg_require_admin();
$page_title = bg_t('webpanel_users_setup') . ' - BastionGuard WebUI';
$active_page = 'web_users.php';
$editing = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
csrf_validate();
$action = $_POST['action'] ?? '';
try {
if ($action === 'create') {
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
$confirm = $_POST['confirm'] ?? '';
$role = $_POST['role'] ?? 'user';
$email = trim($_POST['email'] ?? '');
if ($password !== $confirm) throw new RuntimeException(bg_t('confirm') . ': password mismatch.');
bg_create_user($username, $password, $role, $email);
bg_flash('success', bg_t('user_created'));
bg_redirect('web_users.php');
}
if ($action === 'update') {
$id = (int)($_POST['id'] ?? 0);
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
$confirm = $_POST['confirm'] ?? '';
$role = $_POST['role'] ?? 'user';
$email = trim($_POST['email'] ?? '');
if ($password !== '' && $password !== $confirm) throw new RuntimeException(bg_t('confirm') . ': password mismatch.');
bg_update_user($id, $username, $role, $password, $email);
if ($username === bg_current_user()) {
$_SESSION['user'] = $username;
$_SESSION['role'] = bg_normalize_role($role);
}
bg_flash('success', bg_t('user_updated'));
bg_redirect('web_users.php');
}
if ($action === 'delete') {
bg_delete_user((int)($_POST['id'] ?? 0));
bg_flash('success', bg_t('user_deleted'));
bg_redirect('web_users.php');
}
} catch (Throwable $e) {
bg_flash('danger', $e->getMessage());
bg_redirect('web_users.php');
}
}
$editId = isset($_GET['edit']) ? (int)$_GET['edit'] : 0;
if ($editId > 0) $editing = bg_user_by_id($editId);
$users = bg_users_all();
$adminCount = 0; $standardCount = 0;
foreach ($users as $u) { if (($u['role'] ?? 'user') === 'admin') $adminCount++; else $standardCount++; }
include 'includes/header.php';
include 'includes/sidebar.php';
?>
<div class="page-title web-users-title">
<div>
<span class="section-eyebrow"><i class="bi bi-people"></i> <?= bg_e(bg_t('system')) ?></span>
<h1><?= bg_e(bg_t('webpanel_users_setup')) ?></h1>
<p><?= bg_e(bg_t('users_setup_desc')) ?></p>
</div>
<div class="d-flex gap-2 flex-wrap justify-content-end">
<span class="badge text-bg-primary"><i class="bi bi-shield-check"></i> <?= bg_e(bg_t('admin')) ?>: <?= (int)$adminCount ?></span>
<span class="badge text-bg-secondary"><i class="bi bi-person"></i> <?= bg_e(bg_t('standard_user')) ?>: <?= (int)$standardCount ?></span>
</div>
</div>
<div class="web-users-hero card mb-4">
<div class="card-body d-flex align-items-center justify-content-between gap-3 flex-wrap">
<div class="d-flex align-items-center gap-3">
<div class="hero-icon"><i class="bi bi-people"></i></div>
<div>
<h5 class="mb-1"><?= bg_e(bg_t('current_user')) ?>: <?= bg_e(bg_current_user()) ?></h5>
<p class="mb-0 small-muted"><?= bg_e(bg_t(bg_current_user_is_admin() ? 'admin' : 'standard_user')) ?> · <?= bg_e(bg_t(bg_current_user_is_admin() ? 'current_admin_desc' : 'current_standard_desc')) ?></p>
</div>
</div>
<?php if (!$editing): ?>
<a class="btn btn-outline-primary" href="#user-form"><i class="bi bi-plus-circle"></i> <?= bg_e(bg_t('create_user')) ?></a>
<?php else: ?>
<a class="btn btn-outline-secondary" href="web_users.php"><i class="bi bi-x-circle"></i> <?= bg_e(bg_t('cancel')) ?></a>
<?php endif; ?>
</div>
</div>
<div class="row g-4 web-users-grid">
<div class="col-lg-5">
<div class="card h-100 web-user-form-card" id="user-form">
<div class="card-body">
<div class="d-flex align-items-start justify-content-between gap-2 mb-3">
<div>
<span class="section-eyebrow"><i class="bi bi-key"></i> <?= bg_e($editing ? bg_t('edit_user') : bg_t('new_user')) ?></span>
<h5 class="mb-1"><?= bg_e($editing ? bg_t('edit_user') : bg_t('new_user')) ?></h5>
<p class="small-muted mb-0"><?= bg_e(bg_t('admin_required_desc')) ?></p>
</div>
<span class="badge <?= $editing ? 'text-bg-warning' : 'text-bg-success' ?>"><?= bg_e($editing ? bg_t('edit_user') : bg_t('create_user')) ?></span>
</div>
<form method="post" autocomplete="off" class="web-user-form">
<?php csrf_field(); ?>
<input type="hidden" name="action" value="<?= $editing ? 'update' : 'create' ?>">
<?php if ($editing): ?><input type="hidden" name="id" value="<?= (int)$editing['id'] ?>"><?php endif; ?>
<div class="mb-3">
<label class="form-label" for="web_username"><?= bg_e(bg_t('username')) ?></label>
<input class="form-control" id="web_username" name="username" value="<?= bg_e($editing['username'] ?? '') ?>" required>
</div>
<div class="mb-3">
<label class="form-label" for="web_email"><?= bg_e(bg_t('email_address')) ?></label>
<input class="form-control" id="web_email" name="email" type="email" value="<?= bg_e($editing['email'] ?? '') ?>" placeholder="admin@example.com">
<div class="form-hint"><?= bg_e(bg_t('admin_email_hint')) ?></div>
</div>
<div class="mb-3">
<label class="form-label" for="web_role"><?= bg_e(bg_t('role')) ?></label>
<?php $r = $editing['role'] ?? 'user'; ?>
<div class="role-picker">
<label class="role-card <?= $r === 'admin' ? 'selected' : '' ?>">
<input type="radio" name="role" value="admin" <?= $r === 'admin' ? 'checked' : '' ?>>
<span><strong><?= bg_e(bg_t('admin')) ?></strong><small><?= bg_e(bg_language()==='en' ? 'Full access to WebPanel, users and BastionGuard configuration files.' : 'Accesso completo a WebPanel, utenti e file di configurazione BastionGuard.') ?></small></span>
</label>
<label class="role-card <?= $r === 'user' ? 'selected' : '' ?>">
<input type="radio" name="role" value="user" <?= $r === 'user' ? 'checked' : '' ?>>
<span><strong><?= bg_e(bg_t('standard_user')) ?></strong><small><?= bg_e(bg_language()==='en' ? 'Can use the WebUI but cannot edit BastionGuard configuration files.' : 'Può usare la WebUI ma non può modificare i file di configurazione BastionGuard.') ?></small></span>
</label>
</div>
</div>
<div class="row g-2">
<div class="col-md-6">
<label class="form-label" for="web_password"><?= bg_e($editing ? bg_t('optional_password') : bg_t('password')) ?></label>
<input class="form-control" id="web_password" name="password" type="password" <?= $editing ? '' : 'required' ?> minlength="8">
</div>
<div class="col-md-6">
<label class="form-label" for="web_confirm"><?= bg_e(bg_t('confirm')) ?></label>
<input class="form-control" id="web_confirm" name="confirm" type="password" <?= $editing ? '' : 'required' ?> minlength="8">
</div>
</div>
<div class="d-flex gap-2 mt-3 flex-wrap">
<button class="btn btn-primary" type="submit"><i class="bi bi-save"></i> <?= bg_e($editing ? bg_t('save_user') : bg_t('create_user')) ?></button>
<?php if ($editing): ?><a class="btn btn-outline-secondary" href="web_users.php"><?= bg_e(bg_t('cancel')) ?></a><?php endif; ?>
</div>
</form>
</div>
</div>
</div>
<div class="col-lg-7">
<div class="card h-100 web-users-list-card">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between mb-3 gap-2 flex-wrap">
<div>
<span class="section-eyebrow"><i class="bi bi-shield-check"></i> <?= bg_e(bg_t('webpanel_users')) ?></span>
<h5 class="mb-0"><?= bg_e(bg_t('existing_users')) ?></h5>
</div>
<span class="badge text-bg-light"><?= count($users) ?> <?= bg_e(bg_t('webpanel_users')) ?></span>
</div>
<div class="table-responsive web-users-table-wrap">
<table class="table align-middle web-users-table">
<thead><tr><th><?= bg_e(bg_t('username')) ?></th><th><?= bg_e(bg_t('email_address')) ?></th><th><?= bg_e(bg_t('role')) ?></th><th><?= bg_e(bg_t('created_at')) ?></th><th class="text-end"><?= bg_e(bg_t('actions')) ?></th></tr></thead>
<tbody>
<?php foreach ($users as $u): ?>
<tr>
<td>
<div class="user-cell">
<span class="user-avatar"><?= bg_e(strtoupper(substr((string)$u['username'],0,1))) ?></span>
<div><strong><?= bg_e($u['username']) ?></strong><?php if ($u['username'] === bg_current_user()): ?><span class="badge text-bg-info ms-2"><?= bg_e(bg_t('current_user')) ?></span><?php endif; ?></div>
</div>
</td>
<td class="small-muted"><?= bg_e($u['email'] ?? '') ?></td>
<td><span class="badge <?= ($u['role'] ?? 'user') === 'admin' ? 'text-bg-primary' : 'text-bg-secondary' ?>"><?= bg_e(bg_t(($u['role'] ?? 'user') === 'admin' ? 'admin' : 'standard_user')) ?></span></td>
<td class="small-muted"><?= bg_e($u['created_at'] ?? '') ?></td>
<td class="text-end">
<div class="d-flex gap-2 justify-content-end flex-wrap">
<a class="btn btn-sm btn-outline-primary" href="web_users.php?edit=<?= (int)$u['id'] ?>"><i class="bi bi-pencil"></i> <?= bg_e(bg_t('edit_user')) ?></a>
<?php if ($u['username'] !== bg_current_user()): ?>
<form method="post" class="d-inline" data-confirm="<?= bg_e(bg_t('delete_user')) ?>?">
<?php csrf_field(); ?><input type="hidden" name="action" value="delete"><input type="hidden" name="id" value="<?= (int)$u['id'] ?>">
<button class="btn btn-sm btn-outline-danger" type="submit"><i class="bi bi-trash"></i> <?= bg_e(bg_t('delete')) ?></button>
</form>
<?php endif; ?>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<script>
document.querySelectorAll('.role-card input').forEach(function(input){
input.addEventListener('change', function(){
document.querySelectorAll('.role-card').forEach(function(card){card.classList.toggle('selected', !!card.querySelector('input:checked'));});
});
});
</script>
<?php include 'includes/footer.php'; ?>