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 { 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)
|
||||||
|
|||||||
Reference in new issue
Block a user