117 lines
3.8 KiB
JavaScript
117 lines
3.8 KiB
JavaScript
require('dotenv').config();
|
|
const express = require('express');
|
|
const path = require('path');
|
|
const multer = require('multer');
|
|
const { v4: uuidv4 } = require('uuid');
|
|
const fs = require('fs');
|
|
const pool = require('./db');
|
|
const transporter = require('./services/mailer');
|
|
const { provisionSuperAdmin } = require('./services/provisioning');
|
|
const { createCorsMiddleware } = require('./config/cors');
|
|
const { allowedOrigins, getBaseUrl, getStartupBaseUrl, isProduction, jwtSecret: JWT_SECRET, port: PORT } = require('./config/runtime');
|
|
const { authenticateToken } = require('./middleware/auth');
|
|
const { createAuthRouter } = require('./routes/authRoutes');
|
|
const { createUsersRouter } = require('./routes/usersRoutes');
|
|
const { createTeamsRouter } = require('./routes/teamsRoutes');
|
|
const { createTenantsRouter } = require('./routes/tenantsRoutes');
|
|
const { createActivityRouter } = require('./routes/activityRoutes');
|
|
const { createOriginsRouter } = require('./routes/originsRoutes');
|
|
const { createFunnelsRouter } = require('./routes/funnelsRoutes');
|
|
const { createSearchRouter } = require('./routes/searchRoutes');
|
|
const { createAttendancesRouter } = require('./routes/attendancesRoutes');
|
|
const { createApiKeysRouter } = require('./routes/apiKeysRoutes');
|
|
const { createIntegrationsRouter } = require('./routes/integrationsRoutes');
|
|
|
|
const app = express();
|
|
|
|
app.use(createCorsMiddleware({ allowedOrigins, isProduction }));
|
|
app.use(express.json());
|
|
|
|
// Logger de Requisições
|
|
app.use((req, res, next) => {
|
|
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
|
|
next();
|
|
});
|
|
|
|
// --- Configuração Multer (Upload Seguro) ---
|
|
const uploadDir = path.join(__dirname, 'uploads');
|
|
if (!fs.existsSync(uploadDir)) {
|
|
fs.mkdirSync(uploadDir, { recursive: true });
|
|
}
|
|
|
|
const storage = multer.diskStorage({
|
|
destination: (req, file, cb) => {
|
|
cb(null, uploadDir);
|
|
},
|
|
filename: (req, file, cb) => {
|
|
const ext = path.extname(file.originalname).toLowerCase();
|
|
cb(null, `${uuidv4()}${ext}`);
|
|
}
|
|
});
|
|
|
|
const upload = multer({
|
|
storage: storage,
|
|
limits: { fileSize: 2 * 1024 * 1024 }, // 2MB
|
|
fileFilter: (req, file, cb) => {
|
|
const allowedTypes = ['image/jpeg', 'image/png', 'image/webp'];
|
|
if (allowedTypes.includes(file.mimetype)) {
|
|
cb(null, true);
|
|
} else {
|
|
cb(new Error('Tipo de arquivo inválido. Apenas JPG, PNG e WEBP são permitidos.'));
|
|
}
|
|
}
|
|
});
|
|
|
|
app.use('/uploads', express.static(uploadDir, {
|
|
setHeaders: (res) => {
|
|
res.set('X-Content-Type-Options', 'nosniff');
|
|
}
|
|
}));
|
|
|
|
// --- API Router ---
|
|
const apiRouter = express.Router();
|
|
|
|
apiRouter.use(authenticateToken);
|
|
|
|
// --- Auth Routes ---
|
|
|
|
apiRouter.use(createAuthRouter({ pool, transporter, getBaseUrl, jwtSecret: JWT_SECRET }));
|
|
|
|
apiRouter.use(createUsersRouter({ pool, upload, transporter, getBaseUrl }));
|
|
|
|
apiRouter.use(createTeamsRouter({ pool }));
|
|
|
|
apiRouter.use(createTenantsRouter({ pool, transporter, getBaseUrl }));
|
|
|
|
apiRouter.use(createActivityRouter({ pool }));
|
|
|
|
apiRouter.use(createOriginsRouter({ pool }));
|
|
|
|
apiRouter.use(createFunnelsRouter({ pool }));
|
|
|
|
apiRouter.use(createSearchRouter({ pool }));
|
|
|
|
apiRouter.use(createAttendancesRouter({ pool }));
|
|
|
|
apiRouter.use(createApiKeysRouter({ pool }));
|
|
|
|
apiRouter.use(createIntegrationsRouter({ pool }));
|
|
|
|
// Mount the API Router
|
|
app.use('/api', apiRouter);
|
|
|
|
// Serve static files
|
|
if (process.env.NODE_ENV === 'production') {
|
|
app.use(express.static(path.join(__dirname, 'dist')));
|
|
app.get('*', (req, res) => {
|
|
// Avoid hijacking API requests
|
|
if (req.url.startsWith('/api')) return res.status(404).json({ error: 'API route not found' });
|
|
res.sendFile(path.join(__dirname, 'dist/index.html'));
|
|
});
|
|
}
|
|
|
|
app.listen(PORT, async () => {
|
|
await provisionSuperAdmin({ pool, transporter, getStartupBaseUrl });
|
|
console.log(`🚀 Servidor Backend rodando em http://localhost:${PORT}`);
|
|
});
|