Zugang: was darf dieser Token -- lag seit dem 26.08. nur in der Arbeitskopie

GET /api/zugang nennt die Ordner, in die ein Token schreiben darf (oder die
vorhandenen, wenn er ueberall darf). Das Fotostudio ruft die Route fuer seine
Ordnerauswahl auf.

Gemessen am 03.10.2026: der laufende Container ist am 26.08. um 15:05 aus
dieser Arbeitskopie gebaut worden, in derselben Minute wie die letzte
Aenderung an upload.ts, und /api/zugang antwortet ohne Token mit 401 (ein
erfundener Weg mit 404). Die Route laeuft also -- sie stand nur nicht im Git.
Dieser Commit holt nach, was im Betrieb ist; am Code aendert er nichts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
D4rkst3randClaude Opus 5.5 committed 2026-10-03 09:55:37 +02:00
1 parent 06285a3a53
commit 73c9f310c0
1 file changed
+49 -1
+49 -1
View File
@@ -24,7 +24,7 @@ import type { Context, Next } from 'hono'
import { config } from '../config.js' import { config } from '../config.js'
import { meldeUpload } from '../meldung.js' import { meldeUpload } from '../meldung.js'
import { db, logEvent, now, type Media, type Token } from '../db.js' import { db, logEvent, now, type Media, type Token } from '../db.js'
import { fesselText, tokenAllows, tokenFromHeader } from '../auth.js' import { fesselText, tokenAllows, tokenFromHeader, tokenPrefixes } from '../auth.js'
import { import {
PathError, PathError,
checkPath, checkPath,
@@ -141,6 +141,7 @@ uploadRoutes.use('/media/*', requireToken)
// '/exists/*' trifft sie NICHT, weil dort kein Schraegstrich mehr folgt -- und // '/exists/*' trifft sie NICHT, weil dort kein Schraegstrich mehr folgt -- und
// eine Auskunft ohne Token waere genau das Loch, das die Abfrageform schliessen // eine Auskunft ohne Token waere genau das Loch, das die Abfrageform schliessen
// soll. // soll.
uploadRoutes.use('/zugang', requireToken)
uploadRoutes.use('/exists', requireToken) uploadRoutes.use('/exists', requireToken)
uploadRoutes.use('/exists/*', requireToken) uploadRoutes.use('/exists/*', requireToken)
@@ -425,6 +426,53 @@ function existsAntwort(c: Context<{ Variables: Vars }>, roh: string) {
) )
} }
/** Was darf dieser Token eigentlich?
*
* WOZU. Das Fotostudio soll beim Einrichten eine AUSWAHL der Ordner zeigen
* statt eines Freitextfeldes -- und eine Auswahl, die etwas anbietet, das
* hinterher mit 403 abprallt, ist schlimmer als keine.
*
* Bisher erfuhr man die Fesseln nur, indem man dagegen lief: die
* 403-Meldung nennt sie. Das ist eine Auskunft ueber den eigenen Zugang, kein
* Geheimnis -- wer den Token hat, kennt seinen Umfang ohnehin, er muss ihn
* nur ausprobieren. Also lieber geradeheraus.
*
* Eine leere Liste heisst "ueberall", genau wie in der Datenbank. Das steht
* auch im Feld daneben, damit niemand "keine Ordner" liest.
*/
uploadRoutes.get('/zugang', (c) => {
const token = c.get('token') as Token
const fesseln = tokenPrefixes(token)
// WELCHE ORDNER ZUR AUSWAHL STEHEN.
//
// Ist der Token gefesselt, sind es genau seine -- eine Auswahl, die etwas
// anbietet, das hinterher mit 403 abprallt, waere schlimmer als keine.
//
// Ist er es NICHT, waere die Antwort "ueberall" fuer ein Auswahlfeld
// wertlos. Dann kommen die Ordner, die es wirklich gibt. Das ist keine
// Preisgabe: wer ueberall schreiben darf, kommt an jeden davon ohnehin --
// er muesste den Namen nur raten.
const vorhanden = (
db
.prepare(
`SELECT DISTINCT substr(path, 1, instr(path, '/') - 1) AS o
FROM media WHERE instr(path, '/') > 0 ORDER BY o`,
)
.all() as { o: string }[]
).map((z) => z.o)
return c.json({
// Woraus das Auswahlfeld waehlen darf.
ordner: fesseln.length > 0 ? fesseln : vorhanden,
// Und ob daneben noch etwas anderes ginge -- dann darf das Feld auch
// einen freien Namen zulassen.
ueberall: fesseln.length === 0,
darfLoeschen: token.can_delete === 1,
name: token.name,
})
})
uploadRoutes.get('/exists', (c) => { uploadRoutes.get('/exists', (c) => {
const roh = c.req.query('pfad') ?? c.req.query('path') ?? '' const roh = c.req.query('pfad') ?? c.req.query('path') ?? ''
if (!roh) return c.json({ error: 'Abfrage "pfad" fehlt' }, 400) if (!roh) return c.json({ error: 'Abfrage "pfad" fehlt' }, 400)