Security: API kljuc za pisalne endpointe (articles, upload)
This commit is contained in:
parent
fda5e2ce62
commit
69d400a209
@ -65,6 +65,15 @@ export async function registerRoutes(
|
||||
|
||||
startDailyScheduler();
|
||||
|
||||
// ---- API zascita za pisalne endpointe (boti posiljajo x-api-key) ----
|
||||
const FOLX_API_KEY = process.env.FOLX_API_KEY || "";
|
||||
const requireApiKey = (req: any, res: any, next: any) => {
|
||||
if (!FOLX_API_KEY) return next(); // brez nastavljenega kljuca: ne zaklepamo (rollout varovalka)
|
||||
const provided = req.get("x-api-key") || (req.get("authorization") || "").replace(/^Bearer\s+/i, "");
|
||||
if (provided && provided === FOLX_API_KEY) return next();
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
};
|
||||
|
||||
storage.getArticles().then((articles) => {
|
||||
analyzeAllArticleImages(articles).catch(err =>
|
||||
console.log("[focal-point] Analysis skipped:", err.message)
|
||||
@ -232,7 +241,7 @@ export async function registerRoutes(
|
||||
res.json({ ...article, views: article.views + (isNew ? 1 : 0) });
|
||||
});
|
||||
|
||||
app.post("/api/articles", async (req, res) => {
|
||||
app.post("/api/articles", requireApiKey, async (req, res) => {
|
||||
const parsed = insertArticleSchema.safeParse(req.body);
|
||||
if (!parsed.success) {
|
||||
return res.status(400).json({ message: "Invalid article data", errors: parsed.error.flatten() });
|
||||
@ -245,7 +254,7 @@ export async function registerRoutes(
|
||||
res.status(201).json(article);
|
||||
});
|
||||
|
||||
app.patch("/api/articles/:id", async (req, res) => {
|
||||
app.patch("/api/articles/:id", requireApiKey, async (req, res) => {
|
||||
const id = parseInt(req.params.id);
|
||||
const partial = insertArticleSchema.partial().safeParse(req.body);
|
||||
if (!partial.success) {
|
||||
@ -258,13 +267,13 @@ export async function registerRoutes(
|
||||
res.json(article);
|
||||
});
|
||||
|
||||
app.delete("/api/articles/:id", async (req, res) => {
|
||||
app.delete("/api/articles/:id", requireApiKey, async (req, res) => {
|
||||
const id = parseInt(req.params.id);
|
||||
await storage.deleteArticle(id);
|
||||
res.status(204).send();
|
||||
});
|
||||
|
||||
app.post("/api/upload", upload.single("image"), async (req, res) => {
|
||||
app.post("/api/upload", requireApiKey, upload.single("image"), async (req, res) => {
|
||||
if (!req.file) {
|
||||
return res.status(400).json({ message: "No file uploaded" });
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user