juice-shop
100 строк · 3.9 Кб
1/*
2* Copyright (c) 2014-2024 Bjoern Kimminich & the OWASP Juice Shop contributors.
3* SPDX-License-Identifier: MIT
4*/
5
6import { type Request, type Response, type NextFunction } from 'express'7import { BasketItemModel } from '../models/basketitem'8import { QuantityModel } from '../models/quantity'9import challengeUtils = require('../lib/challengeUtils')10
11import * as utils from '../lib/utils'12import { challenges } from '../data/datacache'13const security = require('../lib/insecurity')14
15interface RequestWithRawBody extends Request {16rawBody: string17}
18
19module.exports.addBasketItem = function addBasketItem () {20return (req: RequestWithRawBody, res: Response, next: NextFunction) => {21const result = utils.parseJsonCustom(req.rawBody)22const productIds = []23const basketIds = []24const quantities = []25
26for (let i = 0; i < result.length; i++) {27if (result[i].key === 'ProductId') {28productIds.push(result[i].value)29} else if (result[i].key === 'BasketId') {30basketIds.push(result[i].value)31} else if (result[i].key === 'quantity') {32quantities.push(result[i].value)33}34}35
36const user = security.authenticatedUsers.from(req)37if (user && basketIds[0] && basketIds[0] !== 'undefined' && Number(user.bid) != Number(basketIds[0])) { // eslint-disable-line eqeqeq38res.status(401).send('{\'error\' : \'Invalid BasketId\'}')39} else {40const basketItem = {41ProductId: productIds[productIds.length - 1],42BasketId: basketIds[basketIds.length - 1],43quantity: quantities[quantities.length - 1]44}45challengeUtils.solveIf(challenges.basketManipulateChallenge, () => { return user && basketItem.BasketId && basketItem.BasketId !== 'undefined' && user.bid != basketItem.BasketId }) // eslint-disable-line eqeqeq46
47const basketItemInstance = BasketItemModel.build(basketItem)48basketItemInstance.save().then((addedBasketItem: BasketItemModel) => {49res.json({ status: 'success', data: addedBasketItem })50}).catch((error: Error) => {51next(error)52})53}54}55}
56
57module.exports.quantityCheckBeforeBasketItemAddition = function quantityCheckBeforeBasketItemAddition () {58return (req: Request, res: Response, next: NextFunction) => {59void quantityCheck(req, res, next, req.body.ProductId, req.body.quantity).catch((error: Error) => {60next(error)61})62}63}
64
65module.exports.quantityCheckBeforeBasketItemUpdate = function quantityCheckBeforeBasketItemUpdate () {66return (req: Request, res: Response, next: NextFunction) => {67BasketItemModel.findOne({ where: { id: req.params.id } }).then((item: BasketItemModel | null) => {68const user = security.authenticatedUsers.from(req)69challengeUtils.solveIf(challenges.basketManipulateChallenge, () => { return user && req.body.BasketId && user.bid != req.body.BasketId }) // eslint-disable-line eqeqeq70if (req.body.quantity) {71if (item == null) {72throw new Error('No such item found!')73}74void quantityCheck(req, res, next, item.ProductId, req.body.quantity)75} else {76next()77}78}).catch((error: Error) => {79next(error)80})81}82}
83
84async function quantityCheck (req: Request, res: Response, next: NextFunction, id: number, quantity: number) {85const product = await QuantityModel.findOne({ where: { ProductId: id } })86if (product == null) {87throw new Error('No such product found!')88}89
90// is product limited per user and order, except if user is deluxe?91if (!product.limitPerUser || (product.limitPerUser && product.limitPerUser >= quantity) || security.isDeluxe(req)) {92if (product.quantity >= quantity) { // enough in stock?93next()94} else {95res.status(400).json({ error: res.__('We are out of stock! Sorry for the inconvenience.') })96}97} else {98res.status(400).json({ error: res.__('You can order only up to {{quantity}} items of this product.', { quantity: product.limitPerUser.toString() }) })99}100}
101