]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/middlewares/validators/videos/video-comments.ts
Live streaming implementation first step
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / videos / video-comments.ts
CommitLineData
bf1f6508 1import * as express from 'express'
c8861d5d 2import { body, param } from 'express-validator'
26d6bf65 3import { MUserAccountUrl } from '@server/types/models'
6e46de09
C
4import { UserRight } from '../../../../shared'
5import { isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc'
57f6896f
C
6import {
7 doesVideoCommentExist,
8 doesVideoCommentThreadExist,
9 isValidVideoCommentText
10} from '../../../helpers/custom-validators/video-comments'
6e46de09 11import { logger } from '../../../helpers/logger'
ceba0e65
C
12import { doesVideoExist } from '../../../helpers/middlewares'
13import { AcceptResult, isLocalVideoCommentReplyAccepted, isLocalVideoThreadAccepted } from '../../../lib/moderation'
14import { Hooks } from '../../../lib/plugins/hooks'
57f6896f 15import { MCommentOwnerVideoReply, MVideo, MVideoFullLight } from '../../../types/models/video'
6e46de09 16import { areValidationErrors } from '../utils'
bf1f6508
C
17
18const listVideoCommentThreadsValidator = [
19 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
20
21 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
d3ea8975 22 logger.debug('Checking listVideoCommentThreads parameters.', { parameters: req.params })
bf1f6508
C
23
24 if (areValidationErrors(req, res)) return
0f6acda1 25 if (!await doesVideoExist(req.params.videoId, res, 'only-video')) return
bf1f6508
C
26
27 return next()
28 }
29]
30
31const listVideoThreadCommentsValidator = [
32 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
33 param('threadId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid threadId'),
34
35 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
d3ea8975 36 logger.debug('Checking listVideoThreadComments parameters.', { parameters: req.params })
bf1f6508
C
37
38 if (areValidationErrors(req, res)) return
0f6acda1 39 if (!await doesVideoExist(req.params.videoId, res, 'only-video')) return
453e83ea 40 if (!await doesVideoCommentThreadExist(req.params.threadId, res.locals.onlyVideo, res)) return
bf1f6508
C
41
42 return next()
43 }
44]
45
46const addVideoCommentThreadValidator = [
47 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
48 body('text').custom(isValidVideoCommentText).not().isEmpty().withMessage('Should have a valid comment text'),
49
50 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
5de8a55a 51 logger.debug('Checking addVideoCommentThread parameters.', { parameters: req.params, body: req.body })
bf1f6508
C
52
53 if (areValidationErrors(req, res)) return
0f6acda1 54 if (!await doesVideoExist(req.params.videoId, res)) return
453e83ea 55 if (!isVideoCommentsEnabled(res.locals.videoAll, res)) return
a1587156 56 if (!await isVideoCommentAccepted(req, res, res.locals.videoAll, false)) return
bf1f6508
C
57
58 return next()
59 }
60]
61
62const addVideoCommentReplyValidator = [
63 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
64 param('commentId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid commentId'),
65 body('text').custom(isValidVideoCommentText).not().isEmpty().withMessage('Should have a valid comment text'),
66
67 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
5de8a55a 68 logger.debug('Checking addVideoCommentReply parameters.', { parameters: req.params, body: req.body })
bf1f6508
C
69
70 if (areValidationErrors(req, res)) return
0f6acda1 71 if (!await doesVideoExist(req.params.videoId, res)) return
453e83ea
C
72 if (!isVideoCommentsEnabled(res.locals.videoAll, res)) return
73 if (!await doesVideoCommentExist(req.params.commentId, res.locals.videoAll, res)) return
74 if (!await isVideoCommentAccepted(req, res, res.locals.videoAll, true)) return
bf1f6508
C
75
76 return next()
77 }
78]
79
da854ddd
C
80const videoCommentGetValidator = [
81 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
82 param('commentId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid commentId'),
83
84 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
85 logger.debug('Checking videoCommentGetValidator parameters.', { parameters: req.params })
86
87 if (areValidationErrors(req, res)) return
0f6acda1 88 if (!await doesVideoExist(req.params.videoId, res, 'id')) return
453e83ea 89 if (!await doesVideoCommentExist(req.params.commentId, res.locals.videoId, res)) return
da854ddd
C
90
91 return next()
92 }
93]
94
4cb6d457
C
95const removeVideoCommentValidator = [
96 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
97 param('commentId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid commentId'),
98
99 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
100 logger.debug('Checking removeVideoCommentValidator parameters.', { parameters: req.params })
101
102 if (areValidationErrors(req, res)) return
0f6acda1 103 if (!await doesVideoExist(req.params.videoId, res)) return
453e83ea 104 if (!await doesVideoCommentExist(req.params.commentId, res.locals.videoAll, res)) return
4cb6d457
C
105
106 // Check if the user who did the request is able to delete the video
453e83ea 107 if (!checkUserCanDeleteVideoComment(res.locals.oauth.token.User, res.locals.videoCommentFull, res)) return
4cb6d457
C
108
109 return next()
110 }
111]
112
bf1f6508
C
113// ---------------------------------------------------------------------------
114
115export {
116 listVideoCommentThreadsValidator,
117 listVideoThreadCommentsValidator,
118 addVideoCommentThreadValidator,
da854ddd 119 addVideoCommentReplyValidator,
4cb6d457
C
120 videoCommentGetValidator,
121 removeVideoCommentValidator
bf1f6508
C
122}
123
124// ---------------------------------------------------------------------------
125
453e83ea 126function isVideoCommentsEnabled (video: MVideo, res: express.Response) {
47564bbe
C
127 if (video.commentsEnabled !== true) {
128 res.status(409)
129 .json({ error: 'Video comments are disabled for this video.' })
47564bbe
C
130
131 return false
132 }
133
134 return true
135}
4cb6d457 136
fde37dc9 137function checkUserCanDeleteVideoComment (user: MUserAccountUrl, videoComment: MCommentOwnerVideoReply, res: express.Response) {
c883db6d
C
138 if (videoComment.isDeleted()) {
139 res.status(409)
140 .json({ error: 'This comment is already deleted' })
57f6896f 141
c883db6d
C
142 return false
143 }
144
fde37dc9
C
145 const userAccount = user.Account
146
147 if (
148 user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) === false && // Not a moderator
149 videoComment.accountId !== userAccount.id && // Not the comment owner
150 videoComment.Video.VideoChannel.accountId !== userAccount.id // Not the video owner
151 ) {
4cb6d457
C
152 res.status(403)
153 .json({ error: 'Cannot remove video comment of another user' })
fde37dc9 154
4cb6d457
C
155 return false
156 }
157
158 return true
159}
b4055e1c 160
453e83ea 161async function isVideoCommentAccepted (req: express.Request, res: express.Response, video: MVideoFullLight, isReply: boolean) {
b4055e1c 162 const acceptParameters = {
453e83ea 163 video,
b4055e1c
C
164 commentBody: req.body,
165 user: res.locals.oauth.token.User
166 }
167
168 let acceptedResult: AcceptResult
169
170 if (isReply) {
453e83ea 171 const acceptReplyParameters = Object.assign(acceptParameters, { parentComment: res.locals.videoCommentFull })
b4055e1c 172
6691c522
C
173 acceptedResult = await Hooks.wrapFun(
174 isLocalVideoCommentReplyAccepted,
175 acceptReplyParameters,
b4055e1c
C
176 'filter:api.video-comment-reply.create.accept.result'
177 )
178 } else {
6691c522
C
179 acceptedResult = await Hooks.wrapFun(
180 isLocalVideoThreadAccepted,
181 acceptParameters,
b4055e1c
C
182 'filter:api.video-thread.create.accept.result'
183 )
184 }
185
186 if (!acceptedResult || acceptedResult.accepted !== true) {
187 logger.info('Refused local comment.', { acceptedResult, acceptParameters })
188 res.status(403)
57f6896f 189 .json({ error: acceptedResult.errorMessage || 'Refused local comment' })
b4055e1c
C
190
191 return false
192 }
193
194 return true
195}