From 76148b27f7501bac061992136852be4303370c8d Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Tue, 1 Jun 2021 01:36:53 +0200 Subject: refactor API errors to standard error format --- .../validators/videos/video-blacklist.ts | 8 +- .../validators/videos/video-channels.ts | 47 ++++----- .../validators/videos/video-comments.ts | 27 +++--- .../middlewares/validators/videos/video-imports.ts | 23 +++-- server/middlewares/validators/videos/video-live.ts | 61 +++++++----- .../validators/videos/video-playlists.ts | 73 +++++++------- .../middlewares/validators/videos/video-rates.ts | 6 +- .../middlewares/validators/videos/video-watch.ts | 5 +- server/middlewares/validators/videos/videos.ts | 105 ++++++++++++--------- 9 files changed, 202 insertions(+), 153 deletions(-) (limited to 'server/middlewares/validators/videos') diff --git a/server/middlewares/validators/videos/video-blacklist.ts b/server/middlewares/validators/videos/video-blacklist.ts index 88c788a43..65132a09f 100644 --- a/server/middlewares/validators/videos/video-blacklist.ts +++ b/server/middlewares/validators/videos/video-blacklist.ts @@ -39,10 +39,10 @@ const videosBlacklistAddValidator = [ const video = res.locals.videoAll if (req.body.unfederate === true && video.remote === true) { - return res - .status(HttpStatusCode.CONFLICT_409) - .send({ error: 'You cannot unfederate a remote video.' }) - .end() + return res.fail({ + status: HttpStatusCode.CONFLICT_409, + message: 'You cannot unfederate a remote video.' + }) } return next() diff --git a/server/middlewares/validators/videos/video-channels.ts b/server/middlewares/validators/videos/video-channels.ts index e881f0d3e..331a51007 100644 --- a/server/middlewares/validators/videos/video-channels.ts +++ b/server/middlewares/validators/videos/video-channels.ts @@ -30,17 +30,16 @@ const videoChannelsAddValidator = [ const actor = await ActorModel.loadLocalByName(req.body.name) if (actor) { - res.status(HttpStatusCode.CONFLICT_409) - .send({ error: 'Another actor (account/channel) with this name on this instance already exists or has already existed.' }) - .end() + res.fail({ + status: HttpStatusCode.CONFLICT_409, + message: 'Another actor (account/channel) with this name on this instance already exists or has already existed.' + }) return false } const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id) if (count >= VIDEO_CHANNELS.MAX_PER_USER) { - res.status(HttpStatusCode.BAD_REQUEST_400) - .send({ error: `You cannot create more than ${VIDEO_CHANNELS.MAX_PER_USER} channels` }) - .end() + res.fail({ message: `You cannot create more than ${VIDEO_CHANNELS.MAX_PER_USER} channels` }) return false } @@ -71,13 +70,17 @@ const videoChannelsUpdateValidator = [ // We need to make additional checks if (res.locals.videoChannel.Actor.isOwned() === false) { - return res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Cannot update video channel of another server' }) + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot update video channel of another server' + }) } if (res.locals.videoChannel.Account.userId !== res.locals.oauth.token.User.id) { - return res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Cannot update video channel of another user' }) + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot update video channel of another user' + }) } return next() @@ -154,10 +157,10 @@ export { function checkUserCanDeleteVideoChannel (user: MUser, videoChannel: MChannelAccountDefault, res: express.Response) { if (videoChannel.Actor.isOwned() === false) { - res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Cannot remove video channel of another server.' }) - .end() - + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot remove video channel of another server.' + }) return false } @@ -165,10 +168,10 @@ function checkUserCanDeleteVideoChannel (user: MUser, videoChannel: MChannelAcco // The user can delete it if s/he is an admin // Or if s/he is the video channel's account if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && videoChannel.Account.userId !== user.id) { - res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Cannot remove video channel of another user' }) - .end() - + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot remove video channel of another user' + }) return false } @@ -179,10 +182,10 @@ async function checkVideoChannelIsNotTheLastOne (res: express.Response) { const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id) if (count <= 1) { - res.status(HttpStatusCode.CONFLICT_409) - .json({ error: 'Cannot remove the last channel of this user' }) - .end() - + res.fail({ + status: HttpStatusCode.CONFLICT_409, + message: 'Cannot remove the last channel of this user' + }) return false } diff --git a/server/middlewares/validators/videos/video-comments.ts b/server/middlewares/validators/videos/video-comments.ts index 1afacfed8..aac25a787 100644 --- a/server/middlewares/validators/videos/video-comments.ts +++ b/server/middlewares/validators/videos/video-comments.ts @@ -155,9 +155,10 @@ export { function isVideoCommentsEnabled (video: MVideo, res: express.Response) { if (video.commentsEnabled !== true) { - res.status(HttpStatusCode.CONFLICT_409) - .json({ error: 'Video comments are disabled for this video.' }) - + res.fail({ + status: HttpStatusCode.CONFLICT_409, + message: 'Video comments are disabled for this video.' + }) return false } @@ -166,9 +167,10 @@ function isVideoCommentsEnabled (video: MVideo, res: express.Response) { function checkUserCanDeleteVideoComment (user: MUserAccountUrl, videoComment: MCommentOwnerVideoReply, res: express.Response) { if (videoComment.isDeleted()) { - res.status(HttpStatusCode.CONFLICT_409) - .json({ error: 'This comment is already deleted' }) - + res.fail({ + status: HttpStatusCode.CONFLICT_409, + message: 'This comment is already deleted' + }) return false } @@ -179,9 +181,10 @@ function checkUserCanDeleteVideoComment (user: MUserAccountUrl, videoComment: MC videoComment.accountId !== userAccount.id && // Not the comment owner videoComment.Video.VideoChannel.accountId !== userAccount.id // Not the video owner ) { - res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Cannot remove video comment of another user' }) - + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot remove video comment of another user' + }) return false } @@ -215,9 +218,11 @@ async function isVideoCommentAccepted (req: express.Request, res: express.Respon if (!acceptedResult || acceptedResult.accepted !== true) { logger.info('Refused local comment.', { acceptedResult, acceptParameters }) - res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: acceptedResult?.errorMessage || 'Refused local comment' }) + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: acceptedResult?.errorMessage || 'Refused local comment' + }) return false } diff --git a/server/middlewares/validators/videos/video-imports.ts b/server/middlewares/validators/videos/video-imports.ts index a5e3ffbcd..55ff09124 100644 --- a/server/middlewares/validators/videos/video-imports.ts +++ b/server/middlewares/validators/videos/video-imports.ts @@ -47,14 +47,20 @@ const videoImportAddValidator = getCommonVideoEditAttributes().concat([ if (CONFIG.IMPORT.VIDEOS.HTTP.ENABLED !== true && req.body.targetUrl) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.CONFLICT_409) - .json({ error: 'HTTP import is not enabled on this instance.' }) + + return res.fail({ + status: HttpStatusCode.CONFLICT_409, + message: 'HTTP import is not enabled on this instance.' + }) } if (CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED !== true && (req.body.magnetUri || torrentFile)) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.CONFLICT_409) - .json({ error: 'Torrent/magnet URI import is not enabled on this instance.' }) + + return res.fail({ + status: HttpStatusCode.CONFLICT_409, + message: 'Torrent/magnet URI import is not enabled on this instance.' + }) } if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req) @@ -63,8 +69,7 @@ const videoImportAddValidator = getCommonVideoEditAttributes().concat([ if (!req.body.targetUrl && !req.body.magnetUri && !torrentFile) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: 'Should have a magnetUri or a targetUrl or a torrent file.' }) + return res.fail({ message: 'Should have a magnetUri or a targetUrl or a torrent file.' }) } if (!await isImportAccepted(req, res)) return cleanUpReqFiles(req) @@ -100,9 +105,11 @@ async function isImportAccepted (req: express.Request, res: express.Response) { if (!acceptedResult || acceptedResult.accepted !== true) { logger.info('Refused to import video.', { acceptedResult, acceptParameters }) - res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: acceptedResult.errorMessage || 'Refused to import video' }) + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: acceptedResult.errorMessage || 'Refused to import video' + }) return false } diff --git a/server/middlewares/validators/videos/video-live.ts b/server/middlewares/validators/videos/video-live.ts index ec4c7f32f..9544fa4f5 100644 --- a/server/middlewares/validators/videos/video-live.ts +++ b/server/middlewares/validators/videos/video-live.ts @@ -30,7 +30,12 @@ const videoLiveGetValidator = [ if (!checkUserCanManageVideo(user, res.locals.videoAll, UserRight.GET_ANY_LIVE, res, false)) return const videoLive = await VideoLiveModel.loadByVideoId(res.locals.videoAll.id) - if (!videoLive) return res.sendStatus(HttpStatusCode.NOT_FOUND_404) + if (!videoLive) { + return res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Live video not found' + }) + } res.locals.videoLive = videoLive @@ -66,22 +71,25 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([ if (CONFIG.LIVE.ENABLED !== true) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Live is not enabled on this instance' }) + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Live is not enabled on this instance' + }) } if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Saving live replay is not allowed instance' }) + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Saving live replay is not allowed instance' + }) } if (req.body.permanentLive && req.body.saveReplay) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: 'Cannot set this live as permanent while saving its replay' }) + return res.fail({ message: 'Cannot set this live as permanent while saving its replay' }) } const user = res.locals.oauth.token.User @@ -93,11 +101,11 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([ if (totalInstanceLives >= CONFIG.LIVE.MAX_INSTANCE_LIVES) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.FORBIDDEN_403) - .json({ - code: ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED, - error: 'Cannot create this live because the max instance lives limit is reached.' - }) + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot create this live because the max instance lives limit is reached.', + type: ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED.toString() + }) } } @@ -107,11 +115,11 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([ if (totalUserLives >= CONFIG.LIVE.MAX_USER_LIVES) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.FORBIDDEN_403) - .json({ - code: ServerErrorCode.MAX_USER_LIVES_LIMIT_REACHED, - error: 'Cannot create this live because the max user lives limit is reached.' - }) + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + type: ServerErrorCode.MAX_USER_LIVES_LIMIT_REACHED.toString(), + message: 'Cannot create this live because the max user lives limit is reached.' + }) } } @@ -133,18 +141,18 @@ const videoLiveUpdateValidator = [ if (areValidationErrors(req, res)) return if (req.body.permanentLive && req.body.saveReplay) { - return res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: 'Cannot set this live as permanent while saving its replay' }) + return res.fail({ message: 'Cannot set this live as permanent while saving its replay' }) } if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) { - return res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Saving live replay is not allowed instance' }) + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Saving live replay is not allowed instance' + }) } if (res.locals.videoAll.state !== VideoState.WAITING_FOR_LIVE) { - return res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: 'Cannot update a live that has already started' }) + return res.fail({ message: 'Cannot update a live that has already started' }) } // Check the user can manage the live @@ -180,9 +188,10 @@ async function isLiveVideoAccepted (req: express.Request, res: express.Response) if (!acceptedResult || acceptedResult.accepted !== true) { logger.info('Refused local live video.', { acceptedResult, acceptParameters }) - res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: acceptedResult.errorMessage || 'Refused local live video' }) - + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: acceptedResult.errorMessage || 'Refused local live video' + }) return false } diff --git a/server/middlewares/validators/videos/video-playlists.ts b/server/middlewares/validators/videos/video-playlists.ts index c872d045e..90815dd3a 100644 --- a/server/middlewares/validators/videos/video-playlists.ts +++ b/server/middlewares/validators/videos/video-playlists.ts @@ -46,8 +46,8 @@ const videoPlaylistsAddValidator = getCommonPlaylistEditAttributes().concat([ if (body.privacy === VideoPlaylistPrivacy.PUBLIC && !body.videoChannelId) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: 'Cannot set "public" a playlist that is not assigned to a channel.' }) + + return res.fail({ message: 'Cannot set "public" a playlist that is not assigned to a channel.' }) } return next() @@ -85,14 +85,14 @@ const videoPlaylistsUpdateValidator = getCommonPlaylistEditAttributes().concat([ ) ) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: 'Cannot set "public" a playlist that is not assigned to a channel.' }) + + return res.fail({ message: 'Cannot set "public" a playlist that is not assigned to a channel.' }) } if (videoPlaylist.type === VideoPlaylistType.WATCH_LATER) { cleanUpReqFiles(req) - return res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: 'Cannot update a watch later playlist.' }) + + return res.fail({ message: 'Cannot update a watch later playlist.' }) } if (body.videoChannelId && !await doesVideoChannelIdExist(body.videoChannelId, res)) return cleanUpReqFiles(req) @@ -114,8 +114,7 @@ const videoPlaylistsDeleteValidator = [ const videoPlaylist = getPlaylist(res) if (videoPlaylist.type === VideoPlaylistType.WATCH_LATER) { - return res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: 'Cannot delete a watch later playlist.' }) + return res.fail({ message: 'Cannot delete a watch later playlist.' }) } if (!checkUserCanManageVideoPlaylist(res.locals.oauth.token.User, videoPlaylist, UserRight.REMOVE_ANY_VIDEO_PLAYLIST, res)) { @@ -144,7 +143,10 @@ const videoPlaylistsGetValidator = (fetchType: VideoPlaylistFetchType) => { if (videoPlaylist.privacy === VideoPlaylistPrivacy.UNLISTED) { if (isUUIDValid(req.params.playlistId)) return next() - return res.status(HttpStatusCode.NOT_FOUND_404).end() + return res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Playlist not found' + }) } if (videoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) { @@ -156,8 +158,10 @@ const videoPlaylistsGetValidator = (fetchType: VideoPlaylistFetchType) => { !user || (videoPlaylist.OwnerAccount.id !== user.Account.id && !user.hasRight(UserRight.UPDATE_ANY_VIDEO_PLAYLIST)) ) { - return res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Cannot get this private video playlist.' }) + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot get this private video playlist.' + }) } return next() @@ -233,10 +237,10 @@ const videoPlaylistsUpdateOrRemoveVideoValidator = [ const videoPlaylistElement = await VideoPlaylistElementModel.loadById(req.params.playlistElementId) if (!videoPlaylistElement) { - res.status(HttpStatusCode.NOT_FOUND_404) - .json({ error: 'Video playlist element not found' }) - .end() - + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video playlist element not found' + }) return } res.locals.videoPlaylistElement = videoPlaylistElement @@ -263,15 +267,18 @@ const videoPlaylistElementAPGetValidator = [ const videoPlaylistElement = await VideoPlaylistElementModel.loadByPlaylistAndElementIdForAP(playlistId, playlistElementId) if (!videoPlaylistElement) { - res.status(HttpStatusCode.NOT_FOUND_404) - .json({ error: 'Video playlist element not found' }) - .end() - + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video playlist element not found' + }) return } if (videoPlaylistElement.VideoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) { - return res.status(HttpStatusCode.FORBIDDEN_403).end() + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot get this private video playlist.' + }) } res.locals.videoPlaylistElementAP = videoPlaylistElement @@ -307,18 +314,12 @@ const videoPlaylistsReorderVideosValidator = [ const reorderLength: number = req.body.reorderLength if (startPosition >= nextPosition || insertAfterPosition >= nextPosition) { - res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: `Start position or insert after position exceed the playlist limits (max: ${nextPosition - 1})` }) - .end() - + res.fail({ message: `Start position or insert after position exceed the playlist limits (max: ${nextPosition - 1})` }) return } if (reorderLength && reorderLength + startPosition > nextPosition) { - res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: `Reorder length with this start position exceeds the playlist limits (max: ${nextPosition - startPosition})` }) - .end() - + res.fail({ message: `Reorder length with this start position exceeds the playlist limits (max: ${nextPosition - startPosition})` }) return } @@ -401,10 +402,10 @@ function getCommonPlaylistEditAttributes () { function checkUserCanManageVideoPlaylist (user: MUserAccountId, videoPlaylist: MVideoPlaylist, right: UserRight, res: express.Response) { if (videoPlaylist.isOwned() === false) { - res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Cannot manage video playlist of another server.' }) - .end() - + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot manage video playlist of another server.' + }) return false } @@ -412,10 +413,10 @@ function checkUserCanManageVideoPlaylist (user: MUserAccountId, videoPlaylist: M // The user can delete it if s/he is an admin // Or if s/he is the video playlist's owner if (user.hasRight(right) === false && videoPlaylist.ownerAccountId !== user.Account.id) { - res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Cannot manage video playlist of another user' }) - .end() - + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot manage video playlist of another user' + }) return false } diff --git a/server/middlewares/validators/videos/video-rates.ts b/server/middlewares/validators/videos/video-rates.ts index 01bdef25f..5c4176f54 100644 --- a/server/middlewares/validators/videos/video-rates.ts +++ b/server/middlewares/validators/videos/video-rates.ts @@ -37,8 +37,10 @@ const getAccountVideoRateValidatorFactory = function (rateType: VideoRateType) { const rate = await AccountVideoRateModel.loadLocalAndPopulateVideo(rateType, req.params.name, +req.params.videoId) if (!rate) { - return res.status(HttpStatusCode.NOT_FOUND_404) - .json({ error: 'Video rate not found' }) + return res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video rate not found' + }) } res.locals.accountVideoRate = rate diff --git a/server/middlewares/validators/videos/video-watch.ts b/server/middlewares/validators/videos/video-watch.ts index 29ce0dab6..00c739d31 100644 --- a/server/middlewares/validators/videos/video-watch.ts +++ b/server/middlewares/validators/videos/video-watch.ts @@ -21,7 +21,10 @@ const videoWatchingValidator = [ const user = res.locals.oauth.token.User if (user.videosHistoryEnabled === false) { logger.warn('Cannot set videos to watch by user %d: videos history is disabled.', user.id) - return res.status(HttpStatusCode.CONFLICT_409).end() + return res.fail({ + status: HttpStatusCode.CONFLICT_409, + message: 'Video history is disabled' + }) } return next() diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts index 8864be269..dfd472400 100644 --- a/server/middlewares/validators/videos/videos.ts +++ b/server/middlewares/validators/videos/videos.ts @@ -73,6 +73,7 @@ const videosAddLegacyValidator = getCommonVideoEditAttributes().concat([ .custom(isIdValid).withMessage('Should have correct video channel id'), async (req: express.Request, res: express.Response, next: express.NextFunction) => { + res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadLegacy" logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) if (areValidationErrors(req, res)) return cleanUpReqFiles(req) @@ -88,9 +89,11 @@ const videosAddLegacyValidator = getCommonVideoEditAttributes().concat([ if (!videoFile.duration) await addDurationToVideo(videoFile) } catch (err) { logger.error('Invalid input file in videosAddLegacyValidator.', { err }) - res.status(HttpStatusCode.UNPROCESSABLE_ENTITY_422) - .json({ error: 'Video file unreadable.' }) + res.fail({ + status: HttpStatusCode.UNPROCESSABLE_ENTITY_422, + message: 'Video file unreadable.' + }) return cleanUpReqFiles(req) } @@ -105,6 +108,7 @@ const videosAddLegacyValidator = getCommonVideoEditAttributes().concat([ */ const videosAddResumableValidator = [ async (req: express.Request, res: express.Response, next: express.NextFunction) => { + res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadResumable" const user = res.locals.oauth.token.User const body: express.CustomUploadXFile = req.body @@ -118,9 +122,11 @@ const videosAddResumableValidator = [ if (!file.duration) await addDurationToVideo(file) } catch (err) { logger.error('Invalid input file in videosAddResumableValidator.', { err }) - res.status(HttpStatusCode.UNPROCESSABLE_ENTITY_422) - .json({ error: 'Video file unreadable.' }) + res.fail({ + status: HttpStatusCode.UNPROCESSABLE_ENTITY_422, + message: 'Video file unreadable.' + }) return cleanup() } @@ -164,6 +170,7 @@ const videosAddResumableInitValidator = getCommonVideoEditAttributes().concat([ .withMessage('Should specify the file mimetype'), async (req: express.Request, res: express.Response, next: express.NextFunction) => { + res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadResumableInit" const videoFileMetadata = { mimetype: req.headers['x-upload-content-type'] as string, size: +req.headers['x-upload-content-length'], @@ -207,6 +214,7 @@ const videosUpdateValidator = getCommonVideoEditAttributes().concat([ .custom(isIdValid).withMessage('Should have correct video channel id'), async (req: express.Request, res: express.Response, next: express.NextFunction) => { + res.docs = 'https://docs.joinpeertube.org/api-rest-reference.html#operation/putVideo' logger.debug('Checking videosUpdate parameters', { parameters: req.body }) if (areValidationErrors(req, res)) return cleanUpReqFiles(req) @@ -242,12 +250,14 @@ async function checkVideoFollowConstraints (req: express.Request, res: express.R const serverActor = await getServerActor() if (await VideoModel.checkVideoHasInstanceFollow(video.id, serverActor.id) === true) return next() - return res.status(HttpStatusCode.FORBIDDEN_403) - .json({ - errorCode: ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS, - error: 'Cannot get this video regarding follow constraints.', - originUrl: video.url - }) + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot get this video regarding follow constraints.', + type: ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS.toString(), + data: { + originUrl: video.url + } + }) } const videosCustomGetValidator = ( @@ -258,6 +268,7 @@ const videosCustomGetValidator = ( param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), async (req: express.Request, res: express.Response, next: express.NextFunction) => { + res.docs = 'https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo' logger.debug('Checking videosGet parameters', { parameters: req.params }) if (areValidationErrors(req, res)) return @@ -276,8 +287,10 @@ const videosCustomGetValidator = ( // Only the owner or a user that have blacklist rights can see the video if (!user || !user.canGetVideo(video)) { - return res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Cannot get this private/internal or blacklisted video.' }) + return res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot get this private/internal or blacklisted video.' + }) } return next() @@ -291,7 +304,10 @@ const videosCustomGetValidator = ( if (isUUIDValid(req.params.id)) return next() // Don't leak this unlisted video - return res.status(HttpStatusCode.NOT_FOUND_404).end() + return res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video not found' + }) } } ] @@ -318,6 +334,7 @@ const videosRemoveValidator = [ param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), async (req: express.Request, res: express.Response, next: express.NextFunction) => { + res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/delVideo" logger.debug('Checking videosRemove parameters', { parameters: req.params }) if (areValidationErrors(req, res)) return @@ -344,13 +361,11 @@ const videosChangeOwnershipValidator = [ const nextOwner = await AccountModel.loadLocalByName(req.body.username) if (!nextOwner) { - res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: 'Changing video ownership to a remote account is not supported yet' }) - + res.fail({ message: 'Changing video ownership to a remote account is not supported yet' }) return } - res.locals.nextOwner = nextOwner + res.locals.nextOwner = nextOwner return next() } ] @@ -370,8 +385,10 @@ const videosTerminateChangeOwnershipValidator = [ const videoChangeOwnership = res.locals.videoChangeOwnership if (videoChangeOwnership.status !== VideoChangeOwnershipStatus.WAITING) { - res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: 'Ownership already accepted or refused' }) + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Ownership already accepted or refused' + }) return } @@ -388,9 +405,10 @@ const videosAcceptChangeOwnershipValidator = [ const videoChangeOwnership = res.locals.videoChangeOwnership const isAble = await isAbleToUploadVideo(user.id, videoChangeOwnership.Video.getMaxQualityFile().size) if (isAble === false) { - res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413) - .json({ error: 'The user video quota is exceeded with this video.' }) - + res.fail({ + status: HttpStatusCode.PAYLOAD_TOO_LARGE_413, + message: 'The user video quota is exceeded with this video.' + }) return } @@ -538,9 +556,10 @@ const commonVideosFiltersValidator = [ (req.query.filter === 'all-local' || req.query.filter === 'all') && (!user || user.hasRight(UserRight.SEE_ALL_VIDEOS) === false) ) { - res.status(HttpStatusCode.UNAUTHORIZED_401) - .json({ error: 'You are not allowed to see all local videos.' }) - + res.fail({ + status: HttpStatusCode.UNAUTHORIZED_401, + message: 'You are not allowed to see all local videos.' + }) return } @@ -581,9 +600,7 @@ function areErrorsInScheduleUpdate (req: express.Request, res: express.Response) if (!req.body.scheduleUpdate.updateAt) { logger.warn('Invalid parameters: scheduleUpdate.updateAt is mandatory.') - res.status(HttpStatusCode.BAD_REQUEST_400) - .json({ error: 'Schedule update at is mandatory.' }) - + res.fail({ message: 'Schedule update at is mandatory.' }) return true } } @@ -605,26 +622,27 @@ async function commonVideoChecksPass (parameters: { if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return false if (!isVideoFileMimeTypeValid(files)) { - res.status(HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415) - .json({ - error: 'This file is not supported. Please, make sure it is of the following type: ' + - CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') - }) - + res.fail({ + status: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415, + message: 'This file is not supported. Please, make sure it is of the following type: ' + + CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') + }) return false } if (!isVideoFileSizeValid(videoFileSize.toString())) { - res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413) - .json({ error: 'This file is too large. It exceeds the maximum file size authorized.' }) - + res.fail({ + status: HttpStatusCode.PAYLOAD_TOO_LARGE_413, + message: 'This file is too large. It exceeds the maximum file size authorized.' + }) return false } if (await isAbleToUploadVideo(user.id, videoFileSize) === false) { - res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413) - .json({ error: 'The user video quota is exceeded with this video.' }) - + res.fail({ + status: HttpStatusCode.PAYLOAD_TOO_LARGE_413, + message: 'The user video quota is exceeded with this video.' + }) return false } @@ -650,9 +668,10 @@ export async function isVideoAccepted ( if (!acceptedResult || acceptedResult.accepted !== true) { logger.info('Refused local video.', { acceptedResult, acceptParameters }) - res.status(HttpStatusCode.FORBIDDEN_403) - .json({ error: acceptedResult.errorMessage || 'Refused local video' }) - + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: acceptedResult.errorMessage || 'Refused local video' + }) return false } -- cgit v1.2.3