]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/controllers/api/config.ts
f14104d7fc244ca0217b1a9a6d145f2e471e8eb6
[github/Chocobozzz/PeerTube.git] / server / controllers / api / config.ts
1 import * as express from 'express'
2 import { omit } from 'lodash'
3 import { ServerConfig, UserRight } from '../../../shared'
4 import { About } from '../../../shared/models/server/about.model'
5 import { CustomConfig } from '../../../shared/models/server/custom-config.model'
6 import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup'
7 import { CONFIG, CONSTRAINTS_FIELDS, reloadConfig } from '../../initializers'
8 import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares'
9 import { customConfigUpdateValidator } from '../../middlewares/validators/config'
10 import { ClientHtml } from '../../lib/client-html'
11 import { auditLoggerFactory, CustomConfigAuditView, getAuditIdFromRes } from '../../helpers/audit-logger'
12 import { remove, writeJSON } from 'fs-extra'
13 import { getVersion } from '../../helpers/utils'
14
15 const packageJSON = require('../../../../package.json')
16 const configRouter = express.Router()
17
18 const auditLogger = auditLoggerFactory('config')
19
20 configRouter.get('/about', getAbout)
21 configRouter.get('/',
22 asyncMiddleware(getConfig)
23 )
24
25 configRouter.get('/custom',
26 authenticate,
27 ensureUserHasRight(UserRight.MANAGE_CONFIGURATION),
28 asyncMiddleware(getCustomConfig)
29 )
30 configRouter.put('/custom',
31 authenticate,
32 ensureUserHasRight(UserRight.MANAGE_CONFIGURATION),
33 asyncMiddleware(customConfigUpdateValidator),
34 asyncMiddleware(updateCustomConfig)
35 )
36 configRouter.delete('/custom',
37 authenticate,
38 ensureUserHasRight(UserRight.MANAGE_CONFIGURATION),
39 asyncMiddleware(deleteCustomConfig)
40 )
41
42 let serverCommit: string
43 async function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) {
44 const allowed = await isSignupAllowed()
45 const allowedForCurrentIP = isSignupAllowedForCurrentIP(req.ip)
46 serverCommit = (serverCommit) ? serverCommit : getVersion()
47 if (serverCommit === packageJSON.version) serverCommit = ''
48
49 const enabledResolutions = Object.keys(CONFIG.TRANSCODING.RESOLUTIONS)
50 .filter(key => CONFIG.TRANSCODING.ENABLED === CONFIG.TRANSCODING.RESOLUTIONS[key] === true)
51 .map(r => parseInt(r, 10))
52
53 const json: ServerConfig = {
54 instance: {
55 name: CONFIG.INSTANCE.NAME,
56 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
57 defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
58 defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
59 customizations: {
60 javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT,
61 css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS
62 }
63 },
64 serverVersion: packageJSON.version,
65 serverCommit,
66 signup: {
67 allowed,
68 allowedForCurrentIP,
69 requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION
70 },
71 transcoding: {
72 enabledResolutions
73 },
74 import: {
75 videos: {
76 http: {
77 enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED
78 },
79 torrent: {
80 enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED
81 }
82 }
83 },
84 avatar: {
85 file: {
86 size: {
87 max: CONSTRAINTS_FIELDS.ACTORS.AVATAR.FILE_SIZE.max
88 },
89 extensions: CONSTRAINTS_FIELDS.ACTORS.AVATAR.EXTNAME
90 }
91 },
92 video: {
93 image: {
94 extensions: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME,
95 size: {
96 max: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max
97 }
98 },
99 file: {
100 extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME
101 }
102 },
103 videoCaption: {
104 file: {
105 size: {
106 max: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max
107 },
108 extensions: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.EXTNAME
109 }
110 },
111 user: {
112 videoQuota: CONFIG.USER.VIDEO_QUOTA,
113 videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY
114 }
115 }
116
117 return res.json(json)
118 }
119
120 function getAbout (req: express.Request, res: express.Response, next: express.NextFunction) {
121 const about: About = {
122 instance: {
123 name: CONFIG.INSTANCE.NAME,
124 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
125 description: CONFIG.INSTANCE.DESCRIPTION,
126 terms: CONFIG.INSTANCE.TERMS
127 }
128 }
129
130 return res.json(about).end()
131 }
132
133 async function getCustomConfig (req: express.Request, res: express.Response, next: express.NextFunction) {
134 const data = customConfig()
135
136 return res.json(data).end()
137 }
138
139 async function deleteCustomConfig (req: express.Request, res: express.Response, next: express.NextFunction) {
140 await remove(CONFIG.CUSTOM_FILE)
141
142 auditLogger.delete(getAuditIdFromRes(res), new CustomConfigAuditView(customConfig()))
143
144 reloadConfig()
145 ClientHtml.invalidCache()
146
147 const data = customConfig()
148
149 return res.json(data).end()
150 }
151
152 async function updateCustomConfig (req: express.Request, res: express.Response, next: express.NextFunction) {
153 const toUpdate: CustomConfig = req.body
154 const oldCustomConfigAuditKeys = new CustomConfigAuditView(customConfig())
155
156 // Force number conversion
157 toUpdate.cache.previews.size = parseInt('' + toUpdate.cache.previews.size, 10)
158 toUpdate.cache.captions.size = parseInt('' + toUpdate.cache.captions.size, 10)
159 toUpdate.signup.limit = parseInt('' + toUpdate.signup.limit, 10)
160 toUpdate.user.videoQuota = parseInt('' + toUpdate.user.videoQuota, 10)
161 toUpdate.user.videoQuotaDaily = parseInt('' + toUpdate.user.videoQuotaDaily, 10)
162 toUpdate.transcoding.threads = parseInt('' + toUpdate.transcoding.threads, 10)
163
164 // camelCase to snake_case key
165 const toUpdateJSON = omit(
166 toUpdate,
167 'user.videoQuota',
168 'instance.defaultClientRoute',
169 'instance.shortDescription',
170 'cache.videoCaptions',
171 'signup.requiresEmailVerification'
172 )
173 toUpdateJSON.user['video_quota'] = toUpdate.user.videoQuota
174 toUpdateJSON.user['video_quota_daily'] = toUpdate.user.videoQuotaDaily
175 toUpdateJSON.instance['default_client_route'] = toUpdate.instance.defaultClientRoute
176 toUpdateJSON.instance['short_description'] = toUpdate.instance.shortDescription
177 toUpdateJSON.instance['default_nsfw_policy'] = toUpdate.instance.defaultNSFWPolicy
178 toUpdateJSON.signup['requires_email_verification'] = toUpdate.signup.requiresEmailVerification
179
180 await writeJSON(CONFIG.CUSTOM_FILE, toUpdateJSON, { spaces: 2 })
181
182 reloadConfig()
183 ClientHtml.invalidCache()
184
185 const data = customConfig()
186
187 auditLogger.update(
188 getAuditIdFromRes(res),
189 new CustomConfigAuditView(data),
190 oldCustomConfigAuditKeys
191 )
192
193 return res.json(data).end()
194 }
195
196 // ---------------------------------------------------------------------------
197
198 export {
199 configRouter
200 }
201
202 // ---------------------------------------------------------------------------
203
204 function customConfig (): CustomConfig {
205 return {
206 instance: {
207 name: CONFIG.INSTANCE.NAME,
208 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
209 description: CONFIG.INSTANCE.DESCRIPTION,
210 terms: CONFIG.INSTANCE.TERMS,
211 defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
212 defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
213 customizations: {
214 css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS,
215 javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT
216 }
217 },
218 services: {
219 twitter: {
220 username: CONFIG.SERVICES.TWITTER.USERNAME,
221 whitelisted: CONFIG.SERVICES.TWITTER.WHITELISTED
222 }
223 },
224 cache: {
225 previews: {
226 size: CONFIG.CACHE.PREVIEWS.SIZE
227 },
228 captions: {
229 size: CONFIG.CACHE.VIDEO_CAPTIONS.SIZE
230 }
231 },
232 signup: {
233 enabled: CONFIG.SIGNUP.ENABLED,
234 limit: CONFIG.SIGNUP.LIMIT,
235 requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION
236 },
237 admin: {
238 email: CONFIG.ADMIN.EMAIL
239 },
240 user: {
241 videoQuota: CONFIG.USER.VIDEO_QUOTA,
242 videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY
243 },
244 transcoding: {
245 enabled: CONFIG.TRANSCODING.ENABLED,
246 threads: CONFIG.TRANSCODING.THREADS,
247 resolutions: {
248 '240p': CONFIG.TRANSCODING.RESOLUTIONS[ '240p' ],
249 '360p': CONFIG.TRANSCODING.RESOLUTIONS[ '360p' ],
250 '480p': CONFIG.TRANSCODING.RESOLUTIONS[ '480p' ],
251 '720p': CONFIG.TRANSCODING.RESOLUTIONS[ '720p' ],
252 '1080p': CONFIG.TRANSCODING.RESOLUTIONS[ '1080p' ]
253 }
254 },
255 import: {
256 videos: {
257 http: {
258 enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED
259 },
260 torrent: {
261 enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED
262 }
263 }
264 }
265 }
266 }