Buchungskalender: Abgleich – iCal-Export (Escape, aktive Unterkünfte, ab gestern, Rate-Limit)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
95cbd473d0
commit
fbd07b3d8c
3 files changed
+40
-3
No files matched your search
@@ -5,6 +5,9 @@ import { Router } from 'express'
|
||||
import { config } from '../config.js'
|
||||
import { listDocuments, Query } from '../services/appwriteAdmin.js'
|
||||
import { baueIcs } from '../services/unterkunft/ical.js'
|
||||
import { plusTage } from '../services/unterkunft/datum.js'
|
||||
import { heute as berlinHeute } from '../services/termine/zeit.js'
|
||||
import { ipSchluessel, zaehle } from '../services/termine/limits.js'
|
||||
import { ladeFuerProjekt, SITE_KEY_RE } from '../services/unterkunft/kontext.js'
|
||||
import { unterkunftFuerKunde, unterkunftModus } from '../services/unterkunft/schalter.js'
|
||||
import { listeAnfragenNachStatus, listeSperren } from '../services/unterkunft/speicher.js'
|
||||
@@ -16,18 +19,21 @@ import { listeAnfragenNachStatus, listeSperren } from '../services/unterkunft/sp
|
||||
*/
|
||||
|
||||
const DATEI_RE = /^[A-Za-z0-9_-]{20,64}\.ics$/
|
||||
const EXPORT_JE_MINUTE = 60
|
||||
const nicht = (res) => res.status(404).type('text/plain').set('Cache-Control', 'no-store').send('Not found')
|
||||
|
||||
async function exportEreignisse(unterkunft, jetzt) {
|
||||
const gestern = plusTage(berlinHeute(new Date(jetzt)), -1)
|
||||
const out = []
|
||||
for (const s of await listeSperren(unterkunft.$id)) {
|
||||
const quelle = String(s.quelle ?? 'manuell')
|
||||
if (quelle.startsWith('ical') || !s.von || !s.bis) continue // nie zurueckspielen, was importiert wurde
|
||||
if (s.bis <= gestern) continue // nur Ereignisse ab gestern
|
||||
out.push({ uid: `${s.$id}@project.webklar.com`, von: s.von, bis: s.bis })
|
||||
}
|
||||
for (const a of await listeAnfragenNachStatus(unterkunft.$id, ['gebucht', 'bezahlt', 'freigegeben'])) {
|
||||
if (a.status === 'freigegeben' && !(Date.parse(a.fristAt) > jetzt)) continue
|
||||
if (!a.von || !a.bis) continue
|
||||
if (!a.von || !a.bis || a.bis <= gestern) continue
|
||||
out.push({ uid: `${a.$id}@project.webklar.com`, von: a.von, bis: a.bis })
|
||||
}
|
||||
return out.sort((x, y) => (x.von < y.von ? -1 : x.von > y.von ? 1 : x.uid < y.uid ? -1 : 1))
|
||||
@@ -87,9 +93,10 @@ export function unterkunftSeiteRouter() {
|
||||
router.get('/unterkunft/ical/:datei', async (req, res, next) => {
|
||||
try {
|
||||
if (unterkunftModus() === 'off' || !DATEI_RE.test(req.params.datei)) return nicht(res)
|
||||
if (!zaehle(`uk-ical:${ipSchluessel(req.ip)}`, EXPORT_JE_MINUTE, 60_000, new Date())) return res.status(429).type('text/plain').set({ 'Cache-Control': 'no-store', 'Retry-After': '60' }).send('Too many requests')
|
||||
const token = req.params.datei.slice(0, -4)
|
||||
const [u] = await listDocuments(config.collections.ukUnterkuenfte, [Query.equal('icalExportToken', token), Query.limit(1)])
|
||||
if (!u || u.icalExportToken !== token) return nicht(res)
|
||||
if (!u || u.icalExportToken !== token || u.aktiv === false) return nicht(res)
|
||||
const ctx = await ladeFuerProjekt(u.customerId, u.projectId)
|
||||
if (!ctx || ctx.featureId !== u.featureId || ctx.state !== 'active' || !unterkunftFuerKunde(ctx.besitzerEmail)) return nicht(res)
|
||||
const jetzt = new Date()
|
||||
|
||||
Reference in new issue
Block a user