]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/middlewares/validators/feeds.ts
Feature/Add replay privacy (#5692)
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / feeds.ts
CommitLineData
41fb13c3 1import express from 'express'
c8861d5d 2import { param, query } from 'express-validator'
c0e8b12e 3import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
244e76a5 4import { isValidRSSFeed } from '../../helpers/custom-validators/feeds'
d4a8e7a6 5import { exists, isIdOrUUIDValid, isIdValid, toCompleteUUID } from '../../helpers/custom-validators/misc'
3e753302 6import {
10363c74 7 areValidationErrors,
ff9d43f6 8 checkCanSeeVideo,
3e753302
C
9 doesAccountIdExist,
10 doesAccountNameWithHostExist,
18490b07 11 doesUserFeedTokenCorrespond,
3e753302 12 doesVideoChannelIdExist,
10363c74
C
13 doesVideoChannelNameWithHostExist,
14 doesVideoExist
15} from './shared'
244e76a5 16
f2f0eda5 17const feedsFormatValidator = [
396f6f01
C
18 param('format')
19 .optional()
20 .custom(isValidRSSFeed).withMessage('Should have a valid format (rss, atom, json)'),
21 query('format')
22 .optional()
23 .custom(isValidRSSFeed).withMessage('Should have a valid format (rss, atom, json)'),
24
25 (req: express.Request, res: express.Response, next: express.NextFunction) => {
396f6f01
C
26 if (areValidationErrors(req, res)) return
27
28 return next()
29 }
f2f0eda5
RK
30]
31
32function setFeedFormatContentType (req: express.Request, res: express.Response, next: express.NextFunction) {
33 const format = req.query.format || req.params.format || 'rss'
34
35 let acceptableContentTypes: string[]
36 if (format === 'atom' || format === 'atom1') {
a1587156 37 acceptableContentTypes = [ 'application/atom+xml', 'application/xml', 'text/xml' ]
f2f0eda5 38 } else if (format === 'json' || format === 'json1') {
a1587156 39 acceptableContentTypes = [ 'application/json' ]
f2f0eda5 40 } else if (format === 'rss' || format === 'rss2') {
a1587156 41 acceptableContentTypes = [ 'application/rss+xml', 'application/xml', 'text/xml' ]
f2f0eda5 42 } else {
a1587156 43 acceptableContentTypes = [ 'application/xml', 'text/xml' ]
f2f0eda5
RK
44 }
45
46 if (req.accepts(acceptableContentTypes)) {
47 res.set('Content-Type', req.accepts(acceptableContentTypes) as string)
48 } else {
76148b27
RK
49 return res.fail({
50 status: HttpStatusCode.NOT_ACCEPTABLE_406,
51 message: `You should accept at least one of the following content-types: ${acceptableContentTypes.join(', ')}`
52 })
f2f0eda5
RK
53 }
54
55 return next()
56}
57
58const videoFeedsValidator = [
18490b07
C
59 query('accountId')
60 .optional()
396f6f01 61 .custom(isIdValid),
18490b07
C
62
63 query('accountName')
64 .optional(),
65
66 query('videoChannelId')
67 .optional()
396f6f01 68 .custom(isIdValid),
18490b07
C
69
70 query('videoChannelName')
71 .optional(),
244e76a5
RK
72
73 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
244e76a5
RK
74 if (areValidationErrors(req, res)) return
75
0f6acda1
C
76 if (req.query.accountId && !await doesAccountIdExist(req.query.accountId, res)) return
77 if (req.query.videoChannelId && !await doesVideoChannelIdExist(req.query.videoChannelId, res)) return
78 if (req.query.accountName && !await doesAccountNameWithHostExist(req.query.accountName, res)) return
79 if (req.query.videoChannelName && !await doesVideoChannelNameWithHostExist(req.query.videoChannelName, res)) return
244e76a5
RK
80
81 return next()
82 }
83]
84
18490b07
C
85const videoSubscriptionFeedsValidator = [
86 query('accountId')
396f6f01 87 .custom(isIdValid),
18490b07
C
88
89 query('token')
396f6f01 90 .custom(exists),
afff310e
RK
91
92 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
afff310e
RK
93 if (areValidationErrors(req, res)) return
94
18490b07
C
95 if (!await doesAccountIdExist(req.query.accountId, res)) return
96 if (!await doesUserFeedTokenCorrespond(res.locals.account.userId, req.query.token, res)) return
afff310e
RK
97
98 return next()
99 }
100]
101
fe3a55b0 102const videoCommentsFeedsValidator = [
d4a8e7a6 103 query('videoId')
d4a8e7a6 104 .optional()
396f6f01 105 .customSanitizer(toCompleteUUID)
d4a8e7a6 106 .custom(isIdOrUUIDValid),
fe3a55b0
C
107
108 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
fe3a55b0
C
109 if (areValidationErrors(req, res)) return
110
00494d6e 111 if (req.query.videoId && (req.query.videoChannelId || req.query.videoChannelName)) {
76148b27 112 return res.fail({ message: 'videoId cannot be mixed with a channel filter' })
00494d6e
RK
113 }
114
ff9d43f6
C
115 if (req.query.videoId) {
116 if (!await doesVideoExist(req.query.videoId, res)) return
117 if (!await checkCanSeeVideo({ req, res, paramId: req.query.videoId, video: res.locals.videoAll })) return
118 }
fe3a55b0
C
119
120 return next()
121 }
122]
123
244e76a5
RK
124// ---------------------------------------------------------------------------
125
126export {
f2f0eda5
RK
127 feedsFormatValidator,
128 setFeedFormatContentType,
fe3a55b0 129 videoFeedsValidator,
18490b07 130 videoSubscriptionFeedsValidator,
fe3a55b0 131 videoCommentsFeedsValidator
244e76a5 132}