Session 45: support email, audit fixes (template validation, content-type, admin auth, waitUntil)
All checks were successful
Deploy to Production / Deploy to Server (push) Successful in 2m20s
All checks were successful
Deploy to Production / Deploy to Server (push) Successful in 2m20s
- Added support@docfast.dev to footer, impressum, terms, landing page, openapi.json - Fixed audit #6: Template render validates required fields (400 on missing) - Fixed audit #7: Content-Type check on markdown/URL routes (415) - Fixed audit #11: /v1/usage and /v1/concurrency now require ADMIN_API_KEY - Fixed audit Critical #3: URL convert uses domcontentloaded instead of networkidle0
This commit is contained in:
parent
8a86e34f91
commit
59cc8f3d0e
22 changed files with 166 additions and 61 deletions
|
|
@ -3,6 +3,10 @@ import { renderPdf } from "../services/browser.js";
|
|||
import logger from "../services/logger.js";
|
||||
import { templates, renderTemplate } from "../services/templates.js";
|
||||
|
||||
function sanitizeFilename(name: string): string {
|
||||
return name.replace(/["\r\n\x00-\x1f]/g, "_").substring(0, 200);
|
||||
}
|
||||
|
||||
export const templatesRouter = Router();
|
||||
|
||||
// GET /v1/templates — list available templates
|
||||
|
|
@ -27,13 +31,28 @@ templatesRouter.post("/:id/render", async (req: Request, res: Response) => {
|
|||
}
|
||||
|
||||
const data = req.body.data || req.body;
|
||||
|
||||
// Validate required fields
|
||||
const missingFields = template.fields
|
||||
.filter((f) => f.required && (data[f.name] === undefined || data[f.name] === null || data[f.name] === ""))
|
||||
.map((f) => f.name);
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
res.status(400).json({
|
||||
error: "Missing required fields",
|
||||
missing: missingFields,
|
||||
hint: `Required fields for '${id}': ${template.fields.filter((f) => f.required).map((f) => f.name).join(", ")}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const html = renderTemplate(id, data);
|
||||
const pdf = await renderPdf(html, {
|
||||
format: data._format || "A4",
|
||||
margin: data._margin,
|
||||
});
|
||||
|
||||
const filename = data._filename || `${id}.pdf`;
|
||||
const filename = sanitizeFilename(data._filename || `${id}.pdf`);
|
||||
res.setHeader("Content-Type", "application/pdf");
|
||||
res.setHeader("Content-Disposition", `inline; filename="${filename}"`);
|
||||
res.send(pdf);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue