aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/middlewares/validators/videos/video-comments.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/middlewares/validators/videos/video-comments.ts')
-rw-r--r--server/middlewares/validators/videos/video-comments.ts249
1 files changed, 0 insertions, 249 deletions
diff --git a/server/middlewares/validators/videos/video-comments.ts b/server/middlewares/validators/videos/video-comments.ts
deleted file mode 100644
index 70689b02e..000000000
--- a/server/middlewares/validators/videos/video-comments.ts
+++ /dev/null
@@ -1,249 +0,0 @@
1import express from 'express'
2import { body, param, query } from 'express-validator'
3import { MUserAccountUrl } from '@server/types/models'
4import { HttpStatusCode, UserRight } from '@shared/models'
5import { exists, isBooleanValid, isIdValid, toBooleanOrNull } from '../../../helpers/custom-validators/misc'
6import { isValidVideoCommentText } from '../../../helpers/custom-validators/video-comments'
7import { logger } from '../../../helpers/logger'
8import { AcceptResult, isLocalVideoCommentReplyAccepted, isLocalVideoThreadAccepted } from '../../../lib/moderation'
9import { Hooks } from '../../../lib/plugins/hooks'
10import { MCommentOwnerVideoReply, MVideo, MVideoFullLight } from '../../../types/models/video'
11import {
12 areValidationErrors,
13 checkCanSeeVideo,
14 doesVideoCommentExist,
15 doesVideoCommentThreadExist,
16 doesVideoExist,
17 isValidVideoIdParam,
18 isValidVideoPasswordHeader
19} from '../shared'
20
21const listVideoCommentsValidator = [
22 query('isLocal')
23 .optional()
24 .customSanitizer(toBooleanOrNull)
25 .custom(isBooleanValid)
26 .withMessage('Should have a valid isLocal boolean'),
27
28 query('onLocalVideo')
29 .optional()
30 .customSanitizer(toBooleanOrNull)
31 .custom(isBooleanValid)
32 .withMessage('Should have a valid onLocalVideo boolean'),
33
34 query('search')
35 .optional()
36 .custom(exists),
37
38 query('searchAccount')
39 .optional()
40 .custom(exists),
41
42 query('searchVideo')
43 .optional()
44 .custom(exists),
45
46 (req: express.Request, res: express.Response, next: express.NextFunction) => {
47 if (areValidationErrors(req, res)) return
48
49 return next()
50 }
51]
52
53const listVideoCommentThreadsValidator = [
54 isValidVideoIdParam('videoId'),
55 isValidVideoPasswordHeader(),
56
57 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
58 if (areValidationErrors(req, res)) return
59 if (!await doesVideoExist(req.params.videoId, res, 'only-video')) return
60
61 if (!await checkCanSeeVideo({ req, res, paramId: req.params.videoId, video: res.locals.onlyVideo })) return
62
63 return next()
64 }
65]
66
67const listVideoThreadCommentsValidator = [
68 isValidVideoIdParam('videoId'),
69
70 param('threadId')
71 .custom(isIdValid),
72 isValidVideoPasswordHeader(),
73
74 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
75 if (areValidationErrors(req, res)) return
76 if (!await doesVideoExist(req.params.videoId, res, 'only-video')) return
77 if (!await doesVideoCommentThreadExist(req.params.threadId, res.locals.onlyVideo, res)) return
78
79 if (!await checkCanSeeVideo({ req, res, paramId: req.params.videoId, video: res.locals.onlyVideo })) return
80
81 return next()
82 }
83]
84
85const addVideoCommentThreadValidator = [
86 isValidVideoIdParam('videoId'),
87
88 body('text')
89 .custom(isValidVideoCommentText),
90 isValidVideoPasswordHeader(),
91
92 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
93 if (areValidationErrors(req, res)) return
94 if (!await doesVideoExist(req.params.videoId, res)) return
95
96 if (!await checkCanSeeVideo({ req, res, paramId: req.params.videoId, video: res.locals.videoAll })) return
97
98 if (!isVideoCommentsEnabled(res.locals.videoAll, res)) return
99 if (!await isVideoCommentAccepted(req, res, res.locals.videoAll, false)) return
100
101 return next()
102 }
103]
104
105const addVideoCommentReplyValidator = [
106 isValidVideoIdParam('videoId'),
107
108 param('commentId').custom(isIdValid),
109 isValidVideoPasswordHeader(),
110
111 body('text').custom(isValidVideoCommentText),
112
113 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
114 if (areValidationErrors(req, res)) return
115 if (!await doesVideoExist(req.params.videoId, res)) return
116
117 if (!await checkCanSeeVideo({ req, res, paramId: req.params.videoId, video: res.locals.videoAll })) return
118
119 if (!isVideoCommentsEnabled(res.locals.videoAll, res)) return
120 if (!await doesVideoCommentExist(req.params.commentId, res.locals.videoAll, res)) return
121 if (!await isVideoCommentAccepted(req, res, res.locals.videoAll, true)) return
122
123 return next()
124 }
125]
126
127const videoCommentGetValidator = [
128 isValidVideoIdParam('videoId'),
129
130 param('commentId')
131 .custom(isIdValid),
132
133 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
134 if (areValidationErrors(req, res)) return
135 if (!await doesVideoExist(req.params.videoId, res, 'id')) return
136 if (!await doesVideoCommentExist(req.params.commentId, res.locals.videoId, res)) return
137
138 return next()
139 }
140]
141
142const removeVideoCommentValidator = [
143 isValidVideoIdParam('videoId'),
144
145 param('commentId')
146 .custom(isIdValid),
147
148 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
149 if (areValidationErrors(req, res)) return
150 if (!await doesVideoExist(req.params.videoId, res)) return
151 if (!await doesVideoCommentExist(req.params.commentId, res.locals.videoAll, res)) return
152
153 // Check if the user who did the request is able to delete the video
154 if (!checkUserCanDeleteVideoComment(res.locals.oauth.token.User, res.locals.videoCommentFull, res)) return
155
156 return next()
157 }
158]
159
160// ---------------------------------------------------------------------------
161
162export {
163 listVideoCommentThreadsValidator,
164 listVideoThreadCommentsValidator,
165 addVideoCommentThreadValidator,
166 listVideoCommentsValidator,
167 addVideoCommentReplyValidator,
168 videoCommentGetValidator,
169 removeVideoCommentValidator
170}
171
172// ---------------------------------------------------------------------------
173
174function isVideoCommentsEnabled (video: MVideo, res: express.Response) {
175 if (video.commentsEnabled !== true) {
176 res.fail({
177 status: HttpStatusCode.CONFLICT_409,
178 message: 'Video comments are disabled for this video.'
179 })
180 return false
181 }
182
183 return true
184}
185
186function checkUserCanDeleteVideoComment (user: MUserAccountUrl, videoComment: MCommentOwnerVideoReply, res: express.Response) {
187 if (videoComment.isDeleted()) {
188 res.fail({
189 status: HttpStatusCode.CONFLICT_409,
190 message: 'This comment is already deleted'
191 })
192 return false
193 }
194
195 const userAccount = user.Account
196
197 if (
198 user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) === false && // Not a moderator
199 videoComment.accountId !== userAccount.id && // Not the comment owner
200 videoComment.Video.VideoChannel.accountId !== userAccount.id // Not the video owner
201 ) {
202 res.fail({
203 status: HttpStatusCode.FORBIDDEN_403,
204 message: 'Cannot remove video comment of another user'
205 })
206 return false
207 }
208
209 return true
210}
211
212async function isVideoCommentAccepted (req: express.Request, res: express.Response, video: MVideoFullLight, isReply: boolean) {
213 const acceptParameters = {
214 video,
215 commentBody: req.body,
216 user: res.locals.oauth.token.User,
217 req
218 }
219
220 let acceptedResult: AcceptResult
221
222 if (isReply) {
223 const acceptReplyParameters = Object.assign(acceptParameters, { parentComment: res.locals.videoCommentFull })
224
225 acceptedResult = await Hooks.wrapFun(
226 isLocalVideoCommentReplyAccepted,
227 acceptReplyParameters,
228 'filter:api.video-comment-reply.create.accept.result'
229 )
230 } else {
231 acceptedResult = await Hooks.wrapFun(
232 isLocalVideoThreadAccepted,
233 acceptParameters,
234 'filter:api.video-thread.create.accept.result'
235 )
236 }
237
238 if (!acceptedResult || acceptedResult.accepted !== true) {
239 logger.info('Refused local comment.', { acceptedResult, acceptParameters })
240
241 res.fail({
242 status: HttpStatusCode.FORBIDDEN_403,
243 message: acceptedResult?.errorMessage || 'Comment has been rejected.'
244 })
245 return false
246 }
247
248 return true
249}