fix: CORS-Origins, Sync-Body-Limit und geteilte Logbuch-Rolle
Erlaubt mehrere/normalisierte CORS-Origins mit Dev-Fallbacks für Session-Cookies, stellt express.json wieder auf 50mb für große Sync-Payloads und setzt die Zugriffsrolle beim Wechsel in geteilte Logbücher ohne Cache korrekt. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import type { CorsOptions } from 'cors'
|
||||
|
||||
function normalizeOrigin(origin: string): string {
|
||||
return origin.trim().replace(/\/$/, '')
|
||||
}
|
||||
|
||||
/** Origins allowed for credentialed CORS (must match the browser frontend URL exactly). */
|
||||
export function getAllowedCorsOrigins(): Set<string> {
|
||||
const raw =
|
||||
process.env.CORS_ORIGINS?.trim() ||
|
||||
process.env.ORIGIN?.trim() ||
|
||||
'http://localhost:5173'
|
||||
|
||||
const origins = raw
|
||||
.split(',')
|
||||
.map(normalizeOrigin)
|
||||
.filter(Boolean)
|
||||
|
||||
const allowed = new Set(origins)
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
for (const dev of [
|
||||
'http://localhost:5173',
|
||||
'http://127.0.0.1:5173',
|
||||
'http://localhost:4173'
|
||||
]) {
|
||||
allowed.add(dev)
|
||||
}
|
||||
}
|
||||
|
||||
return allowed
|
||||
}
|
||||
|
||||
export function buildCorsOptions(): CorsOptions {
|
||||
const allowed = getAllowedCorsOrigins()
|
||||
|
||||
return {
|
||||
origin(origin, callback) {
|
||||
// Non-browser clients, same-origin via reverse proxy (no Origin header)
|
||||
if (!origin) {
|
||||
callback(null, true)
|
||||
return
|
||||
}
|
||||
|
||||
const normalized = normalizeOrigin(origin)
|
||||
if (allowed.has(normalized)) {
|
||||
callback(null, normalized)
|
||||
return
|
||||
}
|
||||
|
||||
console.warn(
|
||||
`[cors] Rejected origin "${origin}". Allowed: ${[...allowed].join(', ')}`
|
||||
)
|
||||
callback(new Error('Not allowed by CORS'))
|
||||
},
|
||||
credentials: true
|
||||
}
|
||||
}
|
||||
+4
-9
@@ -15,6 +15,7 @@ import pushRouter from './routes/push.js'
|
||||
import weatherRouter from './routes/weather.js'
|
||||
import feedbackRouter from './routes/feedback.js'
|
||||
import { prisma } from './db.js'
|
||||
import { buildCorsOptions } from './cors.js'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
@@ -24,22 +25,16 @@ dotenv.config({ path: resolve(__dirname, '../.env') })
|
||||
const app = express()
|
||||
const PORT = process.env.PORT || 5000
|
||||
|
||||
const allowedOrigin = process.env.ORIGIN || 'http://localhost:5173'
|
||||
|
||||
app.use(
|
||||
helmet({
|
||||
contentSecurityPolicy: false,
|
||||
crossOriginEmbedderPolicy: false
|
||||
})
|
||||
)
|
||||
app.use(
|
||||
cors({
|
||||
origin: allowedOrigin,
|
||||
credentials: true
|
||||
})
|
||||
)
|
||||
app.use(cors(buildCorsOptions()))
|
||||
app.use(cookieParser())
|
||||
app.use(express.json({ limit: '10mb' }))
|
||||
// Encrypted sync payloads (photos, GPS tracks) can be large — align with nginx client_max_body_size
|
||||
app.use(express.json({ limit: '50mb' }))
|
||||
|
||||
const authLimiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000,
|
||||
|
||||
Reference in New Issue
Block a user