]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/middlewares/validators/config.ts
/!\ Use a dedicated config file for development
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / config.ts
1 import express from 'express'
2 import { body } from 'express-validator'
3 import { isIntOrNull } from '@server/helpers/custom-validators/misc'
4 import { CONFIG, isEmailEnabled } from '@server/initializers/config'
5 import { CustomConfig } from '../../../shared/models/server/custom-config.model'
6 import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
7 import { isUserNSFWPolicyValid, isUserVideoQuotaDailyValid, isUserVideoQuotaValid } from '../../helpers/custom-validators/users'
8 import { logger } from '../../helpers/logger'
9 import { isThemeRegistered } from '../../lib/plugins/theme-utils'
10 import { areValidationErrors } from './shared'
11 import { HttpStatusCode } from '@shared/models/http/http-error-codes'
12
13 const customConfigUpdateValidator = [
14 body('instance.name').exists().withMessage('Should have a valid instance name'),
15 body('instance.shortDescription').exists().withMessage('Should have a valid instance short description'),
16 body('instance.description').exists().withMessage('Should have a valid instance description'),
17 body('instance.terms').exists().withMessage('Should have a valid instance terms'),
18 body('instance.defaultNSFWPolicy').custom(isUserNSFWPolicyValid).withMessage('Should have a valid NSFW policy'),
19 body('instance.defaultClientRoute').exists().withMessage('Should have a valid instance default client route'),
20 body('instance.customizations.css').exists().withMessage('Should have a valid instance CSS customization'),
21 body('instance.customizations.javascript').exists().withMessage('Should have a valid instance JavaScript customization'),
22
23 body('services.twitter.username').exists().withMessage('Should have a valid twitter username'),
24 body('services.twitter.whitelisted').isBoolean().withMessage('Should have a valid twitter whitelisted boolean'),
25
26 body('cache.previews.size').isInt().withMessage('Should have a valid previews cache size'),
27 body('cache.captions.size').isInt().withMessage('Should have a valid captions cache size'),
28 body('cache.torrents.size').isInt().withMessage('Should have a valid torrents cache size'),
29
30 body('signup.enabled').isBoolean().withMessage('Should have a valid signup enabled boolean'),
31 body('signup.limit').isInt().withMessage('Should have a valid signup limit'),
32 body('signup.requiresEmailVerification').isBoolean().withMessage('Should have a valid requiresEmailVerification boolean'),
33 body('signup.minimumAge').isInt().withMessage("Should have a valid minimum age required"),
34
35 body('admin.email').isEmail().withMessage('Should have a valid administrator email'),
36 body('contactForm.enabled').isBoolean().withMessage('Should have a valid contact form enabled boolean'),
37
38 body('user.videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid video quota'),
39 body('user.videoQuotaDaily').custom(isUserVideoQuotaDailyValid).withMessage('Should have a valid daily video quota'),
40
41 body('videoChannels.maxPerUser').isInt().withMessage("Should have a valid maximum amount of video channels per user"),
42
43 body('transcoding.enabled').isBoolean().withMessage('Should have a valid transcoding enabled boolean'),
44 body('transcoding.allowAdditionalExtensions').isBoolean().withMessage('Should have a valid additional extensions boolean'),
45 body('transcoding.threads').isInt().withMessage('Should have a valid transcoding threads number'),
46 body('transcoding.concurrency').isInt({ min: 1 }).withMessage('Should have a valid transcoding concurrency number'),
47 body('transcoding.resolutions.0p').isBoolean().withMessage('Should have a valid transcoding 0p resolution enabled boolean'),
48 body('transcoding.resolutions.144p').isBoolean().withMessage('Should have a valid transcoding 144p resolution enabled boolean'),
49 body('transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'),
50 body('transcoding.resolutions.360p').isBoolean().withMessage('Should have a valid transcoding 360p resolution enabled boolean'),
51 body('transcoding.resolutions.480p').isBoolean().withMessage('Should have a valid transcoding 480p resolution enabled boolean'),
52 body('transcoding.resolutions.720p').isBoolean().withMessage('Should have a valid transcoding 720p resolution enabled boolean'),
53 body('transcoding.resolutions.1080p').isBoolean().withMessage('Should have a valid transcoding 1080p resolution enabled boolean'),
54 body('transcoding.resolutions.1440p').isBoolean().withMessage('Should have a valid transcoding 1440p resolution enabled boolean'),
55 body('transcoding.resolutions.2160p').isBoolean().withMessage('Should have a valid transcoding 2160p resolution enabled boolean'),
56
57 body('transcoding.webtorrent.enabled').isBoolean().withMessage('Should have a valid webtorrent transcoding enabled boolean'),
58 body('transcoding.hls.enabled').isBoolean().withMessage('Should have a valid hls transcoding enabled boolean'),
59
60 body('videoStudio.enabled').isBoolean().withMessage('Should have a valid video studio enabled boolean'),
61
62 body('import.videos.concurrency').isInt({ min: 0 }).withMessage('Should have a valid import concurrency number'),
63 body('import.videos.http.enabled').isBoolean().withMessage('Should have a valid import video http enabled boolean'),
64 body('import.videos.torrent.enabled').isBoolean().withMessage('Should have a valid import video torrent enabled boolean'),
65
66 body('trending.videos.algorithms.default').exists().withMessage('Should have a valid default trending algorithm'),
67 body('trending.videos.algorithms.enabled').exists().withMessage('Should have a valid array of enabled trending algorithms'),
68
69 body('followers.instance.enabled').isBoolean().withMessage('Should have a valid followers of instance boolean'),
70 body('followers.instance.manualApproval').isBoolean().withMessage('Should have a valid manual approval boolean'),
71
72 body('theme.default').custom(v => isThemeNameValid(v) && isThemeRegistered(v)).withMessage('Should have a valid theme'),
73
74 body('broadcastMessage.enabled').isBoolean().withMessage('Should have a valid broadcast message enabled boolean'),
75 body('broadcastMessage.message').exists().withMessage('Should have a valid broadcast message'),
76 body('broadcastMessage.level').exists().withMessage('Should have a valid broadcast level'),
77 body('broadcastMessage.dismissable').isBoolean().withMessage('Should have a valid broadcast dismissable boolean'),
78
79 body('live.enabled').isBoolean().withMessage('Should have a valid live enabled boolean'),
80 body('live.allowReplay').isBoolean().withMessage('Should have a valid live allow replay boolean'),
81 body('live.maxDuration').isInt().withMessage('Should have a valid live max duration'),
82 body('live.maxInstanceLives').custom(isIntOrNull).withMessage('Should have a valid max instance lives'),
83 body('live.maxUserLives').custom(isIntOrNull).withMessage('Should have a valid max user lives'),
84 body('live.transcoding.enabled').isBoolean().withMessage('Should have a valid live transcoding enabled boolean'),
85 body('live.transcoding.threads').isInt().withMessage('Should have a valid live transcoding threads'),
86 body('live.transcoding.resolutions.144p').isBoolean().withMessage('Should have a valid transcoding 144p resolution enabled boolean'),
87 body('live.transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'),
88 body('live.transcoding.resolutions.360p').isBoolean().withMessage('Should have a valid transcoding 360p resolution enabled boolean'),
89 body('live.transcoding.resolutions.480p').isBoolean().withMessage('Should have a valid transcoding 480p resolution enabled boolean'),
90 body('live.transcoding.resolutions.720p').isBoolean().withMessage('Should have a valid transcoding 720p resolution enabled boolean'),
91 body('live.transcoding.resolutions.1080p').isBoolean().withMessage('Should have a valid transcoding 1080p resolution enabled boolean'),
92 body('live.transcoding.resolutions.1440p').isBoolean().withMessage('Should have a valid transcoding 1440p resolution enabled boolean'),
93 body('live.transcoding.resolutions.2160p').isBoolean().withMessage('Should have a valid transcoding 2160p resolution enabled boolean'),
94
95 body('search.remoteUri.users').isBoolean().withMessage('Should have a remote URI search for users boolean'),
96 body('search.remoteUri.anonymous').isBoolean().withMessage('Should have a valid remote URI search for anonymous boolean'),
97 body('search.searchIndex.enabled').isBoolean().withMessage('Should have a valid search index enabled boolean'),
98 body('search.searchIndex.url').exists().withMessage('Should have a valid search index URL'),
99 body('search.searchIndex.disableLocalSearch').isBoolean().withMessage('Should have a valid search index disable local search boolean'),
100 body('search.searchIndex.isDefaultSearch').isBoolean().withMessage('Should have a valid search index default enabled boolean'),
101
102 (req: express.Request, res: express.Response, next: express.NextFunction) => {
103 logger.debug('Checking customConfigUpdateValidator parameters', { parameters: req.body })
104
105 if (areValidationErrors(req, res)) return
106 if (!checkInvalidConfigIfEmailDisabled(req.body, res)) return
107 if (!checkInvalidTranscodingConfig(req.body, res)) return
108 if (!checkInvalidLiveConfig(req.body, res)) return
109 if (!checkInvalidVideoStudioConfig(req.body, res)) return
110
111 return next()
112 }
113 ]
114
115 function ensureConfigIsEditable (req: express.Request, res: express.Response, next: express.NextFunction) {
116 if (!CONFIG.WEBADMIN.CONFIGURATION.EDITION.ALLOWED) {
117 return res.fail({
118 status: HttpStatusCode.METHOD_NOT_ALLOWED_405,
119 message: 'Server configuration is static and cannot be edited'
120 })
121 }
122
123 return next()
124 }
125
126 // ---------------------------------------------------------------------------
127
128 export {
129 customConfigUpdateValidator,
130 ensureConfigIsEditable
131 }
132
133 function checkInvalidConfigIfEmailDisabled (customConfig: CustomConfig, res: express.Response) {
134 if (isEmailEnabled()) return true
135
136 if (customConfig.signup.requiresEmailVerification === true) {
137 res.fail({ message: 'Emailer is disabled but you require signup email verification.' })
138 return false
139 }
140
141 return true
142 }
143
144 function checkInvalidTranscodingConfig (customConfig: CustomConfig, res: express.Response) {
145 if (customConfig.transcoding.enabled === false) return true
146
147 if (customConfig.transcoding.webtorrent.enabled === false && customConfig.transcoding.hls.enabled === false) {
148 res.fail({ message: 'You need to enable at least webtorrent transcoding or hls transcoding' })
149 return false
150 }
151
152 return true
153 }
154
155 function checkInvalidLiveConfig (customConfig: CustomConfig, res: express.Response) {
156 if (customConfig.live.enabled === false) return true
157
158 if (customConfig.live.allowReplay === true && customConfig.transcoding.enabled === false) {
159 res.fail({ message: 'You cannot allow live replay if transcoding is not enabled' })
160 return false
161 }
162
163 return true
164 }
165
166 function checkInvalidVideoStudioConfig (customConfig: CustomConfig, res: express.Response) {
167 if (customConfig.videoStudio.enabled === false) return true
168
169 if (customConfig.videoStudio.enabled === true && customConfig.transcoding.enabled === false) {
170 res.fail({ message: 'You cannot enable video studio if transcoding is not enabled' })
171 return false
172 }
173
174 return true
175 }