| import { Router, type Request, type Response } from "express"; |
| import { createReadStream, existsSync } from "fs"; |
| import { extractToken, resolveUser } from "../auth.js"; |
| import { getStorageStatus } from "../hf-storage.js"; |
| import { docPath, sanitizeName } from "../utils.js"; |
|
|
| interface StorageContext { |
| oauthEnabled: boolean; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export function createStorageRouter(ctx: StorageContext): Router { |
| const router = Router(); |
|
|
| router.get("/api/storage/status", async (req, res) => { |
| if (ctx.oauthEnabled) { |
| const token = extractToken(req.headers.cookie); |
| const user = await resolveUser(token); |
| if (!user || !user.canEdit) { |
| res.status(403).json({ error: "Unauthorized" }); |
| return; |
| } |
| } |
| res.json(getStorageStatus()); |
| }); |
|
|
| router.get("/api/admin/export-doc", async (req: Request, res: Response) => { |
| if (ctx.oauthEnabled) { |
| const token = extractToken(req.headers.cookie); |
| const user = await resolveUser(token); |
| if (!user || !user.canEdit) { |
| res.status(403).json({ error: "Unauthorized" }); |
| return; |
| } |
| } |
|
|
| |
| |
| const rawName = typeof req.query.name === "string" ? req.query.name : "default"; |
| const safeName = sanitizeName(rawName); |
| const path = docPath(rawName); |
|
|
| if (!existsSync(path)) { |
| res.status(404).json({ error: "No on-disk snapshot for that doc" }); |
| return; |
| } |
|
|
| |
| |
| |
| |
| const stamp = new Date().toISOString().replace(/[:.]/g, "-"); |
| res.setHeader("Content-Type", "application/octet-stream"); |
| res.setHeader( |
| "Content-Disposition", |
| `attachment; filename="${safeName}-${stamp}.yjs"`, |
| ); |
| res.setHeader("Cache-Control", "no-store"); |
|
|
| const stream = createReadStream(path); |
| stream.on("error", (err) => { |
| console.error(`[admin-export] stream error for ${safeName}:`, err.message); |
| if (!res.headersSent) res.status(500).end(); |
| else res.end(); |
| }); |
| stream.pipe(res); |
| }); |
|
|
| return router; |
| } |
|
|