require('dotenv').config(); const express = require('express'); const cors = require('cors'); const helmet = require('helmet'); const rateLimit = require('express-rate-limit'); const path = require('path'); const apiRouter = require('./routes/api'); const stripeRouter = require('./routes/stripe'); const webhookRouter = require('./routes/webhook'); const adminRouter = require('./routes/admin'); const app = express(); const PORT = process.env.PORT || 3000; // ============ SECURITY ============ // Helmet - добавляет security headers app.use(helmet({ contentSecurityPolicy: false // отключаем для admin panel })); // CORS - разрешаем только наши домены const allowedOrigins = [ 'https://wellnuo.smartlaunchhub.com', 'https://wellnuo.com', 'http://localhost:3000', 'http://localhost:8081', // Expo dev 'exp://192.168.1.*' // Expo local ]; app.use(cors({ origin: function(origin, callback) { // Разрешаем запросы без origin (mobile apps, Postman) if (!origin) return callback(null, true); // Проверяем разрешённые домены if (allowedOrigins.some(allowed => { if (allowed.includes('*')) { const regex = new RegExp(allowed.replace('*', '.*')); return regex.test(origin); } return allowed === origin; })) { return callback(null, true); } callback(new Error('Not allowed by CORS')); }, credentials: true })); // Rate Limiting - защита от DDoS const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 минут max: 100, // максимум 100 запросов за 15 минут message: { error: 'Too many requests, please try again later' }, standardHeaders: true, legacyHeaders: false }); // Более строгий лимит для auth endpoints const authLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 5, // только 5 попыток логина за 15 минут message: { error: 'Too many login attempts, please try again later' } }); // Применяем rate limiting app.use(limiter); app.use('/function/well-api/api', authLimiter); // Legacy API с auth // Stripe webhooks need raw body for signature verification // Must be before express.json() app.use('/api/webhook/stripe', express.raw({ type: 'application/json' })); // JSON body parser for other routes app.use(express.json()); app.use(express.urlencoded({ extended: true })); // ============ ROUTES ============ // Legacy API route - matches old API structure // POST /function/well-api/api with function parameter app.use('/function/well-api/api', apiRouter); // New REST API routes app.use('/api/stripe', stripeRouter); app.use('/api/webhook', webhookRouter); app.use('/api/admin', adminRouter); // Admin UI app.get('/admin', (req, res) => { res.sendFile(path.join(__dirname, 'admin', 'index.html')); }); // Health check app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString(), stripe: process.env.STRIPE_SECRET_KEY ? 'configured' : 'missing' }); }); // API info app.get('/api', (req, res) => { res.json({ name: 'WellNuo API', version: '1.0.0', endpoints: { legacy: '/function/well-api/api', stripe: '/api/stripe', webhook: '/api/webhook/stripe' } }); }); app.listen(PORT, () => { console.log(`WellNuo API running on port ${PORT}`); console.log(`Stripe: ${process.env.STRIPE_SECRET_KEY ? '✓ configured' : '✗ missing'}`); });