diff options
Diffstat (limited to 'server/lib/server-config-manager.ts')
-rw-r--r-- | server/lib/server-config-manager.ts | 384 |
1 files changed, 0 insertions, 384 deletions
diff --git a/server/lib/server-config-manager.ts b/server/lib/server-config-manager.ts deleted file mode 100644 index beb5d4d82..000000000 --- a/server/lib/server-config-manager.ts +++ /dev/null | |||
@@ -1,384 +0,0 @@ | |||
1 | import { getServerCommit } from '@server/helpers/version' | ||
2 | import { CONFIG, isEmailEnabled } from '@server/initializers/config' | ||
3 | import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants' | ||
4 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/lib/signup' | ||
5 | import { ActorCustomPageModel } from '@server/models/account/actor-custom-page' | ||
6 | import { PluginModel } from '@server/models/server/plugin' | ||
7 | import { HTMLServerConfig, RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models' | ||
8 | import { Hooks } from './plugins/hooks' | ||
9 | import { PluginManager } from './plugins/plugin-manager' | ||
10 | import { getThemeOrDefault } from './plugins/theme-utils' | ||
11 | import { VideoTranscodingProfilesManager } from './transcoding/default-transcoding-profiles' | ||
12 | |||
13 | /** | ||
14 | * | ||
15 | * Used to send the server config to clients (using REST/API or plugins API) | ||
16 | * We need a singleton class to manage config state depending on external events (to build menu entries etc) | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | class ServerConfigManager { | ||
21 | |||
22 | private static instance: ServerConfigManager | ||
23 | |||
24 | private serverCommit: string | ||
25 | |||
26 | private homepageEnabled = false | ||
27 | |||
28 | private constructor () {} | ||
29 | |||
30 | async init () { | ||
31 | const instanceHomepage = await ActorCustomPageModel.loadInstanceHomepage() | ||
32 | |||
33 | this.updateHomepageState(instanceHomepage?.content) | ||
34 | } | ||
35 | |||
36 | updateHomepageState (content: string) { | ||
37 | this.homepageEnabled = !!content | ||
38 | } | ||
39 | |||
40 | async getHTMLServerConfig (): Promise<HTMLServerConfig> { | ||
41 | if (this.serverCommit === undefined) this.serverCommit = await getServerCommit() | ||
42 | |||
43 | const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME) | ||
44 | |||
45 | return { | ||
46 | client: { | ||
47 | videos: { | ||
48 | miniature: { | ||
49 | displayAuthorAvatar: CONFIG.CLIENT.VIDEOS.MINIATURE.DISPLAY_AUTHOR_AVATAR, | ||
50 | preferAuthorDisplayName: CONFIG.CLIENT.VIDEOS.MINIATURE.PREFER_AUTHOR_DISPLAY_NAME | ||
51 | }, | ||
52 | resumableUpload: { | ||
53 | maxChunkSize: CONFIG.CLIENT.VIDEOS.RESUMABLE_UPLOAD.MAX_CHUNK_SIZE | ||
54 | } | ||
55 | }, | ||
56 | menu: { | ||
57 | login: { | ||
58 | redirectOnSingleExternalAuth: CONFIG.CLIENT.MENU.LOGIN.REDIRECT_ON_SINGLE_EXTERNAL_AUTH | ||
59 | } | ||
60 | } | ||
61 | }, | ||
62 | |||
63 | defaults: { | ||
64 | publish: { | ||
65 | downloadEnabled: CONFIG.DEFAULTS.PUBLISH.DOWNLOAD_ENABLED, | ||
66 | commentsEnabled: CONFIG.DEFAULTS.PUBLISH.COMMENTS_ENABLED, | ||
67 | privacy: CONFIG.DEFAULTS.PUBLISH.PRIVACY, | ||
68 | licence: CONFIG.DEFAULTS.PUBLISH.LICENCE | ||
69 | }, | ||
70 | p2p: { | ||
71 | webapp: { | ||
72 | enabled: CONFIG.DEFAULTS.P2P.WEBAPP.ENABLED | ||
73 | }, | ||
74 | embed: { | ||
75 | enabled: CONFIG.DEFAULTS.P2P.EMBED.ENABLED | ||
76 | } | ||
77 | } | ||
78 | }, | ||
79 | |||
80 | webadmin: { | ||
81 | configuration: { | ||
82 | edition: { | ||
83 | allowed: CONFIG.WEBADMIN.CONFIGURATION.EDITION.ALLOWED | ||
84 | } | ||
85 | } | ||
86 | }, | ||
87 | |||
88 | instance: { | ||
89 | name: CONFIG.INSTANCE.NAME, | ||
90 | shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION, | ||
91 | isNSFW: CONFIG.INSTANCE.IS_NSFW, | ||
92 | defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY, | ||
93 | defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE, | ||
94 | customizations: { | ||
95 | javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT, | ||
96 | css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS | ||
97 | } | ||
98 | }, | ||
99 | search: { | ||
100 | remoteUri: { | ||
101 | users: CONFIG.SEARCH.REMOTE_URI.USERS, | ||
102 | anonymous: CONFIG.SEARCH.REMOTE_URI.ANONYMOUS | ||
103 | }, | ||
104 | searchIndex: { | ||
105 | enabled: CONFIG.SEARCH.SEARCH_INDEX.ENABLED, | ||
106 | url: CONFIG.SEARCH.SEARCH_INDEX.URL, | ||
107 | disableLocalSearch: CONFIG.SEARCH.SEARCH_INDEX.DISABLE_LOCAL_SEARCH, | ||
108 | isDefaultSearch: CONFIG.SEARCH.SEARCH_INDEX.IS_DEFAULT_SEARCH | ||
109 | } | ||
110 | }, | ||
111 | plugin: { | ||
112 | registered: this.getRegisteredPlugins(), | ||
113 | registeredExternalAuths: this.getExternalAuthsPlugins(), | ||
114 | registeredIdAndPassAuths: this.getIdAndPassAuthPlugins() | ||
115 | }, | ||
116 | theme: { | ||
117 | registered: this.getRegisteredThemes(), | ||
118 | default: defaultTheme | ||
119 | }, | ||
120 | email: { | ||
121 | enabled: isEmailEnabled() | ||
122 | }, | ||
123 | contactForm: { | ||
124 | enabled: CONFIG.CONTACT_FORM.ENABLED | ||
125 | }, | ||
126 | serverVersion: PEERTUBE_VERSION, | ||
127 | serverCommit: this.serverCommit, | ||
128 | transcoding: { | ||
129 | remoteRunners: { | ||
130 | enabled: CONFIG.TRANSCODING.ENABLED && CONFIG.TRANSCODING.REMOTE_RUNNERS.ENABLED | ||
131 | }, | ||
132 | hls: { | ||
133 | enabled: CONFIG.TRANSCODING.ENABLED && CONFIG.TRANSCODING.HLS.ENABLED | ||
134 | }, | ||
135 | web_videos: { | ||
136 | enabled: CONFIG.TRANSCODING.ENABLED && CONFIG.TRANSCODING.WEB_VIDEOS.ENABLED | ||
137 | }, | ||
138 | enabledResolutions: this.getEnabledResolutions('vod'), | ||
139 | profile: CONFIG.TRANSCODING.PROFILE, | ||
140 | availableProfiles: VideoTranscodingProfilesManager.Instance.getAvailableProfiles('vod') | ||
141 | }, | ||
142 | live: { | ||
143 | enabled: CONFIG.LIVE.ENABLED, | ||
144 | |||
145 | allowReplay: CONFIG.LIVE.ALLOW_REPLAY, | ||
146 | latencySetting: { | ||
147 | enabled: CONFIG.LIVE.LATENCY_SETTING.ENABLED | ||
148 | }, | ||
149 | |||
150 | maxDuration: CONFIG.LIVE.MAX_DURATION, | ||
151 | maxInstanceLives: CONFIG.LIVE.MAX_INSTANCE_LIVES, | ||
152 | maxUserLives: CONFIG.LIVE.MAX_USER_LIVES, | ||
153 | |||
154 | transcoding: { | ||
155 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED, | ||
156 | remoteRunners: { | ||
157 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED && CONFIG.LIVE.TRANSCODING.REMOTE_RUNNERS.ENABLED | ||
158 | }, | ||
159 | enabledResolutions: this.getEnabledResolutions('live'), | ||
160 | profile: CONFIG.LIVE.TRANSCODING.PROFILE, | ||
161 | availableProfiles: VideoTranscodingProfilesManager.Instance.getAvailableProfiles('live') | ||
162 | }, | ||
163 | |||
164 | rtmp: { | ||
165 | port: CONFIG.LIVE.RTMP.PORT | ||
166 | } | ||
167 | }, | ||
168 | videoStudio: { | ||
169 | enabled: CONFIG.VIDEO_STUDIO.ENABLED, | ||
170 | remoteRunners: { | ||
171 | enabled: CONFIG.VIDEO_STUDIO.REMOTE_RUNNERS.ENABLED | ||
172 | } | ||
173 | }, | ||
174 | videoFile: { | ||
175 | update: { | ||
176 | enabled: CONFIG.VIDEO_FILE.UPDATE.ENABLED | ||
177 | } | ||
178 | }, | ||
179 | import: { | ||
180 | videos: { | ||
181 | http: { | ||
182 | enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED | ||
183 | }, | ||
184 | torrent: { | ||
185 | enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED | ||
186 | } | ||
187 | }, | ||
188 | videoChannelSynchronization: { | ||
189 | enabled: CONFIG.IMPORT.VIDEO_CHANNEL_SYNCHRONIZATION.ENABLED | ||
190 | } | ||
191 | }, | ||
192 | autoBlacklist: { | ||
193 | videos: { | ||
194 | ofUsers: { | ||
195 | enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED | ||
196 | } | ||
197 | } | ||
198 | }, | ||
199 | avatar: { | ||
200 | file: { | ||
201 | size: { | ||
202 | max: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max | ||
203 | }, | ||
204 | extensions: CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME | ||
205 | } | ||
206 | }, | ||
207 | banner: { | ||
208 | file: { | ||
209 | size: { | ||
210 | max: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max | ||
211 | }, | ||
212 | extensions: CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME | ||
213 | } | ||
214 | }, | ||
215 | video: { | ||
216 | image: { | ||
217 | extensions: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME, | ||
218 | size: { | ||
219 | max: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max | ||
220 | } | ||
221 | }, | ||
222 | file: { | ||
223 | extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME | ||
224 | } | ||
225 | }, | ||
226 | videoCaption: { | ||
227 | file: { | ||
228 | size: { | ||
229 | max: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max | ||
230 | }, | ||
231 | extensions: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.EXTNAME | ||
232 | } | ||
233 | }, | ||
234 | user: { | ||
235 | videoQuota: CONFIG.USER.VIDEO_QUOTA, | ||
236 | videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY | ||
237 | }, | ||
238 | videoChannels: { | ||
239 | maxPerUser: CONFIG.VIDEO_CHANNELS.MAX_PER_USER | ||
240 | }, | ||
241 | trending: { | ||
242 | videos: { | ||
243 | intervalDays: CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS, | ||
244 | algorithms: { | ||
245 | enabled: CONFIG.TRENDING.VIDEOS.ALGORITHMS.ENABLED, | ||
246 | default: CONFIG.TRENDING.VIDEOS.ALGORITHMS.DEFAULT | ||
247 | } | ||
248 | } | ||
249 | }, | ||
250 | tracker: { | ||
251 | enabled: CONFIG.TRACKER.ENABLED | ||
252 | }, | ||
253 | |||
254 | followings: { | ||
255 | instance: { | ||
256 | autoFollowIndex: { | ||
257 | indexUrl: CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_INDEX.INDEX_URL | ||
258 | } | ||
259 | } | ||
260 | }, | ||
261 | |||
262 | broadcastMessage: { | ||
263 | enabled: CONFIG.BROADCAST_MESSAGE.ENABLED, | ||
264 | message: CONFIG.BROADCAST_MESSAGE.MESSAGE, | ||
265 | level: CONFIG.BROADCAST_MESSAGE.LEVEL, | ||
266 | dismissable: CONFIG.BROADCAST_MESSAGE.DISMISSABLE | ||
267 | }, | ||
268 | |||
269 | homepage: { | ||
270 | enabled: this.homepageEnabled | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | async getServerConfig (ip?: string): Promise<ServerConfig> { | ||
276 | const { allowed } = await Hooks.wrapPromiseFun( | ||
277 | isSignupAllowed, | ||
278 | |||
279 | { | ||
280 | ip, | ||
281 | signupMode: CONFIG.SIGNUP.REQUIRES_APPROVAL | ||
282 | ? 'request-registration' | ||
283 | : 'direct-registration' | ||
284 | }, | ||
285 | |||
286 | CONFIG.SIGNUP.REQUIRES_APPROVAL | ||
287 | ? 'filter:api.user.request-signup.allowed.result' | ||
288 | : 'filter:api.user.signup.allowed.result' | ||
289 | ) | ||
290 | |||
291 | const allowedForCurrentIP = isSignupAllowedForCurrentIP(ip) | ||
292 | |||
293 | const signup = { | ||
294 | allowed, | ||
295 | allowedForCurrentIP, | ||
296 | minimumAge: CONFIG.SIGNUP.MINIMUM_AGE, | ||
297 | requiresApproval: CONFIG.SIGNUP.REQUIRES_APPROVAL, | ||
298 | requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION | ||
299 | } | ||
300 | |||
301 | const htmlConfig = await this.getHTMLServerConfig() | ||
302 | |||
303 | return { ...htmlConfig, signup } | ||
304 | } | ||
305 | |||
306 | getRegisteredThemes () { | ||
307 | return PluginManager.Instance.getRegisteredThemes() | ||
308 | .map(t => ({ | ||
309 | npmName: PluginModel.buildNpmName(t.name, t.type), | ||
310 | name: t.name, | ||
311 | version: t.version, | ||
312 | description: t.description, | ||
313 | css: t.css, | ||
314 | clientScripts: t.clientScripts | ||
315 | })) | ||
316 | } | ||
317 | |||
318 | getRegisteredPlugins () { | ||
319 | return PluginManager.Instance.getRegisteredPlugins() | ||
320 | .map(p => ({ | ||
321 | npmName: PluginModel.buildNpmName(p.name, p.type), | ||
322 | name: p.name, | ||
323 | version: p.version, | ||
324 | description: p.description, | ||
325 | clientScripts: p.clientScripts | ||
326 | })) | ||
327 | } | ||
328 | |||
329 | getEnabledResolutions (type: 'vod' | 'live') { | ||
330 | const transcoding = type === 'vod' | ||
331 | ? CONFIG.TRANSCODING | ||
332 | : CONFIG.LIVE.TRANSCODING | ||
333 | |||
334 | return Object.keys(transcoding.RESOLUTIONS) | ||
335 | .filter(key => transcoding.ENABLED && transcoding.RESOLUTIONS[key] === true) | ||
336 | .map(r => parseInt(r, 10)) | ||
337 | } | ||
338 | |||
339 | private getIdAndPassAuthPlugins () { | ||
340 | const result: RegisteredIdAndPassAuthConfig[] = [] | ||
341 | |||
342 | for (const p of PluginManager.Instance.getIdAndPassAuths()) { | ||
343 | for (const auth of p.idAndPassAuths) { | ||
344 | result.push({ | ||
345 | npmName: p.npmName, | ||
346 | name: p.name, | ||
347 | version: p.version, | ||
348 | authName: auth.authName, | ||
349 | weight: auth.getWeight() | ||
350 | }) | ||
351 | } | ||
352 | } | ||
353 | |||
354 | return result | ||
355 | } | ||
356 | |||
357 | private getExternalAuthsPlugins () { | ||
358 | const result: RegisteredExternalAuthConfig[] = [] | ||
359 | |||
360 | for (const p of PluginManager.Instance.getExternalAuths()) { | ||
361 | for (const auth of p.externalAuths) { | ||
362 | result.push({ | ||
363 | npmName: p.npmName, | ||
364 | name: p.name, | ||
365 | version: p.version, | ||
366 | authName: auth.authName, | ||
367 | authDisplayName: auth.authDisplayName() | ||
368 | }) | ||
369 | } | ||
370 | } | ||
371 | |||
372 | return result | ||
373 | } | ||
374 | |||
375 | static get Instance () { | ||
376 | return this.instance || (this.instance = new this()) | ||
377 | } | ||
378 | } | ||
379 | |||
380 | // --------------------------------------------------------------------------- | ||
381 | |||
382 | export { | ||
383 | ServerConfigManager | ||
384 | } | ||