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:
1 parent
06285a3a53
commit
73c9f310c0
1 file changed
+49
-1
@@ -24,7 +24,7 @@ import type { Context, Next } from 'hono'
|
||||
import { config } from '../config.js'
|
||||
import { meldeUpload } from '../meldung.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 {
|
||||
PathError,
|
||||
checkPath,
|
||||
@@ -141,6 +141,7 @@ uploadRoutes.use('/media/*', requireToken)
|
||||
// '/exists/*' trifft sie NICHT, weil dort kein Schraegstrich mehr folgt -- und
|
||||
// eine Auskunft ohne Token waere genau das Loch, das die Abfrageform schliessen
|
||||
// soll.
|
||||
uploadRoutes.use('/zugang', 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) => {
|
||||
const roh = c.req.query('pfad') ?? c.req.query('path') ?? ''
|
||||
if (!roh) return c.json({ error: 'Abfrage "pfad" fehlt' }, 400)
|
||||
|
||||
Reference in new issue
Block a user