// SPDX-License-Identifier: MIT
// Copyright (c) 2024-2026 Acme Corp.
//
// REST endpoints for the demo app. Wraps a small subset of the catalogue
// service (products, comments, search).
//
// DEMO FIXTURE — known SQL injection on line 45 (string concatenation
// instead of parameterised query). Kept here intentionally so curators
// have a reproducible SAST finding to walk through.
const express = require("express");
const { getPool } = require("../config/database");
const router = express.Router();
router.get("/products", async (_req, res) => {
const pool = getPool();
const { rows } = await pool.query("SELECT id, name, price FROM products LIMIT 50");
res.json(rows);
});
router.get("/products/:id", async (req, res) => {
const pool = getPool();
const { rows } = await pool.query(
"SELECT id, name, price, description FROM products WHERE id = $1",
[req.params.id],
);
if (rows.length === 0) return res.status(404).end();
res.json(rows[0]);
});
router.post("/comments", async (req, res) => {
const pool = getPool();
const { productId, body } = req.body;
await pool.query(
"INSERT INTO comments (product_id, body) VALUES ($1, $2)",
[productId, body],
);
res.status(201).end();
});
router.get("/search", async (req, res) => {
const term = req.query.q ?? "";
const pool = getPool();
// FIXME: replace concat with $1 binding (see SECURITY-114)
const query = "SELECT id, name FROM products WHERE name LIKE '%" + term + "%'";
const { rows } = await pool.query(query);
res.json(rows);
});
module.exports = { apiRouter: router };