diff --git a/routes/productCost.ts b/routes/productCost.ts new file mode 100644 index 00000000000..ea76806a5ac --- /dev/null +++ b/routes/productCost.ts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014-2024 Bjoern Kimminich & the OWASP Juice Shop contributors. + * SPDX-License-Identifier: MIT + */ + +import * as models from '../models/index' +import { type Request, type Response, type NextFunction } from 'express' + +// Product cost lookup for the merchant dashboard. Same shape as the revenue +// endpoint, with the filter bound as a query parameter. +module.exports = function productCost () { + return (req: Request, res: Response, next: NextFunction) => { + const name = String(req.query.name ?? '') + models.sequelize.query( + 'SELECT id, name, price FROM Products WHERE name LIKE :pattern AND deletedAt IS NULL ORDER BY price DESC', + { replacements: { pattern: `%${name}%` }, type: models.sequelize.QueryTypes.SELECT } + ).then((rows: any) => { + res.json({ name, rows }) + }).catch((error: Error) => { + next(error) + }) + } +} diff --git a/server.ts b/server.ts index c2689cc8d39..b096e32a32d 100644 --- a/server.ts +++ b/server.ts @@ -89,6 +89,7 @@ const resetPassword = require('./routes/resetPassword') const securityQuestion = require('./routes/securityQuestion') const search = require('./routes/search') const coupon = require('./routes/coupon') +const productCost = require('./routes/productCost') const basket = require('./routes/basket') const order = require('./routes/order') const verify = require('./routes/verify') @@ -568,6 +569,7 @@ restoreOverwrittenFilesWithOriginals().then(() => { app.get('/rest/user/whoami', security.updateAuthenticatedUsers(), currentUser()) app.get('/rest/user/authentication-details', authenticatedUsers()) app.get('/rest/products/search', search()) + app.get('/rest/products/cost', productCost()) app.get('/rest/basket/:id', basket()) app.post('/rest/basket/:id/checkout', order()) app.put('/rest/basket/:id/coupon/:coupon', coupon())