Files
server/app/Controllers/ClientController.php

207 lines
7.3 KiB
PHP

<?php
namespace App\Controllers;
use App\Models\Client;
use App\Utils\View;
class ClientController
{
public function index()
{
$clientModel = new Client();
$clients = $clientModel->findAll();
View::render('layouts.admin', [
'title' => 'Gerenciar Clientes',
'content' => __DIR__ . '/../../resources/views/admin/clients/index.php',
'clients' => $clients
]);
}
public function create()
{
View::render('layouts.admin', [
'title' => 'Novo Cliente',
'content' => __DIR__ . '/../../resources/views/admin/clients/form.php'
]);
}
public function store()
{
$data = [
'name' => $_POST['name'],
'asn' => $_POST['asn'],
'email' => $_POST['email'],
'financial_email' => $_POST['financial_email'],
'telegram_id' => $_POST['telegram_id'],
'status' => 'active'
];
// Basic validation could be added here
$conn = \App\Config\Database::getInstance()->getConnection();
$sql = "INSERT INTO clients (name, asn, email, financial_email, telegram_id, status) VALUES (:name, :asn, :email, :financial_email, :telegram_id, :status)";
$stmt = $conn->prepare($sql);
$stmt->execute($data);
$clientId = $conn->lastInsertId();
// Create User for Client
$password = $_POST['password'];
$validation = \App\Utils\PasswordValidator::validate($password);
if ($validation !== true) {
// Rollback or handle error. For simplicity, we redirect with error.
// Ideally we should use transactions.
// Deleting the client created above to keep consistency
$conn->exec("DELETE FROM clients WHERE id = $clientId");
$_SESSION['flash_error'] = "A senha deve ter no mínimo 8 caracteres, contendo pelo menos uma letra maiúscula e um caractere especial.";
$_SESSION['old_input'] = $_POST;
View::redirect('/admin/clients/create');
return;
}
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
$sqlUser = "INSERT INTO users (name, email, password, role, client_id) VALUES (:name, :email, :password, 'client', :client_id)";
$stmtUser = $conn->prepare($sqlUser);
$stmtUser->execute([
'name' => $_POST['name'],
'email' => $_POST['email'],
'password' => $passwordHash,
'client_id' => $clientId
]);
// Pangolin Integration
try {
$pangolinService = new \App\Services\PangolinService();
if ($pangolinService->isEnabled()) {
$pangolinService->syncClient($clientId, 'add');
}
} catch (\Exception $e) {
// Log error silently, don't break the flow
error_log("Pangolin Sync Error (Create): " . $e->getMessage());
}
View::redirect('/admin/clients');
}
public function edit($id)
{
$clientModel = new Client();
$client = $clientModel->find($id);
if (!$client) {
View::redirect('/admin/clients');
}
View::render('layouts.admin', [
'title' => 'Editar Cliente',
'content' => __DIR__ . '/../../resources/views/admin/clients/form.php',
'client' => $client
]);
}
public function update($id)
{
$data = [
'id' => $id,
'name' => $_POST['name'],
'asn' => $_POST['asn'],
'email' => $_POST['email'],
'financial_email' => $_POST['financial_email'],
'telegram_id' => $_POST['telegram_id'] ?? null,
'status' => $_POST['status']
];
$conn = \App\Config\Database::getInstance()->getConnection();
$sql = "UPDATE clients SET name=:name, asn=:asn, email=:email, financial_email=:financial_email, telegram_id=:telegram_id, status=:status WHERE id=:id";
$stmt = $conn->prepare($sql);
$stmt->execute($data);
// Update User Email and Password (if provided)
$sqlUser = "UPDATE users SET email = :email";
$paramsUser = ['email' => $_POST['email'], 'client_id' => $id];
if (!empty($_POST['password'])) {
$password = $_POST['password'];
$validation = \App\Utils\PasswordValidator::validate($password);
if ($validation !== true) {
$_SESSION['flash_error'] = "A senha deve ter no mínimo 8 caracteres, contendo pelo menos uma letra maiúscula e um caractere especial.";
View::redirect('/admin/clients/edit/' . $id);
return;
}
$sqlUser .= ", password = :password";
$paramsUser['password'] = password_hash($password, PASSWORD_DEFAULT);
}
$sqlUser .= " WHERE client_id = :client_id";
$stmtUser = $conn->prepare($sqlUser);
$stmtUser->execute($paramsUser);
// Pangolin Integration - Buscar IPs dos servidores ATIVOS ANTES de desativá-los
$serverIpsToRemove = [];
if ($_POST['status'] === 'inactive') {
$stmtIps = $conn->prepare("SELECT ip_v4, ip_v6 FROM servers WHERE client_id = :client_id AND status = 'active'");
$stmtIps->execute(['client_id' => $id]);
$servers = $stmtIps->fetchAll(\PDO::FETCH_ASSOC);
foreach ($servers as $server) {
if (!empty($server['ip_v4'])) {
$serverIpsToRemove[] = $server['ip_v4'];
}
if (!empty($server['ip_v6'])) {
$serverIpsToRemove[] = $server['ip_v6'];
}
}
}
// Cascade Deactivate Servers quando cliente é desativado
if ($_POST['status'] === 'inactive') {
$sqlServers = "UPDATE servers SET status = 'inactive' WHERE client_id = :client_id";
$stmtServers = $conn->prepare($sqlServers);
$stmtServers->execute(['client_id' => $id]);
}
// Pangolin Integration - Sincroniza com base no status
try {
$pangolinService = new \App\Services\PangolinService();
if ($pangolinService->isEnabled()) {
if ($_POST['status'] === 'active') {
$pangolinService->syncClient($id, 'add');
} else {
// Remove os IPs que foram coletados antes de desativar os servidores
if (!empty($serverIpsToRemove)) {
$pangolinService->removeServerIps($serverIpsToRemove);
}
}
}
} catch (\Exception $e) {
error_log("Pangolin Sync Error (Update): " . $e->getMessage());
}
View::redirect('/admin/clients');
}
public function delete($id)
{
$clientModel = new Client();
// Pangolin Integration (Remove before delete to get ASN)
try {
$client = $clientModel->find($id);
if ($client && $client['status'] === 'active') {
$pangolinService = new \App\Services\PangolinService();
$pangolinService->syncClient($id, 'remove');
}
} catch (\Exception $e) {
error_log("Pangolin Sync Error (Delete): " . $e->getMessage());
}
$clientModel->delete($id);
View::redirect('/admin/clients');
}
}