diff options
author | Chocobozzz <me@florianbigard.com> | 2021-06-02 18:15:41 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-06-02 18:15:41 +0200 |
commit | e030bfb59dd5ee65f20a64686ec9b22ca39f70ae (patch) | |
tree | c9a439159ef540291e3c030bcaf958b953442147 /server | |
parent | 463206948d6a9d46e7e68d55c7b763e601ecc870 (diff) | |
download | PeerTube-e030bfb59dd5ee65f20a64686ec9b22ca39f70ae.tar.gz PeerTube-e030bfb59dd5ee65f20a64686ec9b22ca39f70ae.tar.zst PeerTube-e030bfb59dd5ee65f20a64686ec9b22ca39f70ae.zip |
Refactor server errors handler
Diffstat (limited to 'server')
-rw-r--r-- | server/controllers/api/videos/index.ts | 3 | ||||
-rw-r--r-- | server/controllers/api/videos/update.ts | 2 | ||||
-rw-r--r-- | server/controllers/api/videos/upload.ts | 4 | ||||
-rw-r--r-- | server/helpers/express-utils.ts | 32 | ||||
-rw-r--r-- | server/middlewares/doc.ts | 13 | ||||
-rw-r--r-- | server/middlewares/error.ts | 39 | ||||
-rw-r--r-- | server/middlewares/index.ts | 2 | ||||
-rw-r--r-- | server/middlewares/validators/videos/videos.ts | 6 | ||||
-rw-r--r-- | server/tests/api/check-params/videos.ts | 78 | ||||
-rw-r--r-- | server/tests/api/server/follow-constraints.ts | 16 | ||||
-rw-r--r-- | server/typings/express/index.d.ts | 19 |
11 files changed, 169 insertions, 45 deletions
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index db23e5630..7671f099e 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -2,6 +2,7 @@ import * as express from 'express' | |||
2 | import toInt from 'validator/lib/toInt' | 2 | import toInt from 'validator/lib/toInt' |
3 | import { doJSONRequest } from '@server/helpers/requests' | 3 | import { doJSONRequest } from '@server/helpers/requests' |
4 | import { LiveManager } from '@server/lib/live-manager' | 4 | import { LiveManager } from '@server/lib/live-manager' |
5 | import { docMiddleware } from '@server/middlewares/doc' | ||
5 | import { getServerActor } from '@server/models/application/application' | 6 | import { getServerActor } from '@server/models/application/application' |
6 | import { MVideoAccountLight } from '@server/types/models' | 7 | import { MVideoAccountLight } from '@server/types/models' |
7 | import { VideosCommonQuery } from '../../../../shared' | 8 | import { VideosCommonQuery } from '../../../../shared' |
@@ -83,6 +84,7 @@ videosRouter.get('/:id/metadata/:videoFileId', | |||
83 | asyncMiddleware(getVideoFileMetadata) | 84 | asyncMiddleware(getVideoFileMetadata) |
84 | ) | 85 | ) |
85 | videosRouter.get('/:id', | 86 | videosRouter.get('/:id', |
87 | docMiddleware('https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo'), | ||
86 | optionalAuthenticate, | 88 | optionalAuthenticate, |
87 | asyncMiddleware(videosCustomGetValidator('only-video-with-rights')), | 89 | asyncMiddleware(videosCustomGetValidator('only-video-with-rights')), |
88 | asyncMiddleware(checkVideoFollowConstraints), | 90 | asyncMiddleware(checkVideoFollowConstraints), |
@@ -94,6 +96,7 @@ videosRouter.post('/:id/views', | |||
94 | ) | 96 | ) |
95 | 97 | ||
96 | videosRouter.delete('/:id', | 98 | videosRouter.delete('/:id', |
99 | docMiddleware('https://docs.joinpeertube.org/api-rest-reference.html#operation/delVideo'), | ||
97 | authenticate, | 100 | authenticate, |
98 | asyncMiddleware(videosRemoveValidator), | 101 | asyncMiddleware(videosRemoveValidator), |
99 | asyncRetryTransactionMiddleware(removeVideo) | 102 | asyncRetryTransactionMiddleware(removeVideo) |
diff --git a/server/controllers/api/videos/update.ts b/server/controllers/api/videos/update.ts index 2450abd0e..09e584d30 100644 --- a/server/controllers/api/videos/update.ts +++ b/server/controllers/api/videos/update.ts | |||
@@ -20,6 +20,7 @@ import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist' | |||
20 | import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videosUpdateValidator } from '../../../middlewares' | 20 | import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videosUpdateValidator } from '../../../middlewares' |
21 | import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' | 21 | import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' |
22 | import { VideoModel } from '../../../models/video/video' | 22 | import { VideoModel } from '../../../models/video/video' |
23 | import { docMiddleware } from '@server/middlewares/doc' | ||
23 | 24 | ||
24 | const lTags = loggerTagsFactory('api', 'video') | 25 | const lTags = loggerTagsFactory('api', 'video') |
25 | const auditLogger = auditLoggerFactory('videos') | 26 | const auditLogger = auditLoggerFactory('videos') |
@@ -35,6 +36,7 @@ const reqVideoFileUpdate = createReqFiles( | |||
35 | ) | 36 | ) |
36 | 37 | ||
37 | updateRouter.put('/:id', | 38 | updateRouter.put('/:id', |
39 | docMiddleware('https://docs.joinpeertube.org/api-rest-reference.html#operation/putVideo'), | ||
38 | authenticate, | 40 | authenticate, |
39 | reqVideoFileUpdate, | 41 | reqVideoFileUpdate, |
40 | asyncMiddleware(videosUpdateValidator), | 42 | asyncMiddleware(videosUpdateValidator), |
diff --git a/server/controllers/api/videos/upload.ts b/server/controllers/api/videos/upload.ts index c33d7fcb9..93a68f759 100644 --- a/server/controllers/api/videos/upload.ts +++ b/server/controllers/api/videos/upload.ts | |||
@@ -6,6 +6,7 @@ import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | |||
6 | import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' | 6 | import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' |
7 | import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' | 7 | import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' |
8 | import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' | 8 | import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' |
9 | import { docMiddleware } from '@server/middlewares/doc' | ||
9 | import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' | 10 | import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' |
10 | import { uploadx } from '@uploadx/core' | 11 | import { uploadx } from '@uploadx/core' |
11 | import { VideoCreate, VideoState } from '../../../../shared' | 12 | import { VideoCreate, VideoState } from '../../../../shared' |
@@ -60,6 +61,7 @@ const reqVideoFileAddResumable = createReqFiles( | |||
60 | ) | 61 | ) |
61 | 62 | ||
62 | uploadRouter.post('/upload', | 63 | uploadRouter.post('/upload', |
64 | docMiddleware('https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadLegacy'), | ||
63 | authenticate, | 65 | authenticate, |
64 | reqVideoFileAdd, | 66 | reqVideoFileAdd, |
65 | asyncMiddleware(videosAddLegacyValidator), | 67 | asyncMiddleware(videosAddLegacyValidator), |
@@ -67,6 +69,7 @@ uploadRouter.post('/upload', | |||
67 | ) | 69 | ) |
68 | 70 | ||
69 | uploadRouter.post('/upload-resumable', | 71 | uploadRouter.post('/upload-resumable', |
72 | docMiddleware('https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadResumableInit'), | ||
70 | authenticate, | 73 | authenticate, |
71 | reqVideoFileAddResumable, | 74 | reqVideoFileAddResumable, |
72 | asyncMiddleware(videosAddResumableInitValidator), | 75 | asyncMiddleware(videosAddResumableInitValidator), |
@@ -79,6 +82,7 @@ uploadRouter.delete('/upload-resumable', | |||
79 | ) | 82 | ) |
80 | 83 | ||
81 | uploadRouter.put('/upload-resumable', | 84 | uploadRouter.put('/upload-resumable', |
85 | docMiddleware('https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadResumable'), | ||
82 | authenticate, | 86 | authenticate, |
83 | uploadxMiddleware, // uploadx doesn't use call next() before the file upload completes | 87 | uploadxMiddleware, // uploadx doesn't use call next() before the file upload completes |
84 | asyncMiddleware(videosAddResumableValidator), | 88 | asyncMiddleware(videosAddResumableValidator), |
diff --git a/server/helpers/express-utils.ts b/server/helpers/express-utils.ts index 10a860787..010c6961a 100644 --- a/server/helpers/express-utils.ts +++ b/server/helpers/express-utils.ts | |||
@@ -8,7 +8,6 @@ import { isArray } from './custom-validators/misc' | |||
8 | import { logger } from './logger' | 8 | import { logger } from './logger' |
9 | import { deleteFileAndCatch, generateRandomString } from './utils' | 9 | import { deleteFileAndCatch, generateRandomString } from './utils' |
10 | import { getExtFromMimetype } from './video' | 10 | import { getExtFromMimetype } from './video' |
11 | import { ProblemDocument, ProblemDocumentExtension } from 'http-problem-details' | ||
12 | 11 | ||
13 | function buildNSFWFilter (res?: express.Response, paramNSFW?: string) { | 12 | function buildNSFWFilter (res?: express.Response, paramNSFW?: string) { |
14 | if (paramNSFW === 'true') return true | 13 | if (paramNSFW === 'true') return true |
@@ -126,34 +125,6 @@ function getCountVideos (req: express.Request) { | |||
126 | return req.query.skipCount !== true | 125 | return req.query.skipCount !== true |
127 | } | 126 | } |
128 | 127 | ||
129 | // helpers added in server.ts and used in subsequent controllers used | ||
130 | const apiResponseHelpers = (req, res: express.Response, next = null) => { | ||
131 | res.fail = (options) => { | ||
132 | const { data, status = HttpStatusCode.BAD_REQUEST_400, message, title, type, docs = res.docs, instance } = options | ||
133 | |||
134 | const extension = new ProblemDocumentExtension({ | ||
135 | ...data, | ||
136 | docs, | ||
137 | // fields for <= 3.2 compatibility, deprecated | ||
138 | error: message, | ||
139 | code: type | ||
140 | }) | ||
141 | |||
142 | res.status(status) | ||
143 | res.setHeader('Content-Type', 'application/problem+json') | ||
144 | res.json(new ProblemDocument({ | ||
145 | status, | ||
146 | title, | ||
147 | instance, | ||
148 | // fields intended to replace 'error' and 'code' respectively | ||
149 | detail: message, | ||
150 | type: type && 'https://docs.joinpeertube.org/api-rest-reference.html#section/Errors/' + type | ||
151 | }, extension)) | ||
152 | } | ||
153 | |||
154 | if (next) next() | ||
155 | } | ||
156 | |||
157 | // --------------------------------------------------------------------------- | 128 | // --------------------------------------------------------------------------- |
158 | 129 | ||
159 | export { | 130 | export { |
@@ -163,6 +134,5 @@ export { | |||
163 | badRequest, | 134 | badRequest, |
164 | createReqFiles, | 135 | createReqFiles, |
165 | cleanUpReqFiles, | 136 | cleanUpReqFiles, |
166 | getCountVideos, | 137 | getCountVideos |
167 | apiResponseHelpers | ||
168 | } | 138 | } |
diff --git a/server/middlewares/doc.ts b/server/middlewares/doc.ts new file mode 100644 index 000000000..aa852cd77 --- /dev/null +++ b/server/middlewares/doc.ts | |||
@@ -0,0 +1,13 @@ | |||
1 | import * as express from 'express' | ||
2 | |||
3 | function docMiddleware (docUrl: string) { | ||
4 | return (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
5 | res.locals.docUrl = docUrl | ||
6 | |||
7 | if (next) return next() | ||
8 | } | ||
9 | } | ||
10 | |||
11 | export { | ||
12 | docMiddleware | ||
13 | } | ||
diff --git a/server/middlewares/error.ts b/server/middlewares/error.ts new file mode 100644 index 000000000..e3eb1c8f5 --- /dev/null +++ b/server/middlewares/error.ts | |||
@@ -0,0 +1,39 @@ | |||
1 | import * as express from 'express' | ||
2 | import { ProblemDocument, ProblemDocumentExtension } from 'http-problem-details' | ||
3 | import { HttpStatusCode } from '@shared/core-utils' | ||
4 | |||
5 | function apiFailMiddleware (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
6 | res.fail = options => { | ||
7 | const { status = HttpStatusCode.BAD_REQUEST_400, message, title, type, data, instance } = options | ||
8 | |||
9 | const extension = new ProblemDocumentExtension({ | ||
10 | ...data, | ||
11 | |||
12 | docs: res.locals.docUrl, | ||
13 | code: type, | ||
14 | |||
15 | // For <= 3.2 compatibility | ||
16 | error: message | ||
17 | }) | ||
18 | |||
19 | res.status(status) | ||
20 | res.setHeader('Content-Type', 'application/problem+json') | ||
21 | res.json(new ProblemDocument({ | ||
22 | status, | ||
23 | title, | ||
24 | instance, | ||
25 | |||
26 | detail: message, | ||
27 | |||
28 | type: type | ||
29 | ? `https://docs.joinpeertube.org/api-rest-reference.html#section/Errors/${type}` | ||
30 | : undefined | ||
31 | }, extension)) | ||
32 | } | ||
33 | |||
34 | if (next) next() | ||
35 | } | ||
36 | |||
37 | export { | ||
38 | apiFailMiddleware | ||
39 | } | ||
diff --git a/server/middlewares/index.ts b/server/middlewares/index.ts index 3e280e16f..413653dac 100644 --- a/server/middlewares/index.ts +++ b/server/middlewares/index.ts | |||
@@ -7,4 +7,6 @@ export * from './servers' | |||
7 | export * from './sort' | 7 | export * from './sort' |
8 | export * from './user-right' | 8 | export * from './user-right' |
9 | export * from './dnt' | 9 | export * from './dnt' |
10 | export * from './error' | ||
11 | export * from './doc' | ||
10 | export * from './csp' | 12 | export * from './csp' |
diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts index 64e09234e..b7a9bcbe3 100644 --- a/server/middlewares/validators/videos/videos.ts +++ b/server/middlewares/validators/videos/videos.ts | |||
@@ -73,7 +73,6 @@ const videosAddLegacyValidator = getCommonVideoEditAttributes().concat([ | |||
73 | .custom(isIdValid).withMessage('Should have correct video channel id'), | 73 | .custom(isIdValid).withMessage('Should have correct video channel id'), |
74 | 74 | ||
75 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 75 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
76 | res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadLegacy" | ||
77 | logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) | 76 | logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) |
78 | 77 | ||
79 | if (areValidationErrors(req, res)) return cleanUpReqFiles(req) | 78 | if (areValidationErrors(req, res)) return cleanUpReqFiles(req) |
@@ -108,7 +107,6 @@ const videosAddLegacyValidator = getCommonVideoEditAttributes().concat([ | |||
108 | */ | 107 | */ |
109 | const videosAddResumableValidator = [ | 108 | const videosAddResumableValidator = [ |
110 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 109 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
111 | res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadResumable" | ||
112 | const user = res.locals.oauth.token.User | 110 | const user = res.locals.oauth.token.User |
113 | 111 | ||
114 | const body: express.CustomUploadXFile<express.UploadXFileMetadata> = req.body | 112 | const body: express.CustomUploadXFile<express.UploadXFileMetadata> = req.body |
@@ -170,7 +168,6 @@ const videosAddResumableInitValidator = getCommonVideoEditAttributes().concat([ | |||
170 | .withMessage('Should specify the file mimetype'), | 168 | .withMessage('Should specify the file mimetype'), |
171 | 169 | ||
172 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 170 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
173 | res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadResumableInit" | ||
174 | const videoFileMetadata = { | 171 | const videoFileMetadata = { |
175 | mimetype: req.headers['x-upload-content-type'] as string, | 172 | mimetype: req.headers['x-upload-content-type'] as string, |
176 | size: +req.headers['x-upload-content-length'], | 173 | size: +req.headers['x-upload-content-length'], |
@@ -214,7 +211,6 @@ const videosUpdateValidator = getCommonVideoEditAttributes().concat([ | |||
214 | .custom(isIdValid).withMessage('Should have correct video channel id'), | 211 | .custom(isIdValid).withMessage('Should have correct video channel id'), |
215 | 212 | ||
216 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 213 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
217 | res.docs = 'https://docs.joinpeertube.org/api-rest-reference.html#operation/putVideo' | ||
218 | logger.debug('Checking videosUpdate parameters', { parameters: req.body }) | 214 | logger.debug('Checking videosUpdate parameters', { parameters: req.body }) |
219 | 215 | ||
220 | if (areValidationErrors(req, res)) return cleanUpReqFiles(req) | 216 | if (areValidationErrors(req, res)) return cleanUpReqFiles(req) |
@@ -268,7 +264,6 @@ const videosCustomGetValidator = ( | |||
268 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 264 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), |
269 | 265 | ||
270 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 266 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
271 | res.docs = 'https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo' | ||
272 | logger.debug('Checking videosGet parameters', { parameters: req.params }) | 267 | logger.debug('Checking videosGet parameters', { parameters: req.params }) |
273 | 268 | ||
274 | if (areValidationErrors(req, res)) return | 269 | if (areValidationErrors(req, res)) return |
@@ -334,7 +329,6 @@ const videosRemoveValidator = [ | |||
334 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 329 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), |
335 | 330 | ||
336 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 331 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
337 | res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/delVideo" | ||
338 | logger.debug('Checking videosRemove parameters', { parameters: req.params }) | 332 | logger.debug('Checking videosRemove parameters', { parameters: req.params }) |
339 | 333 | ||
340 | if (areValidationErrors(req, res)) return | 334 | if (areValidationErrors(req, res)) return |
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index c970c4a15..a6eecb13a 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts | |||
@@ -4,6 +4,8 @@ import 'mocha' | |||
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { omit } from 'lodash' | 5 | import { omit } from 'lodash' |
6 | import { join } from 'path' | 6 | import { join } from 'path' |
7 | import { randomInt } from '@shared/core-utils' | ||
8 | import { PeerTubeProblemDocument } from '@shared/models' | ||
7 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' | 9 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' |
8 | import { | 10 | import { |
9 | checkUploadVideoParam, | 11 | checkUploadVideoParam, |
@@ -30,7 +32,6 @@ import { | |||
30 | checkBadStartPagination | 32 | checkBadStartPagination |
31 | } from '../../../../shared/extra-utils/requests/check-api-params' | 33 | } from '../../../../shared/extra-utils/requests/check-api-params' |
32 | import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum' | 34 | import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum' |
33 | import { randomInt } from '@shared/core-utils' | ||
34 | 35 | ||
35 | const expect = chai.expect | 36 | const expect = chai.expect |
36 | 37 | ||
@@ -411,6 +412,31 @@ describe('Test videos API validator', function () { | |||
411 | await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode) | 412 | await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode) |
412 | }) | 413 | }) |
413 | 414 | ||
415 | it('Should report the appropriate error', async function () { | ||
416 | const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) }) | ||
417 | const attaches = baseCorrectAttaches | ||
418 | |||
419 | const attributes = { ...fields, ...attaches } | ||
420 | const res = await checkUploadVideoParam(server.url, server.accessToken, attributes, HttpStatusCode.BAD_REQUEST_400, mode) | ||
421 | |||
422 | const error = res.body as PeerTubeProblemDocument | ||
423 | |||
424 | if (mode === 'legacy') { | ||
425 | expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadLegacy') | ||
426 | } else { | ||
427 | expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadResumableInit') | ||
428 | } | ||
429 | |||
430 | expect(error.type).to.equal('about:blank') | ||
431 | expect(error.title).to.equal('Bad Request') | ||
432 | |||
433 | expect(error.detail).to.equal('Incorrect request parameters: language') | ||
434 | expect(error.error).to.equal('Incorrect request parameters: language') | ||
435 | |||
436 | expect(error.status).to.equal(HttpStatusCode.BAD_REQUEST_400) | ||
437 | expect(error['invalid-params'].language).to.exist | ||
438 | }) | ||
439 | |||
414 | it('Should succeed with the correct parameters', async function () { | 440 | it('Should succeed with the correct parameters', async function () { |
415 | this.timeout(10000) | 441 | this.timeout(10000) |
416 | 442 | ||
@@ -645,6 +671,24 @@ describe('Test videos API validator', function () { | |||
645 | 671 | ||
646 | it('Should fail with a video of another server') | 672 | it('Should fail with a video of another server') |
647 | 673 | ||
674 | it('Shoud report the appropriate error', async function () { | ||
675 | const fields = immutableAssign(baseCorrectParams, { licence: 125 }) | ||
676 | |||
677 | const res = await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | ||
678 | const error = res.body as PeerTubeProblemDocument | ||
679 | |||
680 | expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/putVideo') | ||
681 | |||
682 | expect(error.type).to.equal('about:blank') | ||
683 | expect(error.title).to.equal('Bad Request') | ||
684 | |||
685 | expect(error.detail).to.equal('Incorrect request parameters: licence') | ||
686 | expect(error.error).to.equal('Incorrect request parameters: licence') | ||
687 | |||
688 | expect(error.status).to.equal(HttpStatusCode.BAD_REQUEST_400) | ||
689 | expect(error['invalid-params'].licence).to.exist | ||
690 | }) | ||
691 | |||
648 | it('Should succeed with the correct parameters', async function () { | 692 | it('Should succeed with the correct parameters', async function () { |
649 | const fields = baseCorrectParams | 693 | const fields = baseCorrectParams |
650 | 694 | ||
@@ -678,6 +722,22 @@ describe('Test videos API validator', function () { | |||
678 | await getVideo(server.url, '4da6fde3-88f7-4d16-b119-108df5630b06', HttpStatusCode.NOT_FOUND_404) | 722 | await getVideo(server.url, '4da6fde3-88f7-4d16-b119-108df5630b06', HttpStatusCode.NOT_FOUND_404) |
679 | }) | 723 | }) |
680 | 724 | ||
725 | it('Shoud report the appropriate error', async function () { | ||
726 | const res = await getVideo(server.url, 'hi', HttpStatusCode.BAD_REQUEST_400) | ||
727 | const error = res.body as PeerTubeProblemDocument | ||
728 | |||
729 | expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo') | ||
730 | |||
731 | expect(error.type).to.equal('about:blank') | ||
732 | expect(error.title).to.equal('Bad Request') | ||
733 | |||
734 | expect(error.detail).to.equal('Incorrect request parameters: id') | ||
735 | expect(error.error).to.equal('Incorrect request parameters: id') | ||
736 | |||
737 | expect(error.status).to.equal(HttpStatusCode.BAD_REQUEST_400) | ||
738 | expect(error['invalid-params'].id).to.exist | ||
739 | }) | ||
740 | |||
681 | it('Should succeed with the correct parameters', async function () { | 741 | it('Should succeed with the correct parameters', async function () { |
682 | await getVideo(server.url, videoId) | 742 | await getVideo(server.url, videoId) |
683 | }) | 743 | }) |
@@ -755,6 +815,22 @@ describe('Test videos API validator', function () { | |||
755 | 815 | ||
756 | it('Should fail with a video of another server') | 816 | it('Should fail with a video of another server') |
757 | 817 | ||
818 | it('Shoud report the appropriate error', async function () { | ||
819 | const res = await removeVideo(server.url, server.accessToken, 'hello', HttpStatusCode.BAD_REQUEST_400) | ||
820 | const error = res.body as PeerTubeProblemDocument | ||
821 | |||
822 | expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/delVideo') | ||
823 | |||
824 | expect(error.type).to.equal('about:blank') | ||
825 | expect(error.title).to.equal('Bad Request') | ||
826 | |||
827 | expect(error.detail).to.equal('Incorrect request parameters: id') | ||
828 | expect(error.error).to.equal('Incorrect request parameters: id') | ||
829 | |||
830 | expect(error.status).to.equal(HttpStatusCode.BAD_REQUEST_400) | ||
831 | expect(error['invalid-params'].id).to.exist | ||
832 | }) | ||
833 | |||
758 | it('Should succeed with the correct parameters', async function () { | 834 | it('Should succeed with the correct parameters', async function () { |
759 | await removeVideo(server.url, server.accessToken, videoId) | 835 | await removeVideo(server.url, server.accessToken, videoId) |
760 | }) | 836 | }) |
diff --git a/server/tests/api/server/follow-constraints.ts b/server/tests/api/server/follow-constraints.ts index 8a91fbba3..3f2f71f46 100644 --- a/server/tests/api/server/follow-constraints.ts +++ b/server/tests/api/server/follow-constraints.ts | |||
@@ -18,6 +18,7 @@ import { unfollow } from '../../../../shared/extra-utils/server/follows' | |||
18 | import { userLogin } from '../../../../shared/extra-utils/users/login' | 18 | import { userLogin } from '../../../../shared/extra-utils/users/login' |
19 | import { createUser } from '../../../../shared/extra-utils/users/users' | 19 | import { createUser } from '../../../../shared/extra-utils/users/users' |
20 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' | 20 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' |
21 | import { PeerTubeProblemDocument, ServerErrorCode } from '@shared/models' | ||
21 | 22 | ||
22 | const expect = chai.expect | 23 | const expect = chai.expect |
23 | 24 | ||
@@ -153,7 +154,20 @@ describe('Test follow constraints', function () { | |||
153 | }) | 154 | }) |
154 | 155 | ||
155 | it('Should not get the remote video', async function () { | 156 | it('Should not get the remote video', async function () { |
156 | await getVideo(servers[0].url, video2UUID, HttpStatusCode.FORBIDDEN_403) | 157 | const res = await getVideo(servers[0].url, video2UUID, HttpStatusCode.FORBIDDEN_403) |
158 | |||
159 | const error = res.body as PeerTubeProblemDocument | ||
160 | |||
161 | const doc = 'https://docs.joinpeertube.org/api-rest-reference.html#section/Errors/does_not_respect_follow_constraints' | ||
162 | expect(error.type).to.equal(doc) | ||
163 | expect(error.code).to.equal(ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS) | ||
164 | |||
165 | expect(error.detail).to.equal('Cannot get this video regarding follow constraints') | ||
166 | expect(error.error).to.equal(error.detail) | ||
167 | |||
168 | expect(error.status).to.equal(HttpStatusCode.FORBIDDEN_403) | ||
169 | |||
170 | expect(error.originUrl).to.contains(servers[1].url) | ||
157 | }) | 171 | }) |
158 | 172 | ||
159 | it('Should list local account videos', async function () { | 173 | it('Should list local account videos', async function () { |
diff --git a/server/typings/express/index.d.ts b/server/typings/express/index.d.ts index f58436ce1..cbbf40a78 100644 --- a/server/typings/express/index.d.ts +++ b/server/typings/express/index.d.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | |||
1 | import { RegisterServerAuthExternalOptions } from '@server/types' | 2 | import { RegisterServerAuthExternalOptions } from '@server/types' |
2 | import { | 3 | import { |
3 | MAbuseMessage, | 4 | MAbuseMessage, |
@@ -20,9 +21,8 @@ import { MVideoImportDefault } from '@server/types/models/video/video-import' | |||
20 | import { MVideoPlaylistElement, MVideoPlaylistElementVideoUrlPlaylistPrivacy } from '@server/types/models/video/video-playlist-element' | 21 | import { MVideoPlaylistElement, MVideoPlaylistElementVideoUrlPlaylistPrivacy } from '@server/types/models/video/video-playlist-element' |
21 | import { MAccountVideoRateAccountVideo } from '@server/types/models/video/video-rate' | 22 | import { MAccountVideoRateAccountVideo } from '@server/types/models/video/video-rate' |
22 | import { HttpMethod } from '@shared/core-utils/miscs/http-methods' | 23 | import { HttpMethod } from '@shared/core-utils/miscs/http-methods' |
23 | import { VideoCreate } from '@shared/models' | 24 | import { PeerTubeProblemDocumentData, ServerErrorCode, VideoCreate } from '@shared/models' |
24 | import { File as UploadXFile, Metadata } from '@uploadx/core' | 25 | import { File as UploadXFile, Metadata } from '@uploadx/core' |
25 | import { ProblemDocumentOptions } from 'http-problem-details/dist/ProblemDocument' | ||
26 | import { RegisteredPlugin } from '../../lib/plugins/plugin-manager' | 26 | import { RegisteredPlugin } from '../../lib/plugins/plugin-manager' |
27 | import { | 27 | import { |
28 | MAccountDefault, | 28 | MAccountDefault, |
@@ -41,6 +41,7 @@ import { | |||
41 | MVideoThumbnail, | 41 | MVideoThumbnail, |
42 | MVideoWithRights | 42 | MVideoWithRights |
43 | } from '../../types/models' | 43 | } from '../../types/models' |
44 | |||
44 | declare module 'express' { | 45 | declare module 'express' { |
45 | export interface Request { | 46 | export interface Request { |
46 | query: any | 47 | query: any |
@@ -86,14 +87,20 @@ declare module 'express' { | |||
86 | 87 | ||
87 | // Extends Response with added functions and potential variables passed by middlewares | 88 | // Extends Response with added functions and potential variables passed by middlewares |
88 | interface Response { | 89 | interface Response { |
89 | docs?: string | ||
90 | fail: (options: { | 90 | fail: (options: { |
91 | data?: Record<string, Object> | ||
92 | docs?: string | ||
93 | message: string | 91 | message: string |
94 | } & ProblemDocumentOptions) => void | 92 | |
93 | title?: string | ||
94 | status?: number | ||
95 | type?: ServerErrorCode | ||
96 | instance?: string | ||
97 | |||
98 | data?: PeerTubeProblemDocumentData | ||
99 | }) => void | ||
95 | 100 | ||
96 | locals: { | 101 | locals: { |
102 | docUrl?: string | ||
103 | |||
97 | videoAll?: MVideoFullLight | 104 | videoAll?: MVideoFullLight |
98 | onlyImmutableVideo?: MVideoImmutable | 105 | onlyImmutableVideo?: MVideoImmutable |
99 | onlyVideo?: MVideoThumbnail | 106 | onlyVideo?: MVideoThumbnail |