API CARDIX

This commit is contained in:
2026-02-20 18:57:35 -03:00
parent 83622dc075
commit 2de834b698

238
api.php Normal file
View File

@@ -0,0 +1,238 @@
<?php
/**
* Cardix Admin - MySQL Proxy API
* =========================================================
* INSTRUÇÕES DE DEPLOY:
* 1. Copie este arquivo para o seu servidor em 31.97.64.165
* 2. Coloque em um diretório acessível pelo Apache/Nginx
* Ex: /var/www/html/cardix-api/api.php
* 3. Acesse pelo browser: http://31.97.64.165/cardix-api/api.php?action=tables
* 4. Atualize a variável API_URL em src/lib/config.ts com a URL correta
* =========================================================
*/
// ---- Configurações ----
define('API_SECRET', 'cardix-admin-2024');
define('DB_HOST', 'localhost'); // Use 'localhost' se MySQL está no mesmo servidor
define('DB_NAME', 'cardix');
define('DB_USER', 'wander');
define('DB_PASS', 'DIpIYIp25O');
define('DB_PORT', 3306);
// ---- CORS Headers ----
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, X-API-Key');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
// ---- Autenticação por API Key ----
$apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
if ($apiKey !== API_SECRET) {
http_response_code(401);
echo json_encode(['error' => 'Não autorizado. Forneça o header X-API-Key.']);
exit;
}
// ---- Conexão PDO ----
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";port=" . DB_PORT . ";charset=utf8mb4",
DB_USER,
DB_PASS,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"
]
);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['error' => 'Falha na conexão com o banco de dados: ' . $e->getMessage()]);
exit;
}
// ---- Helpers ----
function sanitizeIdentifier(string $name): string {
return preg_replace('/[^a-zA-Z0-9_]/', '', $name);
}
function getPrimaryKey(PDO $pdo, string $table): string {
$stmt = $pdo->query("SHOW KEYS FROM `{$table}` WHERE Key_name = 'PRIMARY'");
$row = $stmt->fetch();
return $row ? $row['Column_name'] : 'id';
}
function jsonResponse(mixed $data, int $status = 200): void {
http_response_code($status);
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
// ---- Roteamento ----
$method = $_SERVER['REQUEST_METHOD'];
$action = $_GET['action'] ?? null;
$table = isset($_GET['table']) ? sanitizeIdentifier($_GET['table']) : null;
$id = $_GET['id'] ?? null;
// ACTION: Listar todas as tabelas
if ($action === 'tables') {
$stmt = $pdo->query("SHOW TABLES");
jsonResponse($stmt->fetchAll(PDO::FETCH_COLUMN));
}
// ACTION: Schema de uma tabela (colunas + FKs)
if ($action === 'schema' && $table) {
$stmt = $pdo->query("DESCRIBE `{$table}`");
$columns = $stmt->fetchAll();
$fkStmt = $pdo->prepare("
SELECT COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = ?
AND REFERENCED_TABLE_NAME IS NOT NULL
");
$fkStmt->execute([$table]);
$fks = $fkStmt->fetchAll();
// Para cada FK, detecta a melhor coluna de exibição
$fkDisplay = [];
foreach ($fks as $fk) {
$refTable = $fk['REFERENCED_TABLE_NAME'];
$descStmt = $pdo->query("DESCRIBE `{$refTable}`");
$refCols = $descStmt->fetchAll();
$displayCol = null;
foreach ($refCols as $col) {
if ($col['Field'] !== $fk['REFERENCED_COLUMN_NAME'] &&
(strpos($col['Type'], 'varchar') !== false || strpos($col['Type'], 'text') !== false)) {
$displayCol = $col['Field'];
break;
}
}
$fkDisplay[$fk['COLUMN_NAME']] = [
'table' => $refTable,
'keyCol' => $fk['REFERENCED_COLUMN_NAME'],
'displayCol' => $displayCol ?? $fk['REFERENCED_COLUMN_NAME'],
];
}
jsonResponse(['columns' => $columns, 'foreignKeys' => $fks, 'fkDisplay' => $fkDisplay]);
}
// ACTION: Opções para campo FK (select dropdown)
if ($action === 'fk_options' && $table) {
$pkCol = sanitizeIdentifier($_GET['pk'] ?? 'id');
$labelCol = sanitizeIdentifier($_GET['label'] ?? $pkCol);
$stmt = $pdo->query(
"SELECT `{$pkCol}` AS `value`, `{$labelCol}` AS `label` FROM `{$table}` ORDER BY `{$labelCol}` LIMIT 500"
);
jsonResponse($stmt->fetchAll());
}
// ---- CRUD ----
if (!$table) {
jsonResponse(['error' => 'Parâmetro "table" obrigatório'], 400);
}
$pk = getPrimaryKey($pdo, $table);
switch ($method) {
// READ (listagem paginada ou registro único)
case 'GET':
if ($id !== null) {
$stmt = $pdo->prepare("SELECT * FROM `{$table}` WHERE `{$pk}` = ?");
$stmt->execute([$id]);
$row = $stmt->fetch();
jsonResponse($row !== false ? $row : null);
}
$page = max(1, intval($_GET['page'] ?? 1));
$limit = min(100, max(5, intval($_GET['limit'] ?? 10)));
$offset = ($page - 1) * $limit;
$search = trim($_GET['search'] ?? '');
// Busca simples em todas as colunas varchar
$whereClause = '';
$searchParams = [];
if ($search !== '') {
$descStmt = $pdo->query("DESCRIBE `{$table}`");
$cols = $descStmt->fetchAll(PDO::FETCH_COLUMN, 0);
$conditions = [];
foreach ($cols as $col) {
$conditions[] = "`{$col}` LIKE ?";
$searchParams[] = "%{$search}%";
}
$whereClause = 'WHERE ' . implode(' OR ', $conditions);
}
$countStmt = $pdo->query("SELECT COUNT(*) FROM `{$table}` {$whereClause}");
if ($searchParams) {
$countStmt = $pdo->prepare("SELECT COUNT(*) FROM `{$table}` {$whereClause}");
$countStmt->execute($searchParams);
}
$total = (int) $countStmt->fetchColumn();
$dataStmt = $pdo->prepare("SELECT * FROM `{$table}` {$whereClause} LIMIT ? OFFSET ?");
$params = array_merge($searchParams, [$limit, $offset]);
$dataStmt->execute($params);
$data = $dataStmt->fetchAll();
jsonResponse([
'data' => $data,
'total' => $total,
'page' => $page,
'limit' => $limit,
'totalPages' => (int) ceil($total / $limit),
]);
break;
// CREATE
case 'POST':
$body = json_decode(file_get_contents('php://input'), true);
if (!$body || !is_array($body)) {
jsonResponse(['error' => 'Body JSON inválido'], 400);
}
$cols = array_keys($body);
$placeholders = implode(', ', array_fill(0, count($cols), '?'));
$colNames = '`' . implode('`, `', $cols) . '`';
$stmt = $pdo->prepare("INSERT INTO `{$table}` ({$colNames}) VALUES ({$placeholders})");
$stmt->execute(array_values($body));
jsonResponse(['id' => $pdo->lastInsertId(), 'message' => 'Registro criado com sucesso!']);
break;
// UPDATE
case 'PUT':
if ($id === null) jsonResponse(['error' => 'ID obrigatório para atualização'], 400);
$body = json_decode(file_get_contents('php://input'), true);
if (!$body || !is_array($body)) {
jsonResponse(['error' => 'Body JSON inválido'], 400);
}
$sets = implode(', ', array_map(fn($col) => "`{$col}` = ?", array_keys($body)));
$stmt = $pdo->prepare("UPDATE `{$table}` SET {$sets} WHERE `{$pk}` = ?");
$stmt->execute([...array_values($body), $id]);
jsonResponse(['message' => 'Registro atualizado com sucesso!']);
break;
// DELETE
case 'DELETE':
if ($id === null) jsonResponse(['error' => 'ID obrigatório para exclusão'], 400);
$stmt = $pdo->prepare("DELETE FROM `{$table}` WHERE `{$pk}` = ?");
$stmt->execute([$id]);
jsonResponse(['message' => 'Registro excluído com sucesso!']);
break;
default:
jsonResponse(['error' => 'Método não permitido'], 405);
}