juice-shop

Форк
0
/
productReviewApiSpec.ts 
163 строки · 4.9 Кб
1
/*
2
 * Copyright (c) 2014-2024 Bjoern Kimminich & the OWASP Juice Shop contributors.
3
 * SPDX-License-Identifier: MIT
4
 */
5

6
import frisby = require('frisby')
7
import config from 'config'
8
import { type Product } from '../../data/types'
9
import { type IncomingMessage } from 'http'
10
const Joi = frisby.Joi
11
const security = require('../../lib/insecurity')
12
const http = require('http')
13

14
const REST_URL = 'http://localhost:3000/rest'
15

16
const jsonHeader = { 'content-type': 'application/json' }
17
const authHeader = { Authorization: `Bearer ${security.authorize()}`, 'content-type': 'application/json' }
18

19
describe('/rest/products/:id/reviews', () => {
20
  const reviewResponseSchema = {
21
    id: Joi.number(),
22
    product: Joi.number(),
23
    message: Joi.string(),
24
    author: Joi.string()
25
  }
26

27
  it('GET product reviews by product id', () => {
28
    return frisby.get(`${REST_URL}/products/1/reviews`)
29
      .expect('status', 200)
30
      .expect('header', 'content-type', /application\/json/)
31
      .expect('jsonTypes', reviewResponseSchema)
32
  })
33

34
  it('GET product reviews attack by injecting a mongoDB sleep command', () => {
35
    return 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

41
  xit('GET product reviews by alphanumeric non-mongoDB-command product id', () => { // FIXME Turn on when #1960 is resolved
42
    return frisby.get(`${REST_URL}/products/kaboom/reviews`)
43
      .expect('status', 400)
44
  })
45

46
  it('PUT single product review can be created', () => {
47
    return frisby.put(`${REST_URL}/products/1/reviews`, {
48
      body: {
49
        message: 'Lorem Ipsum',
50
        author: 'Anonymous'
51
      }
52
    })
53
      .expect('status', 201)
54
      .expect('header', 'content-type', /application\/json/)
55
  })
56
})
57

58
describe('/rest/products/reviews', () => {
59
  const updatedReviewResponseSchema = {
60
    modified: Joi.number(),
61
    original: Joi.array(),
62
    updated: Joi.array()
63
  }
64

65
  let reviewId: string
66

67
  beforeAll((done) => {
68
    http.get(`${REST_URL}/products/1/reviews`, (res: IncomingMessage) => {
69
      let body = ''
70

71
      res.on('data', (chunk: string) => {
72
        body += chunk
73
      })
74

75
      res.on('end', () => {
76
        const response = JSON.parse(body)
77
        reviewId = response.data[0]._id
78
        done()
79
      })
80
    })
81
  })
82

83
  it('PATCH single product review can be edited', () => {
84
    return frisby.patch(`${REST_URL}/products/reviews`, {
85
      headers: authHeader,
86
      body: {
87
        id: reviewId,
88
        message: 'Lorem Ipsum'
89
      }
90
    })
91
      .expect('status', 200)
92
      .expect('header', 'content-type', /application\/json/)
93
      .expect('jsonTypes', updatedReviewResponseSchema)
94
  })
95

96
  it('PATCH single product review editing need an authenticated user', () => {
97
    return frisby.patch(`${REST_URL}/products/reviews`, {
98
      body: {
99
        id: reviewId,
100
        message: 'Lorem Ipsum'
101
      }
102
    })
103
      .expect('status', 401)
104
  })
105

106
  it('POST non-existing product review cannot be liked', () => {
107
    return frisby.post(`${REST_URL}/user/login`, {
108
      headers: jsonHeader,
109
      body: {
110
        email: 'bjoern.kimminich@gmail.com',
111
        password: 'bW9jLmxpYW1nQGhjaW5pbW1pay5ucmVvamI='
112
      }
113
    })
114
      .expect('status', 200)
115
      .then(({ json: jsonLogin }) => {
116
        return frisby.post(`${REST_URL}/products/reviews`, {
117
          headers: { Authorization: `Bearer ${jsonLogin.authentication.token}` },
118
          body: {
119
            id: 'does not exist'
120
          }
121
        })
122
          .expect('status', 404)
123
      })
124
  })
125

126
  it('POST single product review can be liked', () => {
127
    return frisby.post(`${REST_URL}/user/login`, {
128
      headers: jsonHeader,
129
      body: {
130
        email: 'bjoern.kimminich@gmail.com',
131
        password: 'bW9jLmxpYW1nQGhjaW5pbW1pay5ucmVvamI='
132
      }
133
    })
134
      .expect('status', 200)
135
      .then(({ json: jsonLogin }) => {
136
        return frisby.post(`${REST_URL}/products/reviews`, {
137
          headers: { Authorization: `Bearer ${jsonLogin.authentication.token}` },
138
          body: {
139
            id: reviewId
140
          }
141
        })
142
          .expect('status', 200)
143
          .expect('jsonTypes', { likesCount: Joi.number() })
144
      })
145
  })
146

147
  it('PATCH multiple product review via injection', () => {
148
    // Count all the reviews. (Count starts at one because of the review inserted by the other tests...)
149
    const totalReviews = config.get<Product[]>('products').reduce((sum: number, { reviews = [] }: any) => sum + reviews.length, 1)
150

151
    return frisby.patch(`${REST_URL}/products/reviews`, {
152
      headers: authHeader,
153
      body: {
154
        id: { $ne: -1 },
155
        message: '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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.