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