juice-shop
163 строки · 4.9 Кб
1/*
2* Copyright (c) 2014-2024 Bjoern Kimminich & the OWASP Juice Shop contributors.
3* SPDX-License-Identifier: MIT
4*/
5
6import frisby = require('frisby')
7import config from 'config'
8import { type Product } from '../../data/types'
9import { type IncomingMessage } from 'http'
10const Joi = frisby.Joi
11const security = require('../../lib/insecurity')
12const http = require('http')
13
14const REST_URL = 'http://localhost:3000/rest'
15
16const jsonHeader = { 'content-type': 'application/json' }
17const authHeader = { Authorization: `Bearer ${security.authorize()}`, 'content-type': 'application/json' }
18
19describe('/rest/products/:id/reviews', () => {
20const reviewResponseSchema = {
21id: Joi.number(),
22product: Joi.number(),
23message: Joi.string(),
24author: Joi.string()
25}
26
27it('GET product reviews by product id', () => {
28return frisby.get(`${REST_URL}/products/1/reviews`)
29.expect('status', 200)
30.expect('header', 'content-type', /application\/json/)
31.expect('jsonTypes', reviewResponseSchema)
32})
33
34it('GET product reviews attack by injecting a mongoDB sleep command', () => {
35return frisby.get(`${REST_URL}/products/sleep(1)/reviews`)
36.expect('status', 200)
37.expect('header', 'content-type', /application\/json/)
38.expect('jsonTypes', reviewResponseSchema)
39})
40
41xit('GET product reviews by alphanumeric non-mongoDB-command product id', () => { // FIXME Turn on when #1960 is resolved
42return frisby.get(`${REST_URL}/products/kaboom/reviews`)
43.expect('status', 400)
44})
45
46it('PUT single product review can be created', () => {
47return frisby.put(`${REST_URL}/products/1/reviews`, {
48body: {
49message: 'Lorem Ipsum',
50author: 'Anonymous'
51}
52})
53.expect('status', 201)
54.expect('header', 'content-type', /application\/json/)
55})
56})
57
58describe('/rest/products/reviews', () => {
59const updatedReviewResponseSchema = {
60modified: Joi.number(),
61original: Joi.array(),
62updated: Joi.array()
63}
64
65let reviewId: string
66
67beforeAll((done) => {
68http.get(`${REST_URL}/products/1/reviews`, (res: IncomingMessage) => {
69let body = ''
70
71res.on('data', (chunk: string) => {
72body += chunk
73})
74
75res.on('end', () => {
76const response = JSON.parse(body)
77reviewId = response.data[0]._id
78done()
79})
80})
81})
82
83it('PATCH single product review can be edited', () => {
84return frisby.patch(`${REST_URL}/products/reviews`, {
85headers: authHeader,
86body: {
87id: reviewId,
88message: 'Lorem Ipsum'
89}
90})
91.expect('status', 200)
92.expect('header', 'content-type', /application\/json/)
93.expect('jsonTypes', updatedReviewResponseSchema)
94})
95
96it('PATCH single product review editing need an authenticated user', () => {
97return frisby.patch(`${REST_URL}/products/reviews`, {
98body: {
99id: reviewId,
100message: 'Lorem Ipsum'
101}
102})
103.expect('status', 401)
104})
105
106it('POST non-existing product review cannot be liked', () => {
107return frisby.post(`${REST_URL}/user/login`, {
108headers: jsonHeader,
109body: {
110email: 'bjoern.kimminich@gmail.com',
111password: 'bW9jLmxpYW1nQGhjaW5pbW1pay5ucmVvamI='
112}
113})
114.expect('status', 200)
115.then(({ json: jsonLogin }) => {
116return frisby.post(`${REST_URL}/products/reviews`, {
117headers: { Authorization: `Bearer ${jsonLogin.authentication.token}` },
118body: {
119id: 'does not exist'
120}
121})
122.expect('status', 404)
123})
124})
125
126it('POST single product review can be liked', () => {
127return frisby.post(`${REST_URL}/user/login`, {
128headers: jsonHeader,
129body: {
130email: 'bjoern.kimminich@gmail.com',
131password: 'bW9jLmxpYW1nQGhjaW5pbW1pay5ucmVvamI='
132}
133})
134.expect('status', 200)
135.then(({ json: jsonLogin }) => {
136return frisby.post(`${REST_URL}/products/reviews`, {
137headers: { Authorization: `Bearer ${jsonLogin.authentication.token}` },
138body: {
139id: reviewId
140}
141})
142.expect('status', 200)
143.expect('jsonTypes', { likesCount: Joi.number() })
144})
145})
146
147it('PATCH multiple product review via injection', () => {
148// Count all the reviews. (Count starts at one because of the review inserted by the other tests...)
149const totalReviews = config.get<Product[]>('products').reduce((sum: number, { reviews = [] }: any) => sum + reviews.length, 1)
150
151return frisby.patch(`${REST_URL}/products/reviews`, {
152headers: authHeader,
153body: {
154id: { $ne: -1 },
155message: 'trololololololololololololololololololololololololololol'
156}
157})
158.expect('status', 200)
159.expect('header', 'content-type', /application\/json/)
160.expect('jsonTypes', updatedReviewResponseSchema)
161.expect('json', { modified: totalReviews })
162})
163})
164