feat(audit): platform-tools atualizado (12f26fd) e registo de auditoria ligado
- shared/platform-tools: ea3616a → 12f26fd (27 commits). Traz o módulo de audit (f761d99, o pin da frota), «manter sessão iniciada», o registo de segurança da frota (o gancho que o login já tinha passa a funcionar) e a correção do IP do cliente encontrada nesta auditoria (último X-Forwarded-For / X-Real-IP), promovida ao partilhado. client_ip() da app delega nele. - config/functions_audit.php: audit() sobre platform_audit(); tabela audit_log criada no primeiro uso, segredos ocultados, nunca parte a ação. - Registado: login, falha de login, bloqueio por excesso de tentativas, logout, pedidos de recuperação, mudança/definição de palavra-passe, registo e criação de utilizadores, convites, perfil (antes/depois), todas as definições (db_update_setting, com valor anterior), cada passo da lixeira (apagar, restaurar, eliminar de vez) e ações nas mensagens. - Sistema → Auditoria (views/sysadmin/audit.php), só sysadmin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5e300fc341
commit
0e8b53f620
65 files changed
+5852
-455
No files matched your search
@@ -25,8 +25,13 @@
|
||||
// Nada disto se aplica a endereços internos: atrás do NPM o contentor fala
|
||||
// consigo próprio para cron e health checks, e auto-banir-se seria uma avaria
|
||||
// difícil de diagnosticar.
|
||||
//
|
||||
// Com o site emparelhado com o hub, os banimentos e as infracções seguem para lá
|
||||
// e os banimentos dos outros sites chegam cá com source='fleet' — ver
|
||||
// functions_security_events.php.
|
||||
|
||||
require_once __DIR__ . '/functions_client_ip.php';
|
||||
require_once __DIR__ . '/functions_security_events.php';
|
||||
|
||||
/** [infracções em 24h => minutos de banimento]. null = permanente. */
|
||||
const IP_BAN_LADDER = [3 => 60, 5 => 1440, 8 => 10080, 12 => null];
|
||||
@@ -123,6 +128,13 @@ function platform_ip_ban(PDO $pdo, string $ip, string $reason, ?int $minutes = 6
|
||||
expires_at = VALUES(expires_at), created_at = NOW(), created_by = VALUES(created_by)'
|
||||
)->execute([$ip, mb_substr($reason, 0, 190), $source, $expires, $userId]);
|
||||
error_log("[ip-ban] $ip banido ($source): $reason" . ($expires ? " até $expires" : ' permanentemente'));
|
||||
// As cópias da frota não voltam ao hub: ecoavam em ciclo.
|
||||
if ($source !== 'fleet') {
|
||||
platform_security_event($pdo, 'ip_ban', $reason, $ip, [
|
||||
'source' => $source,
|
||||
'expires_ts' => $minutes === null ? null : time() + $minutes * 60,
|
||||
]);
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable $e) {
|
||||
error_log('[ip-ban] não conseguiu banir: ' . $e->getMessage());
|
||||
@@ -134,6 +146,9 @@ function platform_ip_unban(PDO $pdo, string $ip): bool
|
||||
{
|
||||
try {
|
||||
platform_ip_ban_ensure_tables($pdo);
|
||||
// Levanta também na frota — incluindo quando isto era uma cópia vinda de
|
||||
// outro site. Sem isso a sincronização seguinte voltava a pô-la cá.
|
||||
platform_security_event($pdo, 'ip_unban', null, $ip);
|
||||
return $pdo->prepare('DELETE FROM ip_bans WHERE ip = ?')->execute([$ip]);
|
||||
} catch (Throwable $e) {
|
||||
error_log('[ip-ban] não conseguiu levantar: ' . $e->getMessage());
|
||||
@@ -161,6 +176,7 @@ function platform_ip_record_offence(PDO $pdo, string $kind, ?string $detail = nu
|
||||
platform_ip_ban_ensure_tables($pdo);
|
||||
$pdo->prepare('INSERT INTO ip_offences (ip, kind, detail) VALUES (?, ?, ?)')
|
||||
->execute([$ip, mb_substr($kind, 0, 40), $detail === null ? null : mb_substr($detail, 0, 190)]);
|
||||
platform_security_event($pdo, 'offence', $kind . ($detail !== null && $detail !== '' ? ' · ' . $detail : ''), $ip);
|
||||
|
||||
$st = $pdo->prepare('SELECT COUNT(*) FROM ip_offences WHERE ip = ? AND created_at >= NOW() - INTERVAL 1 DAY');
|
||||
$st->execute([$ip]);
|
||||
@@ -194,6 +210,8 @@ function platform_ip_record_offence(PDO $pdo, string $kind, ?string $detail = nu
|
||||
*/
|
||||
function platform_ip_guard(PDO $pdo, ?string $contactEmail = null): void
|
||||
{
|
||||
hub_security_maybe_sync($pdo);
|
||||
|
||||
$ban = platform_ip_banned($pdo);
|
||||
if ($ban === null) {
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user