feat: estrutura inicial do gerenciador de subdomínios
- backend Express com endpoints Hostinger DNS API - frontend React+Vite+Tailwind com card de API key - docker-compose (frontend:3014, backend:8019, nginx:8021) - Traefik label para subdominio.clube67.com
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import express from 'express';
|
||||
import cors from 'cors';
|
||||
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname, join } from 'path';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const CONFIG_FILE = join(__dirname, 'config.json');
|
||||
|
||||
const app = express();
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
|
||||
function loadConfig() {
|
||||
if (!existsSync(CONFIG_FILE)) return { hostinger_api_key: '' };
|
||||
try { return JSON.parse(readFileSync(CONFIG_FILE, 'utf8')); } catch { return { hostinger_api_key: '' }; }
|
||||
}
|
||||
|
||||
function saveConfig(data) {
|
||||
writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8');
|
||||
}
|
||||
|
||||
// GET configuração (mascara a key)
|
||||
app.get('/api/config', (req, res) => {
|
||||
const cfg = loadConfig();
|
||||
res.json({ has_api_key: !!cfg.hostinger_api_key });
|
||||
});
|
||||
|
||||
// POST salvar API key da Hostinger
|
||||
app.post('/api/config/hostinger-key', (req, res) => {
|
||||
const { api_key } = req.body;
|
||||
if (!api_key?.trim()) return res.status(400).json({ error: 'api_key obrigatória' });
|
||||
const cfg = loadConfig();
|
||||
cfg.hostinger_api_key = api_key.trim();
|
||||
saveConfig(cfg);
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
// GET listar subdomínios via Hostinger API
|
||||
app.get('/api/subdomains', async (req, res) => {
|
||||
const cfg = loadConfig();
|
||||
if (!cfg.hostinger_api_key) return res.status(400).json({ error: 'API key não configurada' });
|
||||
|
||||
try {
|
||||
const r = await fetch('https://developers.hostinger.com/api/dns/v1/domains', {
|
||||
headers: { Authorization: `Bearer ${cfg.hostinger_api_key}`, 'Content-Type': 'application/json' }
|
||||
});
|
||||
const data = await r.json();
|
||||
res.json(data);
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
// POST criar subdomínio no DNS da Hostinger
|
||||
app.post('/api/subdomains', async (req, res) => {
|
||||
const cfg = loadConfig();
|
||||
if (!cfg.hostinger_api_key) return res.status(400).json({ error: 'API key não configurada' });
|
||||
|
||||
const { domain, subdomain, type = 'A', value } = req.body;
|
||||
if (!domain || !subdomain || !value) return res.status(400).json({ error: 'domain, subdomain e value obrigatórios' });
|
||||
|
||||
try {
|
||||
const r = await fetch(`https://developers.hostinger.com/api/dns/v1/domains/${domain}/records`, {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Bearer ${cfg.hostinger_api_key}`, 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ type, name: subdomain, content: value, ttl: 300 })
|
||||
});
|
||||
const data = await r.json();
|
||||
res.json(data);
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
const PORT = process.env.PORT || 8019;
|
||||
app.listen(PORT, () => console.log(`[subdominio-backend] porta ${PORT}`));
|
||||
Reference in New Issue
Block a user