]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/middlewares/validators/config.ts
refactor(server): redis > ioredis (#5371)
[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 { HttpStatusCode } from '@shared/models/http/http-error-codes'
6 import { CustomConfig } from '../../../shared/models/server/custom-config.model'
7 import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
8 import { isUserNSFWPolicyValid, isUserVideoQuotaDailyValid, isUserVideoQuotaValid } from '../../helpers/custom-validators/users'
9 import { isThemeRegistered } from '../../lib/plugins/theme-utils'
10 import { areValidationErrors } from './shared'
11
12 const customConfigUpdateValidator = [
13 body('instance.name').exists(),
14 body('instance.shortDescription').exists(),
15 body('instance.description').exists(),
16 body('instance.terms').exists(),
17 body('instance.defaultNSFWPolicy').custom(isUserNSFWPolicyValid),
18 body('instance.defaultClientRoute').exists(),
19 body('instance.customizations.css').exists(),
20 body('instance.customizations.javascript').exists(),
21
22 body('services.twitter.username').exists(),
23 body('services.twitter.whitelisted').isBoolean(),
24
25 body('cache.previews.size').isInt(),
26 body('cache.captions.size').isInt(),
27 body('cache.torrents.size').isInt(),
28
29 body('signup.enabled').isBoolean(),
30 body('signup.limit').isInt(),
31 body('signup.requiresEmailVerification').isBoolean(),
32 body('signup.minimumAge').isInt(),
33
34 body('admin.email').isEmail(),
35 body('contactForm.enabled').isBoolean(),
36
37 body('user.videoQuota').custom(isUserVideoQuotaValid),
38 body('user.videoQuotaDaily').custom(isUserVideoQuotaDailyValid),
39
40 body('videoChannels.maxPerUser').isInt(),
41
42 body('transcoding.enabled').isBoolean(),
43 body('transcoding.allowAdditionalExtensions').isBoolean(),
44 body('transcoding.threads').isInt(),
45 body('transcoding.concurrency').isInt({ min: 1 }),
46 body('transcoding.resolutions.0p').isBoolean(),
47 body('transcoding.resolutions.144p').isBoolean(),
48 body('transcoding.resolutions.240p').isBoolean(),
49 body('transcoding.resolutions.360p').isBoolean(),
50 body('transcoding.resolutions.480p').isBoolean(),
51 body('transcoding.resolutions.720p').isBoolean(),
52 body('transcoding.resolutions.1080p').isBoolean(),
53 body('transcoding.resolutions.1440p').isBoolean(),
54 body('transcoding.resolutions.2160p').isBoolean(),
55
56 body('transcoding.alwaysTranscodeOriginalResolution').isBoolean(),
57
58 body('transcoding.webtorrent.enabled').isBoolean(),
59 body('transcoding.hls.enabled').isBoolean(),
60
61 body('videoStudio.enabled').isBoolean(),
62
63 body('import.videos.concurrency').isInt({ min: 0 }),
64 body('import.videos.http.enabled').isBoolean(),
65 body('import.videos.torrent.enabled').isBoolean(),
66
67 body('import.videoChannelSynchronization.enabled').isBoolean(),
68
69 body('trending.videos.algorithms.default').exists(),
70 body('trending.videos.algorithms.enabled').exists(),
71
72 body('followers.instance.enabled').isBoolean(),
73 body('followers.instance.manualApproval').isBoolean(),
74
75 body('theme.default').custom(v => isThemeNameValid(v) && isThemeRegistered(v)),
76
77 body('broadcastMessage.enabled').isBoolean(),
78 body('broadcastMessage.message').exists(),
79 body('broadcastMessage.level').exists(),
80 body('broadcastMessage.dismissable').isBoolean(),
81
82 body('live.enabled').isBoolean(),
83 body('live.allowReplay').isBoolean(),
84 body('live.maxDuration').isInt(),
85 body('live.maxInstanceLives').custom(isIntOrNull),
86 body('live.maxUserLives').custom(isIntOrNull),
87 body('live.transcoding.enabled').isBoolean(),
88 body('live.transcoding.threads').isInt(),
89 body('live.transcoding.resolutions.144p').isBoolean(),
90 body('live.transcoding.resolutions.240p').isBoolean(),
91 body('live.transcoding.resolutions.360p').isBoolean(),
92 body('live.transcoding.resolutions.480p').isBoolean(),
93 body('live.transcoding.resolutions.720p').isBoolean(),
94 body('live.transcoding.resolutions.1080p').isBoolean(),
95 body('live.transcoding.resolutions.1440p').isBoolean(),
96 body('live.transcoding.resolutions.2160p').isBoolean(),
97 body('live.transcoding.alwaysTranscodeOriginalResolution').isBoolean(),
98
99 body('search.remoteUri.users').isBoolean(),
100 body('search.remoteUri.anonymous').isBoolean(),
101 body('search.searchIndex.enabled').isBoolean(),
102 body('search.searchIndex.url').exists(),
103 body('search.searchIndex.disableLocalSearch').isBoolean(),
104 body('search.searchIndex.isDefaultSearch').isBoolean(),
105
106 (req: express.Request, res: express.Response, next: express.NextFunction) => {
107 if (areValidationErrors(req, res)) return
108 if (!checkInvalidConfigIfEmailDisabled(req.body, res)) return
109 if (!checkInvalidTranscodingConfig(req.body, res)) return
110 if (!checkInvalidSynchronizationConfig(req.body, res)) return
111 if (!checkInvalidLiveConfig(req.body, res)) return
112 if (!checkInvalidVideoStudioConfig(req.body, res)) return
113
114 return next()
115 }
116 ]
117
118 function ensureConfigIsEditable (req: express.Request, res: express.Response, next: express.NextFunction) {
119 if (!CONFIG.WEBADMIN.CONFIGURATION.EDITION.ALLOWED) {
120 return res.fail({
121 status: HttpStatusCode.METHOD_NOT_ALLOWED_405,
122 message: 'Server configuration is static and cannot be edited'
123 })
124 }
125
126 return next()
127 }
128
129 // ---------------------------------------------------------------------------
130
131 export {
132 customConfigUpdateValidator,
133 ensureConfigIsEditable
134 }
135
136 function checkInvalidConfigIfEmailDisabled (customConfig: CustomConfig, res: express.Response) {
137 if (isEmailEnabled()) return true
138
139 if (customConfig.signup.requiresEmailVerification === true) {
140 res.fail({ message: 'Emailer is disabled but you require signup email verification.' })
141 return false
142 }
143
144 return true
145 }
146
147 function checkInvalidTranscodingConfig (customConfig: CustomConfig, res: express.Response) {
148 if (customConfig.transcoding.enabled === false) return true
149
150 if (customConfig.transcoding.webtorrent.enabled === false && customConfig.transcoding.hls.enabled === false) {
151 res.fail({ message: 'You need to enable at least webtorrent transcoding or hls transcoding' })
152 return false
153 }
154
155 return true
156 }
157
158 function checkInvalidSynchronizationConfig (customConfig: CustomConfig, res: express.Response) {
159 if (customConfig.import.videoChannelSynchronization.enabled && !customConfig.import.videos.http.enabled) {
160 res.fail({ message: 'You need to enable HTTP video import in order to enable channel synchronization' })
161 return false
162 }
163 return true
164 }
165
166 function checkInvalidLiveConfig (customConfig: CustomConfig, res: express.Response) {
167 if (customConfig.live.enabled === false) return true
168
169 if (customConfig.live.allowReplay === true && customConfig.transcoding.enabled === false) {
170 res.fail({ message: 'You cannot allow live replay if transcoding is not enabled' })
171 return false
172 }
173
174 return true
175 }
176
177 function checkInvalidVideoStudioConfig (customConfig: CustomConfig, res: express.Response) {
178 if (customConfig.videoStudio.enabled === false) return true
179
180 if (customConfig.videoStudio.enabled === true && customConfig.transcoding.enabled === false) {
181 res.fail({ message: 'You cannot enable video studio if transcoding is not enabled' })
182 return false
183 }
184
185 return true
186 }