Seguridad y docs: fix SQLi en updatePost, middleware por segmentos exactos, cover-cache directo al upstream, JWT sin fallback hardcodeado, password sudo fuera de deploy/setup.sh; reescritura AGENTS.md y CLAUDE.md
This commit is contained in:
+15
-3
@@ -1,5 +1,6 @@
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
import { get } from "./settings"
|
||||
|
||||
const COVERS_DIR = process.env.COVERS_DIR || path.join(process.cwd(), "data", "covers")
|
||||
|
||||
@@ -20,10 +21,21 @@ function extFromContentType(ct: string | null): string {
|
||||
return exts[m[1]] || ".jpg"
|
||||
}
|
||||
|
||||
export async function cacheCover(gid: string, proxyUrl: string): Promise<string | null> {
|
||||
// Descarga la portada DIRECTAMENTE del upstream (API_BASE_URL), con la misma
|
||||
// API key que usa el resto de la app. NO pasa por el proxy /api/proxy/* (que el
|
||||
// middleware protege), evitando el redirect a /login que guardaba HTML como portada.
|
||||
export async function cacheCover(gid: string): Promise<string | null> {
|
||||
ensureDir()
|
||||
try {
|
||||
const res = await fetch(proxyUrl, { signal: AbortSignal.timeout(15000) })
|
||||
const apiBase = get("API_BASE_URL", "http://127.0.0.1:8080/api/v1")
|
||||
const apiKey = get("API_KEY")
|
||||
const headers: Record<string, string> = {}
|
||||
if (apiKey) headers["X-API-Key"] = apiKey
|
||||
|
||||
const res = await fetch(`${apiBase}/galleries/${gid}/cover`, {
|
||||
headers,
|
||||
signal: AbortSignal.timeout(15000),
|
||||
})
|
||||
if (!res.ok) return null
|
||||
|
||||
const buffer = Buffer.from(await res.arrayBuffer())
|
||||
@@ -61,4 +73,4 @@ export function getCoverContentType(gid: string): string {
|
||||
export function deleteCover(gid: string): void {
|
||||
const fp = getCoverPath(gid)
|
||||
if (fp) fs.unlinkSync(fp)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user