aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/api/config.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-07-31 14:34:36 +0200
committerChocobozzz <me@florianbigard.com>2023-08-11 15:02:33 +0200
commit3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch)
treee4510b39bdac9c318fdb4b47018d08f15368b8f0 /server/controllers/api/config.ts
parent04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff)
downloadPeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'server/controllers/api/config.ts')
-rw-r--r--server/controllers/api/config.ts377
1 files changed, 0 insertions, 377 deletions
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
deleted file mode 100644
index c5c4c8a74..000000000
--- a/server/controllers/api/config.ts
+++ /dev/null
@@ -1,377 +0,0 @@
1import express from 'express'
2import { remove, writeJSON } from 'fs-extra'
3import { snakeCase } from 'lodash'
4import validator from 'validator'
5import { ServerConfigManager } from '@server/lib/server-config-manager'
6import { About, CustomConfig, UserRight } from '@shared/models'
7import { auditLoggerFactory, CustomConfigAuditView, getAuditIdFromRes } from '../../helpers/audit-logger'
8import { objectConverter } from '../../helpers/core-utils'
9import { CONFIG, reloadConfig } from '../../initializers/config'
10import { ClientHtml } from '../../lib/client-html'
11import { apiRateLimiter, asyncMiddleware, authenticate, ensureUserHasRight, openapiOperationDoc } from '../../middlewares'
12import { customConfigUpdateValidator, ensureConfigIsEditable } from '../../middlewares/validators/config'
13
14const configRouter = express.Router()
15
16configRouter.use(apiRateLimiter)
17
18const auditLogger = auditLoggerFactory('config')
19
20configRouter.get('/',
21 openapiOperationDoc({ operationId: 'getConfig' }),
22 asyncMiddleware(getConfig)
23)
24
25configRouter.get('/about',
26 openapiOperationDoc({ operationId: 'getAbout' }),
27 getAbout
28)
29
30configRouter.get('/custom',
31 openapiOperationDoc({ operationId: 'getCustomConfig' }),
32 authenticate,
33 ensureUserHasRight(UserRight.MANAGE_CONFIGURATION),
34 getCustomConfig
35)
36
37configRouter.put('/custom',
38 openapiOperationDoc({ operationId: 'putCustomConfig' }),
39 authenticate,
40 ensureUserHasRight(UserRight.MANAGE_CONFIGURATION),
41 ensureConfigIsEditable,
42 customConfigUpdateValidator,
43 asyncMiddleware(updateCustomConfig)
44)
45
46configRouter.delete('/custom',
47 openapiOperationDoc({ operationId: 'delCustomConfig' }),
48 authenticate,
49 ensureUserHasRight(UserRight.MANAGE_CONFIGURATION),
50 ensureConfigIsEditable,
51 asyncMiddleware(deleteCustomConfig)
52)
53
54async function getConfig (req: express.Request, res: express.Response) {
55 const json = await ServerConfigManager.Instance.getServerConfig(req.ip)
56
57 return res.json(json)
58}
59
60function getAbout (req: express.Request, res: express.Response) {
61 const about: About = {
62 instance: {
63 name: CONFIG.INSTANCE.NAME,
64 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
65 description: CONFIG.INSTANCE.DESCRIPTION,
66 terms: CONFIG.INSTANCE.TERMS,
67 codeOfConduct: CONFIG.INSTANCE.CODE_OF_CONDUCT,
68
69 hardwareInformation: CONFIG.INSTANCE.HARDWARE_INFORMATION,
70
71 creationReason: CONFIG.INSTANCE.CREATION_REASON,
72 moderationInformation: CONFIG.INSTANCE.MODERATION_INFORMATION,
73 administrator: CONFIG.INSTANCE.ADMINISTRATOR,
74 maintenanceLifetime: CONFIG.INSTANCE.MAINTENANCE_LIFETIME,
75 businessModel: CONFIG.INSTANCE.BUSINESS_MODEL,
76
77 languages: CONFIG.INSTANCE.LANGUAGES,
78 categories: CONFIG.INSTANCE.CATEGORIES
79 }
80 }
81
82 return res.json(about)
83}
84
85function getCustomConfig (req: express.Request, res: express.Response) {
86 const data = customConfig()
87
88 return res.json(data)
89}
90
91async function deleteCustomConfig (req: express.Request, res: express.Response) {
92 await remove(CONFIG.CUSTOM_FILE)
93
94 auditLogger.delete(getAuditIdFromRes(res), new CustomConfigAuditView(customConfig()))
95
96 reloadConfig()
97 ClientHtml.invalidCache()
98
99 const data = customConfig()
100
101 return res.json(data)
102}
103
104async function updateCustomConfig (req: express.Request, res: express.Response) {
105 const oldCustomConfigAuditKeys = new CustomConfigAuditView(customConfig())
106
107 // camelCase to snake_case key + Force number conversion
108 const toUpdateJSON = convertCustomConfigBody(req.body)
109
110 await writeJSON(CONFIG.CUSTOM_FILE, toUpdateJSON, { spaces: 2 })
111
112 reloadConfig()
113 ClientHtml.invalidCache()
114
115 const data = customConfig()
116
117 auditLogger.update(
118 getAuditIdFromRes(res),
119 new CustomConfigAuditView(data),
120 oldCustomConfigAuditKeys
121 )
122
123 return res.json(data)
124}
125
126// ---------------------------------------------------------------------------
127
128export {
129 configRouter
130}
131
132// ---------------------------------------------------------------------------
133
134function customConfig (): CustomConfig {
135 return {
136 instance: {
137 name: CONFIG.INSTANCE.NAME,
138 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
139 description: CONFIG.INSTANCE.DESCRIPTION,
140 terms: CONFIG.INSTANCE.TERMS,
141 codeOfConduct: CONFIG.INSTANCE.CODE_OF_CONDUCT,
142
143 creationReason: CONFIG.INSTANCE.CREATION_REASON,
144 moderationInformation: CONFIG.INSTANCE.MODERATION_INFORMATION,
145 administrator: CONFIG.INSTANCE.ADMINISTRATOR,
146 maintenanceLifetime: CONFIG.INSTANCE.MAINTENANCE_LIFETIME,
147 businessModel: CONFIG.INSTANCE.BUSINESS_MODEL,
148 hardwareInformation: CONFIG.INSTANCE.HARDWARE_INFORMATION,
149
150 languages: CONFIG.INSTANCE.LANGUAGES,
151 categories: CONFIG.INSTANCE.CATEGORIES,
152
153 isNSFW: CONFIG.INSTANCE.IS_NSFW,
154 defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
155
156 defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
157
158 customizations: {
159 css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS,
160 javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT
161 }
162 },
163 theme: {
164 default: CONFIG.THEME.DEFAULT
165 },
166 services: {
167 twitter: {
168 username: CONFIG.SERVICES.TWITTER.USERNAME,
169 whitelisted: CONFIG.SERVICES.TWITTER.WHITELISTED
170 }
171 },
172 client: {
173 videos: {
174 miniature: {
175 preferAuthorDisplayName: CONFIG.CLIENT.VIDEOS.MINIATURE.PREFER_AUTHOR_DISPLAY_NAME
176 }
177 },
178 menu: {
179 login: {
180 redirectOnSingleExternalAuth: CONFIG.CLIENT.MENU.LOGIN.REDIRECT_ON_SINGLE_EXTERNAL_AUTH
181 }
182 }
183 },
184 cache: {
185 previews: {
186 size: CONFIG.CACHE.PREVIEWS.SIZE
187 },
188 captions: {
189 size: CONFIG.CACHE.VIDEO_CAPTIONS.SIZE
190 },
191 torrents: {
192 size: CONFIG.CACHE.TORRENTS.SIZE
193 },
194 storyboards: {
195 size: CONFIG.CACHE.STORYBOARDS.SIZE
196 }
197 },
198 signup: {
199 enabled: CONFIG.SIGNUP.ENABLED,
200 limit: CONFIG.SIGNUP.LIMIT,
201 requiresApproval: CONFIG.SIGNUP.REQUIRES_APPROVAL,
202 requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION,
203 minimumAge: CONFIG.SIGNUP.MINIMUM_AGE
204 },
205 admin: {
206 email: CONFIG.ADMIN.EMAIL
207 },
208 contactForm: {
209 enabled: CONFIG.CONTACT_FORM.ENABLED
210 },
211 user: {
212 history: {
213 videos: {
214 enabled: CONFIG.USER.HISTORY.VIDEOS.ENABLED
215 }
216 },
217 videoQuota: CONFIG.USER.VIDEO_QUOTA,
218 videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY
219 },
220 videoChannels: {
221 maxPerUser: CONFIG.VIDEO_CHANNELS.MAX_PER_USER
222 },
223 transcoding: {
224 enabled: CONFIG.TRANSCODING.ENABLED,
225 remoteRunners: {
226 enabled: CONFIG.TRANSCODING.REMOTE_RUNNERS.ENABLED
227 },
228 allowAdditionalExtensions: CONFIG.TRANSCODING.ALLOW_ADDITIONAL_EXTENSIONS,
229 allowAudioFiles: CONFIG.TRANSCODING.ALLOW_AUDIO_FILES,
230 threads: CONFIG.TRANSCODING.THREADS,
231 concurrency: CONFIG.TRANSCODING.CONCURRENCY,
232 profile: CONFIG.TRANSCODING.PROFILE,
233 resolutions: {
234 '0p': CONFIG.TRANSCODING.RESOLUTIONS['0p'],
235 '144p': CONFIG.TRANSCODING.RESOLUTIONS['144p'],
236 '240p': CONFIG.TRANSCODING.RESOLUTIONS['240p'],
237 '360p': CONFIG.TRANSCODING.RESOLUTIONS['360p'],
238 '480p': CONFIG.TRANSCODING.RESOLUTIONS['480p'],
239 '720p': CONFIG.TRANSCODING.RESOLUTIONS['720p'],
240 '1080p': CONFIG.TRANSCODING.RESOLUTIONS['1080p'],
241 '1440p': CONFIG.TRANSCODING.RESOLUTIONS['1440p'],
242 '2160p': CONFIG.TRANSCODING.RESOLUTIONS['2160p']
243 },
244 alwaysTranscodeOriginalResolution: CONFIG.TRANSCODING.ALWAYS_TRANSCODE_ORIGINAL_RESOLUTION,
245 webVideos: {
246 enabled: CONFIG.TRANSCODING.WEB_VIDEOS.ENABLED
247 },
248 hls: {
249 enabled: CONFIG.TRANSCODING.HLS.ENABLED
250 }
251 },
252 live: {
253 enabled: CONFIG.LIVE.ENABLED,
254 allowReplay: CONFIG.LIVE.ALLOW_REPLAY,
255 latencySetting: {
256 enabled: CONFIG.LIVE.LATENCY_SETTING.ENABLED
257 },
258 maxDuration: CONFIG.LIVE.MAX_DURATION,
259 maxInstanceLives: CONFIG.LIVE.MAX_INSTANCE_LIVES,
260 maxUserLives: CONFIG.LIVE.MAX_USER_LIVES,
261 transcoding: {
262 enabled: CONFIG.LIVE.TRANSCODING.ENABLED,
263 remoteRunners: {
264 enabled: CONFIG.LIVE.TRANSCODING.REMOTE_RUNNERS.ENABLED
265 },
266 threads: CONFIG.LIVE.TRANSCODING.THREADS,
267 profile: CONFIG.LIVE.TRANSCODING.PROFILE,
268 resolutions: {
269 '144p': CONFIG.LIVE.TRANSCODING.RESOLUTIONS['144p'],
270 '240p': CONFIG.LIVE.TRANSCODING.RESOLUTIONS['240p'],
271 '360p': CONFIG.LIVE.TRANSCODING.RESOLUTIONS['360p'],
272 '480p': CONFIG.LIVE.TRANSCODING.RESOLUTIONS['480p'],
273 '720p': CONFIG.LIVE.TRANSCODING.RESOLUTIONS['720p'],
274 '1080p': CONFIG.LIVE.TRANSCODING.RESOLUTIONS['1080p'],
275 '1440p': CONFIG.LIVE.TRANSCODING.RESOLUTIONS['1440p'],
276 '2160p': CONFIG.LIVE.TRANSCODING.RESOLUTIONS['2160p']
277 },
278 alwaysTranscodeOriginalResolution: CONFIG.LIVE.TRANSCODING.ALWAYS_TRANSCODE_ORIGINAL_RESOLUTION
279 }
280 },
281 videoStudio: {
282 enabled: CONFIG.VIDEO_STUDIO.ENABLED,
283 remoteRunners: {
284 enabled: CONFIG.VIDEO_STUDIO.REMOTE_RUNNERS.ENABLED
285 }
286 },
287 videoFile: {
288 update: {
289 enabled: CONFIG.VIDEO_FILE.UPDATE.ENABLED
290 }
291 },
292 import: {
293 videos: {
294 concurrency: CONFIG.IMPORT.VIDEOS.CONCURRENCY,
295 http: {
296 enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED
297 },
298 torrent: {
299 enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED
300 }
301 },
302 videoChannelSynchronization: {
303 enabled: CONFIG.IMPORT.VIDEO_CHANNEL_SYNCHRONIZATION.ENABLED,
304 maxPerUser: CONFIG.IMPORT.VIDEO_CHANNEL_SYNCHRONIZATION.MAX_PER_USER
305 }
306 },
307 trending: {
308 videos: {
309 algorithms: {
310 enabled: CONFIG.TRENDING.VIDEOS.ALGORITHMS.ENABLED,
311 default: CONFIG.TRENDING.VIDEOS.ALGORITHMS.DEFAULT
312 }
313 }
314 },
315 autoBlacklist: {
316 videos: {
317 ofUsers: {
318 enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED
319 }
320 }
321 },
322 followers: {
323 instance: {
324 enabled: CONFIG.FOLLOWERS.INSTANCE.ENABLED,
325 manualApproval: CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL
326 }
327 },
328 followings: {
329 instance: {
330 autoFollowBack: {
331 enabled: CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_BACK.ENABLED
332 },
333
334 autoFollowIndex: {
335 enabled: CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_INDEX.ENABLED,
336 indexUrl: CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_INDEX.INDEX_URL
337 }
338 }
339 },
340 broadcastMessage: {
341 enabled: CONFIG.BROADCAST_MESSAGE.ENABLED,
342 message: CONFIG.BROADCAST_MESSAGE.MESSAGE,
343 level: CONFIG.BROADCAST_MESSAGE.LEVEL,
344 dismissable: CONFIG.BROADCAST_MESSAGE.DISMISSABLE
345 },
346 search: {
347 remoteUri: {
348 users: CONFIG.SEARCH.REMOTE_URI.USERS,
349 anonymous: CONFIG.SEARCH.REMOTE_URI.ANONYMOUS
350 },
351 searchIndex: {
352 enabled: CONFIG.SEARCH.SEARCH_INDEX.ENABLED,
353 url: CONFIG.SEARCH.SEARCH_INDEX.URL,
354 disableLocalSearch: CONFIG.SEARCH.SEARCH_INDEX.DISABLE_LOCAL_SEARCH,
355 isDefaultSearch: CONFIG.SEARCH.SEARCH_INDEX.IS_DEFAULT_SEARCH
356 }
357 }
358 }
359}
360
361function convertCustomConfigBody (body: CustomConfig) {
362 function keyConverter (k: string) {
363 // Transcoding resolutions exception
364 if (/^\d{3,4}p$/.exec(k)) return k
365 if (k === '0p') return k
366
367 return snakeCase(k)
368 }
369
370 function valueConverter (v: any) {
371 if (validator.isNumeric(v + '')) return parseInt('' + v, 10)
372
373 return v
374 }
375
376 return objectConverter(body, keyConverter, valueConverter)
377}