Buchungskalender: öffentliche API gegen manipulierte IDs und Lookups absichern
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
035967f8eb
commit
0c5ca76a4d
3 files changed
+73
-7
No files matched your search
@@ -7,7 +7,7 @@ import { belegteBereiche } from '../services/unterkunft/belegung.js'
|
||||
import { istTag } from '../services/unterkunft/datum.js'
|
||||
import { UkFehler } from '../services/unterkunft/fehler.js'
|
||||
import { unterkunftPerSiteKey } from '../services/unterkunft/kontext.js'
|
||||
import { ladeUnterkunft, listeUnterkuenfte } from '../services/unterkunft/speicher.js'
|
||||
import { ID_RE, ladeUnterkunft, listeUnterkuenfte } from '../services/unterkunft/speicher.js'
|
||||
import { formToken, ipHashVon, pruefeFormToken } from '../services/unterkunft/token.js'
|
||||
import { darfAnfrage, darfAnfrageSite, darfBuchungsversuch, zaehle } from '../services/termine/limits.js'
|
||||
import { heute } from '../services/termine/zeit.js'
|
||||
@@ -257,17 +257,18 @@ router.get(
|
||||
const ctx = await unterkunftPerSiteKey(req.params.siteKey, { now })
|
||||
if (!ctx) return aktivFalse()
|
||||
if (!darfAnfrageSite(req.params.siteKey, now)) throw zuViele(60)
|
||||
if (typeof req.query.unterkunft === 'string' && !ID_RE.test(req.query.unterkunft)) throw ungueltig({ unterkunft: 'Ungültige Unterkunft.' })
|
||||
const { unterkunft, von, bis } = req.query
|
||||
if (typeof unterkunft !== 'string' || unterkunft === '' || !istTag(von) || !istTag(bis) || bis <= von) {
|
||||
if (typeof unterkunft !== 'string' || unterkunft === '' || !istTag(von) || !istTag(bis) || bis < von) {
|
||||
throw ungueltig({ zeitraum: 'Ungültiger Zeitraum.' })
|
||||
}
|
||||
const tag = heute(now)
|
||||
const bisMax = monateDazu(tag, config.unterkunft.horizontMonate)
|
||||
if (bis > bisMax) throw ungueltig({ zeitraum: 'Der Zeitraum liegt zu weit in der Zukunft.' })
|
||||
const bisBis = bis > bisMax ? bisMax : bis // Fenster des Widgets (UTC-Datum des Browsers) darf nie an einem Tag Abweichung scheitern
|
||||
const u = await ladeUnterkunft(unterkunft)
|
||||
if (!u || u.featureId !== ctx.featureId || u.aktiv !== true) throw nichtGefunden()
|
||||
const ab = von < tag ? tag : von
|
||||
const belegt = ab < bis ? verschmelze(await belegteBereiche(u.$id, ab, bis, { now })) : []
|
||||
const belegt = ab < bisBis ? verschmelze(await belegteBereiche(u.$id, ab, bisBis, { now })) : []
|
||||
return { body: { belegt, heute: tag, bisMax } }
|
||||
}),
|
||||
)
|
||||
@@ -287,6 +288,7 @@ router.post(
|
||||
route(
|
||||
async (req, now, cors) => {
|
||||
const { siteKey } = req.params
|
||||
if (!darfAnfrage(req.ip, now)) throw zuViele(60)
|
||||
const ctx = await unterkunftPerSiteKey(siteKey, { now })
|
||||
if (!ctx) return { body: { aktiv: false } }
|
||||
pruefeHerkunft(req, cors, ctx.project)
|
||||
@@ -299,6 +301,7 @@ router.post(
|
||||
if (pruefung === 'zu_schnell') return { status: 201, body: { nummer: scheinNummer() } }
|
||||
if (pruefung !== 'ok') throw fehlerMit(400, 'neu_laden')
|
||||
if (!zaehle(`uk-anfrage:${siteKey}`, config.unterkunft.anfragenJeSiteStunde, STUNDE_MS, now)) throw zuViele(3600)
|
||||
if (!ID_RE.test(text(b.unterkunft))) throw ungueltig({ unterkunft: 'Ungültige Unterkunft.' })
|
||||
const personen = typeof b.personen === 'string' && /^\d{1,3}$/.test(b.personen) ? Number(b.personen) : b.personen
|
||||
const anfrage = await legeAnfrageAn(
|
||||
ctx,
|
||||
|
||||
@@ -41,8 +41,11 @@ function schreiben(name, felder) {
|
||||
|
||||
const nichtGefunden = (err) => err?.status === 404 && err.type !== 'collection_not_found' && err.type !== 'database_not_found'
|
||||
|
||||
/** Dokument-IDs landen roh im URL-Pfad: nur harmlose Zeichen durchlassen. */
|
||||
export const ID_RE = /^[A-Za-z0-9_]{1,36}$/
|
||||
|
||||
async function ladeDok(name, id) {
|
||||
if (!id) return null
|
||||
if (typeof id !== 'string' || !ID_RE.test(id)) return null
|
||||
try {
|
||||
return lesen(name, await getDocument(config.collections[name], id))
|
||||
} catch (err) {
|
||||
|
||||
Reference in new issue
Block a user