aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2015-11-07 14:16:26 +0100
committerChocobozzz <florian.bigard@gmail.com>2015-11-07 14:16:26 +0100
commit34ca3b5225479a5da986c86ee4c42a73ae6df5ad (patch)
tree561ba5ae1adccd5729305a8cc17d13d24a0c2ddb
parentf5a60a5138135a3412dfbcfd6e564f7aa47a55c2 (diff)
downloadPeerTube-34ca3b5225479a5da986c86ee4c42a73ae6df5ad.tar.gz
PeerTube-34ca3b5225479a5da986c86ee4c42a73ae6df5ad.tar.zst
PeerTube-34ca3b5225479a5da986c86ee4c42a73ae6df5ad.zip
Add requests parameters validations
-rw-r--r--middlewares/reqValidators/index.js11
-rw-r--r--middlewares/reqValidators/pods.js19
-rw-r--r--middlewares/reqValidators/remote.js40
-rw-r--r--middlewares/reqValidators/utils.js22
-rw-r--r--middlewares/reqValidators/videos.js67
-rw-r--r--routes/api/v1/pods.js3
-rw-r--r--routes/api/v1/remoteVideos.js5
-rw-r--r--routes/api/v1/videos.js9
-rw-r--r--server.js2
-rw-r--r--test/api/checkParams.js295
-rw-r--r--test/fixtures/video_short.mp4bin0 -> 38783 bytes
-rw-r--r--test/fixtures/video_short.ogvbin0 -> 140849 bytes
-rw-r--r--test/fixtures/video_short_fake.webm1
13 files changed, 467 insertions, 7 deletions
diff --git a/middlewares/reqValidators/index.js b/middlewares/reqValidators/index.js
new file mode 100644
index 000000000..1ea611031
--- /dev/null
+++ b/middlewares/reqValidators/index.js
@@ -0,0 +1,11 @@
1;(function () {
2 'use strict'
3
4 var reqValidator = {
5 videos: require('./videos'),
6 pods: require('./pods'),
7 remote: require('./remote')
8 }
9
10 module.exports = reqValidator
11})()
diff --git a/middlewares/reqValidators/pods.js b/middlewares/reqValidators/pods.js
new file mode 100644
index 000000000..31eaf8449
--- /dev/null
+++ b/middlewares/reqValidators/pods.js
@@ -0,0 +1,19 @@
1;(function () {
2 'use strict'
3
4 var checkErrors = require('./utils').checkErrors
5 var logger = require('../../src/logger')
6
7 var pods = {}
8
9 pods.podsAdd = function (req, res, next) {
10 req.checkBody('data.url', 'Should have an url').notEmpty().isURL({ require_protocol: true })
11 req.checkBody('data.publicKey', 'Should have a public key').notEmpty()
12
13 logger.debug('Checking podsAdd parameters', { parameters: req.body })
14
15 checkErrors(req, res, next)
16 }
17
18 module.exports = pods
19})()
diff --git a/middlewares/reqValidators/remote.js b/middlewares/reqValidators/remote.js
new file mode 100644
index 000000000..e851b49a4
--- /dev/null
+++ b/middlewares/reqValidators/remote.js
@@ -0,0 +1,40 @@
1;(function () {
2 'use strict'
3
4 var checkErrors = require('./utils').checkErrors
5 var logger = require('../../src/logger')
6
7 var remote = {}
8
9 remote.secureRequest = function (req, res, next) {
10 req.checkBody('signature.url', 'Should have a signature url').isURL()
11 req.checkBody('signature.signature', 'Should have a signature').notEmpty()
12 req.checkBody('key', 'Should have a key').notEmpty()
13 req.checkBody('data', 'Should have data').notEmpty()
14
15 logger.debug('Checking secureRequest parameters', { parameters: req.body })
16
17 checkErrors(req, res, next)
18 }
19
20 remote.remoteVideosAdd = function (req, res, next) {
21 req.checkBody('data.name', 'Should have a name').isLength(1, 50)
22 req.checkBody('data.description', 'Should have a description').isLength(1, 250)
23 req.checkBody('data.magnetUri', 'Should have a magnetUri').notEmpty()
24 req.checkBody('data.podUrl', 'Should have a podUrl').isURL()
25
26 logger.debug('Checking remoteVideosAdd parameters', { parameters: req.body })
27
28 checkErrors(req, res, next)
29 }
30
31 remote.remoteVideosRemove = function (req, res, next) {
32 req.checkBody('data.magnetUri', 'Should have a magnetUri').notEmpty()
33
34 logger.debug('Checking remoteVideosRemove parameters', { parameters: req.body })
35
36 checkErrors(req, res, next)
37 }
38
39 module.exports = remote
40})()
diff --git a/middlewares/reqValidators/utils.js b/middlewares/reqValidators/utils.js
new file mode 100644
index 000000000..91ead27a5
--- /dev/null
+++ b/middlewares/reqValidators/utils.js
@@ -0,0 +1,22 @@
1;(function () {
2 'use strict'
3
4 var util = require('util')
5 var logger = require('../../src/logger')
6
7 var utils = {}
8
9 utils.checkErrors = function (req, res, next, status_code) {
10 if (status_code === undefined) status_code = 400
11 var errors = req.validationErrors()
12
13 if (errors) {
14 logger.warn('Incorrect request parameters', { path: req.originalUrl, err: errors })
15 return res.status(status_code).send('There have been validation errors: ' + util.inspect(errors))
16 }
17
18 return next()
19 }
20
21 module.exports = utils
22})()
diff --git a/middlewares/reqValidators/videos.js b/middlewares/reqValidators/videos.js
new file mode 100644
index 000000000..3763a657c
--- /dev/null
+++ b/middlewares/reqValidators/videos.js
@@ -0,0 +1,67 @@
1;(function () {
2 'use strict'
3
4 var checkErrors = require('./utils').checkErrors
5 var VideosDB = require('../../src/database').VideosDB
6 var logger = require('../../src/logger')
7
8 var videos = {}
9
10 function findVideoById (id, callback) {
11 VideosDB.findById(id, { _id: 1, namePath: 1 }).limit(1).exec(function (err, video) {
12 if (err) throw err
13
14 callback(video)
15 })
16 }
17
18 videos.videosSearch = function (req, res, next) {
19 req.checkParams('name', 'Should have a name').notEmpty()
20
21 logger.debug('Checking videosSearch parameters', { parameters: req.params })
22
23 checkErrors(req, res, next)
24 }
25
26 videos.videosAdd = function (req, res, next) {
27 req.checkFiles('input_video.originalname', 'Should have an input video').notEmpty()
28 req.checkFiles('input_video.mimetype', 'Should have a correct mime type').matches(/video\/(webm)|(mp4)|(ogg)/i)
29 req.checkBody('name', 'Should have a name').isLength(1, 50)
30 req.checkBody('description', 'Should have a description').isLength(1, 250)
31
32 logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files })
33
34 checkErrors(req, res, next)
35 }
36
37 videos.videosGet = function (req, res, next) {
38 req.checkParams('id', 'Should have a valid id').notEmpty().isMongoId()
39
40 logger.debug('Checking videosGet parameters', { parameters: req.params })
41
42 checkErrors(req, res, function () {
43 findVideoById(req.params.id, function (video) {
44 if (!video) return res.status(404).send('Video not found')
45
46 next()
47 })
48 })
49 }
50
51 videos.videosRemove = function (req, res, next) {
52 req.checkParams('id', 'Should have a valid id').notEmpty().isMongoId()
53
54 logger.debug('Checking videosRemove parameters', { parameters: req.params })
55
56 checkErrors(req, res, function () {
57 findVideoById(req.params.id, function (video) {
58 if (!video) return res.status(404).send('Video not found')
59 else if (video.namePath === null) return res.status(403).send('Cannot remove video of another pod')
60
61 next()
62 })
63 })
64 }
65
66 module.exports = videos
67})()
diff --git a/routes/api/v1/pods.js b/routes/api/v1/pods.js
index 961388fcb..8ae676834 100644
--- a/routes/api/v1/pods.js
+++ b/routes/api/v1/pods.js
@@ -4,6 +4,7 @@
4 var express = require('express') 4 var express = require('express')
5 var router = express.Router() 5 var router = express.Router()
6 var middleware = require('../../../middlewares') 6 var middleware = require('../../../middlewares')
7 var reqValidator = require('../../../middlewares/reqValidators').pods
7 var pods = require('../../../src/pods') 8 var pods = require('../../../src/pods')
8 9
9 function listPods (req, res, next) { 10 function listPods (req, res, next) {
@@ -32,7 +33,7 @@
32 33
33 router.get('/', middleware.cache(false), listPods) 34 router.get('/', middleware.cache(false), listPods)
34 router.get('/makefriends', middleware.cache(false), makeFriends) 35 router.get('/makefriends', middleware.cache(false), makeFriends)
35 router.post('/', middleware.cache(false), addPods) 36 router.post('/', reqValidator.podsAdd, middleware.cache(false), addPods)
36 37
37 module.exports = router 38 module.exports = router
38})() 39})()
diff --git a/routes/api/v1/remoteVideos.js b/routes/api/v1/remoteVideos.js
index 88b8e879b..23bdcbe24 100644
--- a/routes/api/v1/remoteVideos.js
+++ b/routes/api/v1/remoteVideos.js
@@ -4,6 +4,7 @@
4 var express = require('express') 4 var express = require('express')
5 var router = express.Router() 5 var router = express.Router()
6 var middleware = require('../../../middlewares') 6 var middleware = require('../../../middlewares')
7 var requestValidator = require('../../../middlewares/reqValidators').remote
7 var videos = require('../../../src/videos') 8 var videos = require('../../../src/videos')
8 9
9 function addRemoteVideos (req, res, next) { 10 function addRemoteVideos (req, res, next) {
@@ -22,8 +23,8 @@
22 }) 23 })
23 } 24 }
24 25
25 router.post('/add', middleware.cache(false), middleware.decryptBody, addRemoteVideos) 26 router.post('/add', requestValidator.secureRequest, middleware.decryptBody, requestValidator.remoteVideosAdd, middleware.cache(false), addRemoteVideos)
26 router.post('/remove', middleware.cache(false), middleware.decryptBody, removeRemoteVideo) 27 router.post('/remove', requestValidator.secureRequest, middleware.decryptBody, requestValidator.remoteVideosRemove, middleware.cache(false), removeRemoteVideo)
27 28
28 module.exports = router 29 module.exports = router
29})() 30})()
diff --git a/routes/api/v1/videos.js b/routes/api/v1/videos.js
index 246620ac6..06b248244 100644
--- a/routes/api/v1/videos.js
+++ b/routes/api/v1/videos.js
@@ -4,6 +4,7 @@
4 var express = require('express') 4 var express = require('express')
5 var router = express.Router() 5 var router = express.Router()
6 var middleware = require('../../../middlewares') 6 var middleware = require('../../../middlewares')
7 var reqValidator = require('../../../middlewares/reqValidators').videos
7 var videos = require('../../../src/videos') 8 var videos = require('../../../src/videos')
8 9
9 function listVideos (req, res, next) { 10 function listVideos (req, res, next) {
@@ -52,10 +53,10 @@
52 } 53 }
53 54
54 router.get('/', middleware.cache(false), listVideos) 55 router.get('/', middleware.cache(false), listVideos)
55 router.post('/', middleware.cache(false), addVideos) 56 router.post('/', reqValidator.videosAdd, middleware.cache(false), addVideos)
56 router.get('/search/:name', middleware.cache(false), searchVideos) 57 router.get('/search/:name', reqValidator.videosSearch, middleware.cache(false), searchVideos)
57 router.get('/:id', middleware.cache(false), getVideos) 58 router.get('/:id', reqValidator.videosGet, middleware.cache(false), getVideos)
58 router.delete('/:id', middleware.cache(false), removeVideo) 59 router.delete('/:id', reqValidator.videosRemove, middleware.cache(false), removeVideo)
59 60
60 module.exports = router 61 module.exports = router
61})() 62})()
diff --git a/server.js b/server.js
index d3718f8de..317d8c3cd 100644
--- a/server.js
+++ b/server.js
@@ -6,6 +6,7 @@
6 6
7 // ----------- Node modules ----------- 7 // ----------- Node modules -----------
8 var express = require('express') 8 var express = require('express')
9 var expressValidator = require('express-validator')
9 var path = require('path') 10 var path = require('path')
10 var morgan = require('morgan') 11 var morgan = require('morgan')
11 var bodyParser = require('body-parser') 12 var bodyParser = require('body-parser')
@@ -47,6 +48,7 @@
47 app.use(bodyParser.json()) 48 app.use(bodyParser.json())
48 app.use(multer({ dest: uploads })) 49 app.use(multer({ dest: uploads }))
49 app.use(bodyParser.urlencoded({ extended: false })) 50 app.use(bodyParser.urlencoded({ extended: false }))
51 app.use(expressValidator())
50 52
51 // ----------- Views, routes and static files ----------- 53 // ----------- Views, routes and static files -----------
52 54
diff --git a/test/api/checkParams.js b/test/api/checkParams.js
new file mode 100644
index 000000000..a06e32bbc
--- /dev/null
+++ b/test/api/checkParams.js
@@ -0,0 +1,295 @@
1;(function () {
2 'use strict'
3
4 var request = require('supertest')
5 var chai = require('chai')
6 var expect = chai.expect
7
8 var utils = require('../utils')
9
10 describe('Test parameters validator', function () {
11 var app = null
12 var url = ''
13
14 before(function (done) {
15 this.timeout(20000)
16
17 utils.flushTests(function () {
18 utils.runServer(1, function (app1, url1) {
19 app = app1
20 url = url1
21 done()
22 })
23 })
24 })
25
26 function makePostRequest (path, fields, attach, done, fail) {
27 var status_code = 400
28 if (fail !== undefined && fail === false) status_code = 200
29
30 var req = request(url)
31 .post(path)
32 .set('Accept', 'application/json')
33
34 Object.keys(fields).forEach(function (field) {
35 var value = fields[field]
36 req.field(field, value)
37 })
38
39 req.expect(status_code, done)
40 }
41
42 function makePostBodyRequest (path, fields, done, fail) {
43 var status_code = 400
44 if (fail !== undefined && fail === false) status_code = 200
45
46 request(url)
47 .post(path)
48 .set('Accept', 'application/json')
49 .send(fields)
50 .expect(status_code, done)
51 }
52
53 describe('Of the pods API', function () {
54 var path = '/api/v1/pods/'
55
56 describe('When adding a pod', function () {
57 it('Should fail with nothing', function (done) {
58 var data = {}
59 makePostBodyRequest(path, data, done)
60 })
61
62 it('Should fail without public key', function (done) {
63 var data = {
64 data: {
65 url: 'http://coucou.com'
66 }
67 }
68 makePostBodyRequest(path, data, done)
69 })
70
71 it('Should fail without an url', function (done) {
72 var data = {
73 data: {
74 publicKey: 'mysuperpublickey'
75 }
76 }
77 makePostBodyRequest(path, data, done)
78 })
79
80 it('Should fail with an incorrect url', function (done) {
81 var data = {
82 data: {
83 url: 'coucou.com',
84 publicKey: 'mysuperpublickey'
85 }
86 }
87 makePostBodyRequest(path, data, function () {
88 data.data.url = 'http://coucou'
89 makePostBodyRequest(path, data, function () {
90 data.data.url = 'coucou'
91 makePostBodyRequest(path, data, done)
92 })
93 })
94 })
95
96 it('Should succeed with the correct parameters', function (done) {
97 var data = {
98 data: {
99 url: 'http://coucou.com',
100 publicKey: 'mysuperpublickey'
101 }
102 }
103 makePostBodyRequest(path, data, done, false)
104 })
105 })
106 })
107
108 describe('Of the videos API', function () {
109 var path = '/api/v1/videos/'
110
111 describe('When searching a video', function () {
112 it('Should fail with nothing', function (done) {
113 request(url)
114 .get(path + '/search/')
115 .set('Accept', 'application/json')
116 .expect(400, done)
117 })
118 })
119
120 describe('When adding a video', function () {
121 it('Should fail with nothing', function (done) {
122 var data = {}
123 var attach = {}
124 makePostRequest(path, data, attach, done)
125 })
126
127 it('Should fail without name', function (done) {
128 var data = {
129 description: 'my super description'
130 }
131 var attach = {
132 'input_video': __dirname + '/../fixtures/video_short.webm'
133 }
134 makePostRequest(path, data, attach, done)
135 })
136
137 it('Should fail with a long name', function (done) {
138 var data = {
139 name: 'My very very very very very very very very very very very very very very very very long name',
140 description: 'my super description'
141 }
142 var attach = {
143 'input_video': __dirname + '/../fixtures/video_short.webm'
144 }
145 makePostRequest(path, data, attach, done)
146 })
147
148 it('Should fail without description', function (done) {
149 var data = {
150 name: 'my super name'
151 }
152 var attach = {
153 'input_video': __dirname + '/../fixtures/video_short.webm'
154 }
155 makePostRequest(path, data, attach, done)
156 })
157
158 it('Should fail with a long description', function (done) {
159 var data = {
160 name: 'my super name',
161 description: 'my super description which is very very very very very very very very very very very very very very' +
162 'very very very very very very very very very very very very very very very very very very very very very' +
163 'very very very very very very very very very very very very very very very long'
164 }
165 var attach = {
166 'input_video': __dirname + '/../fixtures/video_short.webm'
167 }
168 makePostRequest(path, data, attach, done)
169 })
170
171 it('Should fail without an input file', function (done) {
172 var data = {
173 name: 'my super name',
174 description: 'my super description'
175 }
176 var attach = {}
177 makePostRequest(path, data, attach, done)
178 })
179
180 it('Should fail without an incorrect input file', function (done) {
181 var data = {
182 name: 'my super name',
183 description: 'my super description'
184 }
185 var attach = {
186 'input_video': __dirname + '/../fixtures/video_short_fake.webm'
187 }
188 makePostRequest(path, data, attach, done)
189 })
190
191 it('Should succeed with the correct parameters', function (done) {
192 var data = {
193 name: 'my super name',
194 description: 'my super description'
195 }
196 var attach = {
197 'input_video': __dirname + '/../fixtures/video_short.webm'
198 }
199 makePostRequest(path, data, attach, function () {
200 attach.input_video = __dirname + '/../fixtures/video_short.mp4'
201 makePostRequest(path, data, attach, function () {
202 attach.input_video = __dirname + '/../fixtures/video_short.ogv'
203 makePostRequest(path, data, attach, done, true)
204 }, true)
205 }, true)
206 })
207 })
208
209 describe('When getting a video', function () {
210 it('Should return the list of the videos with nothing', function (done) {
211 request(url)
212 .get(path)
213 .set('Accept', 'application/json')
214 .expect(200)
215 .expect('Content-Type', /json/)
216 .end(function (err, res) {
217 if (err) throw err
218
219 expect(res.body).to.be.an('array')
220 expect(res.body.length).to.equal(0)
221
222 done()
223 })
224 })
225
226 it('Should fail without a mongodb id', function (done) {
227 request(url)
228 .get(path + 'coucou')
229 .set('Accept', 'application/json')
230 .expect(400, done)
231 })
232
233 it('Should return 404 with an incorrect video', function (done) {
234 request(url)
235 .get(path + '123456789012345678901234')
236 .set('Accept', 'application/json')
237 .expect(404, done)
238 })
239
240 it('Should succeed with the correct parameters')
241 })
242
243 describe('When removing a video', function () {
244 it('Should have 404 with nothing', function (done) {
245 request(url)
246 .delete(path)
247 .expect(404, done)
248 })
249
250 it('Should fail without a mongodb id', function (done) {
251 request(url)
252 .delete(path + 'hello')
253 .expect(400, done)
254 })
255
256 it('Should fail with a video which does not exist', function (done) {
257 request(url)
258 .delete(path + '123456789012345678901234')
259 .expect(404, done)
260 })
261
262 it('Should fail with a video of another pod')
263
264 it('Should succeed with the correct parameters')
265 })
266 })
267
268 describe('Of the remote videos API', function () {
269 describe('When making a secure request', function () {
270 it('Should check a secure request')
271 })
272
273 describe('When adding a video', function () {
274 it('Should check when adding a video')
275 })
276
277 describe('When removing a video', function () {
278 it('Should check when removing a video')
279 })
280 })
281
282 after(function (done) {
283 process.kill(-app.pid)
284
285 // Keep the logs if the test failed
286 if (this.ok) {
287 utils.flushTests(function () {
288 done()
289 })
290 } else {
291 done()
292 }
293 })
294 })
295})()
diff --git a/test/fixtures/video_short.mp4 b/test/fixtures/video_short.mp4
new file mode 100644
index 000000000..35678362b
--- /dev/null
+++ b/test/fixtures/video_short.mp4
Binary files differ
diff --git a/test/fixtures/video_short.ogv b/test/fixtures/video_short.ogv
new file mode 100644
index 000000000..9e253da82
--- /dev/null
+++ b/test/fixtures/video_short.ogv
Binary files differ
diff --git a/test/fixtures/video_short_fake.webm b/test/fixtures/video_short_fake.webm
new file mode 100644
index 000000000..d85290ae5
--- /dev/null
+++ b/test/fixtures/video_short_fake.webm
@@ -0,0 +1 @@
this is a fake video mouahahah