ade0b7b9fb440596e603ce63ea6167eeece07c0d
[oweals/peertube.git] / server / middlewares / validators / video-comments.ts
1 import * as express from 'express'
2 import { body, param } from 'express-validator/check'
3 import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc'
4 import { isValidVideoCommentText } from '../../helpers/custom-validators/video-comments'
5 import { isVideoExist } from '../../helpers/custom-validators/videos'
6 import { logger } from '../../helpers/logger'
7 import { VideoModel } from '../../models/video/video'
8 import { VideoCommentModel } from '../../models/video/video-comment'
9 import { areValidationErrors } from './utils'
10
11 const listVideoCommentThreadsValidator = [
12   param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
13
14   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
15     logger.debug('Checking listVideoCommentThreads parameters.', { parameters: req.params })
16
17     if (areValidationErrors(req, res)) return
18     if (!await isVideoExist(req.params.videoId, res)) return
19
20     return next()
21   }
22 ]
23
24 const listVideoThreadCommentsValidator = [
25   param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
26   param('threadId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid threadId'),
27
28   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
29     logger.debug('Checking listVideoThreadComments parameters.', { parameters: req.params })
30
31     if (areValidationErrors(req, res)) return
32     if (!await isVideoExist(req.params.videoId, res)) return
33     if (!await isVideoCommentThreadExist(req.params.threadId, res.locals.video, res)) return
34
35     return next()
36   }
37 ]
38
39 const addVideoCommentThreadValidator = [
40   param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
41   body('text').custom(isValidVideoCommentText).not().isEmpty().withMessage('Should have a valid comment text'),
42
43   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
44     logger.debug('Checking addVideoCommentThread parameters.', { parameters: req.params })
45
46     if (areValidationErrors(req, res)) return
47     if (!await isVideoExist(req.params.videoId, res)) return
48     if (!isVideoCommentsEnabled(res.locals.video, res)) return
49
50     return next()
51   }
52 ]
53
54 const addVideoCommentReplyValidator = [
55   param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
56   param('commentId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid commentId'),
57   body('text').custom(isValidVideoCommentText).not().isEmpty().withMessage('Should have a valid comment text'),
58
59   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
60     logger.debug('Checking addVideoCommentReply parameters.', { parameters: req.params })
61
62     if (areValidationErrors(req, res)) return
63     if (!await isVideoExist(req.params.videoId, res)) return
64     if (!isVideoCommentsEnabled(res.locals.video, res)) return
65     if (!await isVideoCommentExist(req.params.commentId, res.locals.video, res)) return
66
67     return next()
68   }
69 ]
70
71 const videoCommentGetValidator = [
72   param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
73   param('commentId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid commentId'),
74
75   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
76     logger.debug('Checking videoCommentGetValidator parameters.', { parameters: req.params })
77
78     if (areValidationErrors(req, res)) return
79     if (!await isVideoExist(req.params.videoId, res)) return
80     if (!await isVideoCommentExist(req.params.commentId, res.locals.video, res)) return
81
82     return next()
83   }
84 ]
85
86 // ---------------------------------------------------------------------------
87
88 export {
89   listVideoCommentThreadsValidator,
90   listVideoThreadCommentsValidator,
91   addVideoCommentThreadValidator,
92   addVideoCommentReplyValidator,
93   videoCommentGetValidator
94 }
95
96 // ---------------------------------------------------------------------------
97
98 async function isVideoCommentThreadExist (id: number, video: VideoModel, res: express.Response) {
99   const videoComment = await VideoCommentModel.loadById(id)
100
101   if (!videoComment) {
102     res.status(404)
103       .json({ error: 'Video comment thread not found' })
104       .end()
105
106     return false
107   }
108
109   if (videoComment.videoId !== video.id) {
110     res.status(400)
111       .json({ error: 'Video comment is associated to this video.' })
112       .end()
113
114     return false
115   }
116
117   if (videoComment.inReplyToCommentId !== null) {
118     res.status(400)
119       .json({ error: 'Video comment is not a thread.' })
120       .end()
121
122     return false
123   }
124
125   res.locals.videoCommentThread = videoComment
126   return true
127 }
128
129 async function isVideoCommentExist (id: number, video: VideoModel, res: express.Response) {
130   const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id)
131
132   if (!videoComment) {
133     res.status(404)
134       .json({ error: 'Video comment thread not found' })
135       .end()
136
137     return false
138   }
139
140   if (videoComment.videoId !== video.id) {
141     res.status(400)
142       .json({ error: 'Video comment is associated to this video.' })
143       .end()
144
145     return false
146   }
147
148   res.locals.videoComment = videoComment
149   return true
150 }
151
152 function isVideoCommentsEnabled (video: VideoModel, res: express.Response) {
153   if (video.commentsEnabled !== true) {
154     res.status(409)
155       .json({ error: 'Video comments are disabled for this video.' })
156       .end()
157
158     return false
159   }
160
161   return true
162 }