89 lines
2.7 KiB
JavaScript
89 lines
2.7 KiB
JavaScript
const path = require('path')
|
|
const fs = require('fs')
|
|
const express = require('express')
|
|
const cors = require('cors')
|
|
const session = require('express-session')
|
|
const FileStoreFactory = require('session-file-store')
|
|
|
|
const { ensureData } = require('./src/db')
|
|
const authRoutes = require('./src/routes/auth')
|
|
const gamesRoutes = require('./src/routes/games')
|
|
const tierListsRoutes = require('./src/routes/tierlists')
|
|
const adminRoutes = require('./src/routes/admin')
|
|
|
|
const app = express()
|
|
const PORT = process.env.PORT ? Number(process.env.PORT) : 5179
|
|
const SESSION_SECRET = process.env.SESSION_SECRET || 'dev-secret-change-me'
|
|
const SESSION_COOKIE_SECURE = process.env.SESSION_COOKIE_SECURE === 'true'
|
|
const SESSION_COOKIE_SAME_SITE = process.env.SESSION_COOKIE_SAME_SITE || 'lax'
|
|
const TRUST_PROXY = process.env.TRUST_PROXY ? Number(process.env.TRUST_PROXY) : 1
|
|
const allowedOrigins = (process.env.CORS_ORIGINS || '')
|
|
.split(',')
|
|
.map((origin) => origin.trim())
|
|
.filter(Boolean)
|
|
|
|
const FileStore = FileStoreFactory(session)
|
|
|
|
;['uploads/avatars', 'uploads/games', 'uploads/custom', '.sessions'].forEach((relativePath) => {
|
|
fs.mkdirSync(path.join(__dirname, relativePath), { recursive: true })
|
|
})
|
|
|
|
app.set('trust proxy', TRUST_PROXY)
|
|
app.use(
|
|
cors({
|
|
origin: (origin, cb) => {
|
|
if (!origin) return cb(null, true)
|
|
if (allowedOrigins.includes(origin)) return cb(null, true)
|
|
if (/^http:\/\/localhost:517\d$/.test(origin)) return cb(null, true) // 5170~5179
|
|
if (/^https?:\/\/127\.0\.0\.1:517\d$/.test(origin)) return cb(null, true)
|
|
if (origin === 'http://localhost:5173') return cb(null, true)
|
|
cb(new Error('not_allowed_by_cors'))
|
|
},
|
|
credentials: true,
|
|
})
|
|
)
|
|
app.use(express.json({ limit: '10mb' }))
|
|
app.use(express.urlencoded({ extended: true }))
|
|
|
|
app.use(
|
|
session({
|
|
store: new FileStore({
|
|
path: path.join(__dirname, '.sessions'),
|
|
ttl: 60 * 60 * 24 * 30,
|
|
retries: 0,
|
|
}),
|
|
secret: SESSION_SECRET,
|
|
proxy: TRUST_PROXY > 0,
|
|
resave: false,
|
|
saveUninitialized: false,
|
|
cookie: {
|
|
httpOnly: true,
|
|
sameSite: SESSION_COOKIE_SAME_SITE,
|
|
secure: SESSION_COOKIE_SECURE,
|
|
maxAge: 1000 * 60 * 60 * 24 * 30,
|
|
},
|
|
})
|
|
)
|
|
|
|
app.use('/uploads', express.static(path.join(__dirname, 'uploads')))
|
|
|
|
app.get('/health', (req, res) => res.json({ ok: true }))
|
|
|
|
app.use(async (req, res, next) => {
|
|
try {
|
|
await ensureData()
|
|
next()
|
|
} catch (e) {
|
|
res.status(500).json({ error: 'db_init_failed' })
|
|
}
|
|
})
|
|
|
|
app.use('/api/auth', authRoutes)
|
|
app.use('/api/games', gamesRoutes)
|
|
app.use('/api/tierlists', tierListsRoutes)
|
|
app.use('/api/admin', adminRoutes)
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`[backend] listening on http://localhost:${PORT}`)
|
|
})
|