feat: mapa carrega logo no site; sysadmin edita utilizadores (incl. promover a admin)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
andreandClaude Sonnet 5.5 committed 2026-09-29 12:39:36 +01:00
1 parent 4bf177289a
commit f2a9c5181b
4 files changed
+111 -19

No files matched your search

+101
View File
@@ -0,0 +1,101 @@
<?php
// Edição de um utilizador pelo administrador de sistema: nome, email, telefone,
// perfil (incluindo promover a admin) e estado. A palavra-passe continua em
// set_password.php. Só o sysadmin chega aqui — um admin não se pode promover.
require __DIR__ . '/../../config/db.php';
require __DIR__ . '/../../config/functions.php';
$user = require_sysadmin();
$target = db_get_user($pdo, (int) ($_GET['id'] ?? $_POST['id'] ?? 0));
if (!$target) {
header('Location: ' . base_url('views/user/index.php'));
exit;
}
// Não se altera o próprio perfil/estado aqui: evita o sysadmin ficar sem acesso
// por engano (o último sysadmin deixaria de existir).
$is_self = ((int) $target['id'] === (int) $user['id']);
$roles = ['sysadmin', 'admin', 'staff', 'client'];
$error = '';
$saved = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
csrf_check();
$name = trim($_POST['name'] ?? '');
$email = strtolower(trim($_POST['email'] ?? ''));
$phone = trim($_POST['phone'] ?? '');
$role = $is_self ? $target['role'] : (string) ($_POST['role'] ?? '');
$active = $is_self ? (int) $target['is_active'] : (isset($_POST['is_active']) ? 1 : 0);
if ($name === '' || mb_strlen($name) > 100) {
$error = 'Indique um nome (máx. 100 caracteres).';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > 190) {
$error = 'Email inválido.';
} elseif (!in_array($role, $roles, true)) {
$error = 'Perfil inválido.';
} elseif (mb_strlen($phone) > 20) {
$error = 'Telefone demasiado longo (máx. 20 caracteres).';
} else {
$other = db_get_user_by_email($pdo, $email);
if ($other && (int) $other['id'] !== (int) $target['id']) {
$error = 'Já existe outro utilizador com esse email.';
}
}
if ($error === '') {
$fields = ['name', 'email', 'phone', 'role', 'is_active'];
$before = array_intersect_key($target, array_flip($fields));
$new = ['name' => $name, 'email' => $email, 'phone' => $phone !== '' ? $phone : null,
'role' => $role, 'is_active' => $active];
$pdo->prepare('UPDATE users SET name=?, email=?, phone=?, role=?, is_active=? WHERE id=?')
->execute([$name, $email, $new['phone'], $role, $active, (int) $target['id']]);
$changes = platform_audit_diff($before, $new);
if ($changes) {
audit('user.update', [
'target_type' => 'user', 'target_id' => (int) $target['id'],
'target_label' => $name, 'changes' => $changes,
]);
}
$saved = true;
$target = db_get_user($pdo, (int) $target['id']) ?? $target;
} else {
// Mantém o que foi escrito para o formulário não perder as alterações.
$target = array_merge($target, ['name' => $name, 'email' => $email, 'phone' => $phone, 'role' => $role, 'is_active' => $active]);
}
}
$page_title = 'Editar utilizador';
include __DIR__ . '/../../includes/header.php';
?>
<div class="container" style="max-width:640px;">
<h1 class="h3 mb-4">Editar utilizador</h1>
<?php if ($saved): ?><div class="alert alert-success">Utilizador atualizado.</div><?php endif; ?>
<?php if ($error): ?><div class="alert alert-danger"><?= htmlspecialchars($error) ?></div><?php endif; ?>
<?php if ($is_self): ?>
<div class="alert alert-info small">É a sua própria conta: o perfil e o estado não podem ser alterados aqui, para não perder o acesso.</div>
<?php endif; ?>
<form method="POST" class="card shadow-sm"><div class="card-body">
<?= csrf_field() ?>
<input type="hidden" name="id" value="<?= (int) $target['id'] ?>">
<div class="mb-3"><label class="form-label" for="eu-name">Nome</label>
<input class="form-control" id="eu-name" name="name" required maxlength="100" value="<?= htmlspecialchars($target['name']) ?>"></div>
<div class="mb-3"><label class="form-label" for="eu-email">Email</label>
<input type="email" class="form-control" id="eu-email" name="email" required maxlength="190" value="<?= htmlspecialchars($target['email']) ?>"></div>
<div class="mb-3"><label class="form-label" for="eu-phone">Telefone</label>
<input class="form-control" id="eu-phone" name="phone" maxlength="20" value="<?= htmlspecialchars((string) ($target['phone'] ?? '')) ?>"></div>
<div class="mb-3"><label class="form-label" for="eu-role">Perfil</label>
<select class="form-select" id="eu-role" name="role"<?= $is_self ? ' disabled' : '' ?>>
<?php foreach ($roles as $r): ?>
<option value="<?= $r ?>"<?= $target['role'] === $r ? ' selected' : '' ?>><?= htmlspecialchars(role_label($r)) ?></option>
<?php endforeach; ?>
</select></div>
<div class="form-check mb-3"><input class="form-check-input" type="checkbox" name="is_active" id="eu-active" value="1"
<?= !empty($target['is_active']) ? 'checked' : '' ?><?= $is_self ? ' disabled' : '' ?>>
<label class="form-check-label" for="eu-active">Conta ativa</label></div>
<button class="btn btn-primary">Guardar</button>
<a class="btn btn-link" href="<?= base_url('views/user/index.php') ?>">Voltar</a>
</div></form>
</div>
<?php include __DIR__ . '/../../includes/footer.php'; ?>