]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/middlewares/validators/videos/video-channels.ts
fix plugin storage return value when storing a Json array
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / videos / video-channels.ts
1 import express from 'express'
2 import { body, param, query } from 'express-validator'
3 import { CONFIG } from '@server/initializers/config'
4 import { MChannelAccountDefault } from '@server/types/models'
5 import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
6 import { isBooleanValid, toBooleanOrNull } from '../../../helpers/custom-validators/misc'
7 import {
8 isVideoChannelDescriptionValid,
9 isVideoChannelDisplayNameValid,
10 isVideoChannelSupportValid,
11 isVideoChannelUsernameValid
12 } from '../../../helpers/custom-validators/video-channels'
13 import { logger } from '../../../helpers/logger'
14 import { ActorModel } from '../../../models/actor/actor'
15 import { VideoChannelModel } from '../../../models/video/video-channel'
16 import { areValidationErrors, doesVideoChannelNameWithHostExist } from '../shared'
17
18 const videoChannelsAddValidator = [
19 body('name').custom(isVideoChannelUsernameValid).withMessage('Should have a valid channel name'),
20 body('displayName').custom(isVideoChannelDisplayNameValid).withMessage('Should have a valid display name'),
21 body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
22 body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
23
24 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
25 logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body })
26
27 if (areValidationErrors(req, res)) return
28
29 const actor = await ActorModel.loadLocalByName(req.body.name)
30 if (actor) {
31 res.fail({
32 status: HttpStatusCode.CONFLICT_409,
33 message: 'Another actor (account/channel) with this name on this instance already exists or has already existed.'
34 })
35 return false
36 }
37
38 const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id)
39 if (count >= CONFIG.VIDEO_CHANNELS.MAX_PER_USER) {
40 res.fail({ message: `You cannot create more than ${CONFIG.VIDEO_CHANNELS.MAX_PER_USER} channels` })
41 return false
42 }
43
44 return next()
45 }
46 ]
47
48 const videoChannelsUpdateValidator = [
49 param('nameWithHost').exists().withMessage('Should have an video channel name with host'),
50 body('displayName')
51 .optional()
52 .custom(isVideoChannelDisplayNameValid).withMessage('Should have a valid display name'),
53 body('description')
54 .optional()
55 .custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
56 body('support')
57 .optional()
58 .custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
59 body('bulkVideosSupportUpdate')
60 .optional()
61 .custom(isBooleanValid).withMessage('Should have a valid bulkVideosSupportUpdate boolean field'),
62
63 (req: express.Request, res: express.Response, next: express.NextFunction) => {
64 logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body })
65
66 if (areValidationErrors(req, res)) return
67
68 return next()
69 }
70 ]
71
72 const videoChannelsRemoveValidator = [
73 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
74 logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params })
75
76 if (!await checkVideoChannelIsNotTheLastOne(res.locals.videoChannel, res)) return
77
78 return next()
79 }
80 ]
81
82 const videoChannelsNameWithHostValidator = [
83 param('nameWithHost').exists().withMessage('Should have an video channel name with host'),
84
85 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
86 logger.debug('Checking videoChannelsNameWithHostValidator parameters', { parameters: req.params })
87
88 if (areValidationErrors(req, res)) return
89
90 if (!await doesVideoChannelNameWithHostExist(req.params.nameWithHost, res)) return
91
92 return next()
93 }
94 ]
95
96 const ensureIsLocalChannel = [
97 (req: express.Request, res: express.Response, next: express.NextFunction) => {
98 if (res.locals.videoChannel.Actor.isOwned() === false) {
99 return res.fail({
100 status: HttpStatusCode.FORBIDDEN_403,
101 message: 'This channel is not owned.'
102 })
103 }
104
105 return next()
106 }
107 ]
108
109 const videoChannelStatsValidator = [
110 query('withStats')
111 .optional()
112 .customSanitizer(toBooleanOrNull)
113 .custom(isBooleanValid).withMessage('Should have a valid stats flag'),
114
115 (req: express.Request, res: express.Response, next: express.NextFunction) => {
116 if (areValidationErrors(req, res)) return
117 return next()
118 }
119 ]
120
121 const videoChannelsListValidator = [
122 query('search').optional().not().isEmpty().withMessage('Should have a valid search'),
123
124 (req: express.Request, res: express.Response, next: express.NextFunction) => {
125 logger.debug('Checking video channels search query', { parameters: req.query })
126
127 if (areValidationErrors(req, res)) return
128
129 return next()
130 }
131 ]
132
133 // ---------------------------------------------------------------------------
134
135 export {
136 videoChannelsAddValidator,
137 videoChannelsUpdateValidator,
138 videoChannelsRemoveValidator,
139 videoChannelsNameWithHostValidator,
140 ensureIsLocalChannel,
141 videoChannelsListValidator,
142 videoChannelStatsValidator
143 }
144
145 // ---------------------------------------------------------------------------
146
147 async function checkVideoChannelIsNotTheLastOne (videoChannel: MChannelAccountDefault, res: express.Response) {
148 const count = await VideoChannelModel.countByAccount(videoChannel.Account.id)
149
150 if (count <= 1) {
151 res.fail({
152 status: HttpStatusCode.CONFLICT_409,
153 message: 'Cannot remove the last channel of this user'
154 })
155 return false
156 }
157
158 return true
159 }