const express = require('express') const rateLimit = require('express-rate-limit') const config = require('./config') const { ok, fail } = require('./lib/response') const { authMiddleware } = require('./middleware/auth') const app = express() // Rate limiting for auth-sensitive endpoints const userLoginLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 10, standardHeaders: true, legacyHeaders: false, message: { code: 2001, message: 'too_many_attempts' } }) const adminLoginLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 5, standardHeaders: true, legacyHeaders: false, message: { code: 2001, message: 'too_many_attempts' } }) const uploadLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 20, standardHeaders: true, legacyHeaders: false, message: { code: 2001, message: 'too_many_attempts' } }) app.use(express.json()) app.use((req, res, next) => { const origin = config.nodeEnv === 'production' ? (process.env.CORS_ORIGIN || 'https://admin.vsai.net.cn') : '*' res.header('Access-Control-Allow-Origin', origin) res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Device-Id, X-App-Version, X-Platform') res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') if (req.method === 'OPTIONS') return res.sendStatus(204) next() }) app.use('/api/v1/auth/login', userLoginLimiter) app.use('/api/v1/admin/login', adminLoginLimiter) app.use('/api/v1/user/avatar', uploadLimiter) app.use('/api/v1/user/phone', uploadLimiter) app.use(authMiddleware) app.get('/health', (req, res) => res.json(ok({ status: 'ok' }))) app.use('/api/v1', require('./routes/auth')) app.use('/api/v1', require('./routes/user')) app.use('/api/v1', require('./routes/device')) app.use('/api/v1', require('./routes/subscription')) app.use('/api/v1', require('./routes/treatment')) app.use('/api/v1/admin', require('./routes/admin')) app.use('/api/v1', require('./routes/firmware')) app.use((req, res) => res.status(404).json(fail(404, 'not_found'))) app.use((err, req, res, _next) => { console.error('[ERROR]', req.method, req.path, err.code || '', err.sqlMessage || err.message, err.stack) res.status(500).json(fail(3001, 'server_error')) }) module.exports = app