aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-05-14 12:04:44 +0200
committerChocobozzz <me@florianbigard.com>2021-05-14 13:37:23 +0200
commitaea0b0e7cde7495e60fe07b4444067f53d35ce3f (patch)
tree61d1e161bb32be144d46b9f5f51f1386e6819b0b /server
parentc76ecc3ff746d78519404db4c525fd024f9a51c0 (diff)
downloadPeerTube-aea0b0e7cde7495e60fe07b4444067f53d35ce3f.tar.gz
PeerTube-aea0b0e7cde7495e60fe07b4444067f53d35ce3f.tar.zst
PeerTube-aea0b0e7cde7495e60fe07b4444067f53d35ce3f.zip
Inject server config in HTML
Diffstat (limited to 'server')
-rw-r--r--server/initializers/constants.ts3
-rw-r--r--server/lib/client-html.ts18
-rw-r--r--server/lib/config.ts31
-rw-r--r--server/models/abuse/abuse.ts3
-rw-r--r--server/tests/client.ts28
5 files changed, 62 insertions, 21 deletions
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 6f388420e..4cf7dcf0a 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -702,7 +702,8 @@ const CUSTOM_HTML_TAG_COMMENTS = {
702 TITLE: '<!-- title tag -->', 702 TITLE: '<!-- title tag -->',
703 DESCRIPTION: '<!-- description tag -->', 703 DESCRIPTION: '<!-- description tag -->',
704 CUSTOM_CSS: '<!-- custom css tag -->', 704 CUSTOM_CSS: '<!-- custom css tag -->',
705 META_TAGS: '<!-- meta tags -->' 705 META_TAGS: '<!-- meta tags -->',
706 SERVER_CONFIG: '<!-- server config -->'
706} 707}
707 708
708// --------------------------------------------------------------------------- 709// ---------------------------------------------------------------------------
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts
index 203bd3893..85fdc8754 100644
--- a/server/lib/client-html.ts
+++ b/server/lib/client-html.ts
@@ -2,12 +2,14 @@ import * as express from 'express'
2import { readFile } from 'fs-extra' 2import { readFile } from 'fs-extra'
3import { join } from 'path' 3import { join } from 'path'
4import validator from 'validator' 4import validator from 'validator'
5import { escapeHTML } from '@shared/core-utils/renderer'
6import { HTMLServerConfig } from '@shared/models'
5import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n' 7import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
6import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' 8import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
7import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos' 9import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos'
8import { isTestInstance, sha256 } from '../helpers/core-utils' 10import { isTestInstance, sha256 } from '../helpers/core-utils'
9import { escapeHTML } from '@shared/core-utils/renderer'
10import { logger } from '../helpers/logger' 11import { logger } from '../helpers/logger'
12import { mdToPlainText } from '../helpers/markdown'
11import { CONFIG } from '../initializers/config' 13import { CONFIG } from '../initializers/config'
12import { 14import {
13 ACCEPT_HEADERS, 15 ACCEPT_HEADERS,
@@ -24,7 +26,7 @@ import { VideoChannelModel } from '../models/video/video-channel'
24import { getActivityStreamDuration } from '../models/video/video-format-utils' 26import { getActivityStreamDuration } from '../models/video/video-format-utils'
25import { VideoPlaylistModel } from '../models/video/video-playlist' 27import { VideoPlaylistModel } from '../models/video/video-playlist'
26import { MAccountActor, MChannelActor } from '../types/models' 28import { MAccountActor, MChannelActor } from '../types/models'
27import { mdToPlainText } from '../helpers/markdown' 29import { getHTMLServerConfig } from './config'
28 30
29type Tags = { 31type Tags = {
30 ogType: string 32 ogType: string
@@ -209,11 +211,14 @@ class ClientHtml {
209 if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path] 211 if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path]
210 212
211 const buffer = await readFile(path) 213 const buffer = await readFile(path)
214 const serverConfig = await getHTMLServerConfig()
212 215
213 let html = buffer.toString() 216 let html = buffer.toString()
214 html = await ClientHtml.addAsyncPluginCSS(html) 217 html = await ClientHtml.addAsyncPluginCSS(html)
215 html = ClientHtml.addCustomCSS(html) 218 html = ClientHtml.addCustomCSS(html)
216 html = ClientHtml.addTitleTag(html) 219 html = ClientHtml.addTitleTag(html)
220 html = ClientHtml.addDescriptionTag(html)
221 html = ClientHtml.addServerConfig(html, serverConfig)
217 222
218 ClientHtml.htmlCache[path] = html 223 ClientHtml.htmlCache[path] = html
219 224
@@ -275,6 +280,7 @@ class ClientHtml {
275 if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path] 280 if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path]
276 281
277 const buffer = await readFile(path) 282 const buffer = await readFile(path)
283 const serverConfig = await getHTMLServerConfig()
278 284
279 let html = buffer.toString() 285 let html = buffer.toString()
280 286
@@ -283,6 +289,7 @@ class ClientHtml {
283 html = ClientHtml.addFaviconContentHash(html) 289 html = ClientHtml.addFaviconContentHash(html)
284 html = ClientHtml.addLogoContentHash(html) 290 html = ClientHtml.addLogoContentHash(html)
285 html = ClientHtml.addCustomCSS(html) 291 html = ClientHtml.addCustomCSS(html)
292 html = ClientHtml.addServerConfig(html, serverConfig)
286 html = await ClientHtml.addAsyncPluginCSS(html) 293 html = await ClientHtml.addAsyncPluginCSS(html)
287 294
288 ClientHtml.htmlCache[path] = html 295 ClientHtml.htmlCache[path] = html
@@ -355,6 +362,13 @@ class ClientHtml {
355 return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.CUSTOM_CSS, styleTag) 362 return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.CUSTOM_CSS, styleTag)
356 } 363 }
357 364
365 private static addServerConfig (htmlStringPage: string, serverConfig: HTMLServerConfig) {
366 const serverConfigString = JSON.stringify(serverConfig)
367 const configScriptTag = `<script type="application/javascript">window.PeerTubeServerConfig = '${serverConfigString}'</script>`
368
369 return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.SERVER_CONFIG, configScriptTag)
370 }
371
358 private static async addAsyncPluginCSS (htmlStringPage: string) { 372 private static async addAsyncPluginCSS (htmlStringPage: string) {
359 const globalCSSContent = await readFile(PLUGIN_GLOBAL_CSS_PATH) 373 const globalCSSContent = await readFile(PLUGIN_GLOBAL_CSS_PATH)
360 if (globalCSSContent.byteLength === 0) return htmlStringPage 374 if (globalCSSContent.byteLength === 0) return htmlStringPage
diff --git a/server/lib/config.ts b/server/lib/config.ts
index fed468fe1..18d49f05a 100644
--- a/server/lib/config.ts
+++ b/server/lib/config.ts
@@ -2,17 +2,13 @@ import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/helpers/si
2import { getServerCommit } from '@server/helpers/utils' 2import { getServerCommit } from '@server/helpers/utils'
3import { CONFIG, isEmailEnabled } from '@server/initializers/config' 3import { CONFIG, isEmailEnabled } from '@server/initializers/config'
4import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants' 4import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants'
5import { RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models' 5import { HTMLServerConfig, RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models'
6import { Hooks } from './plugins/hooks' 6import { Hooks } from './plugins/hooks'
7import { PluginManager } from './plugins/plugin-manager' 7import { PluginManager } from './plugins/plugin-manager'
8import { getThemeOrDefault } from './plugins/theme-utils' 8import { getThemeOrDefault } from './plugins/theme-utils'
9import { VideoTranscodingProfilesManager } from './transcoding/video-transcoding-profiles' 9import { VideoTranscodingProfilesManager } from './transcoding/video-transcoding-profiles'
10 10
11let serverCommit: string
12
13async function getServerConfig (ip?: string): Promise<ServerConfig> { 11async function getServerConfig (ip?: string): Promise<ServerConfig> {
14 if (serverCommit === undefined) serverCommit = await getServerCommit()
15
16 const { allowed } = await Hooks.wrapPromiseFun( 12 const { allowed } = await Hooks.wrapPromiseFun(
17 isSignupAllowed, 13 isSignupAllowed,
18 { 14 {
@@ -22,6 +18,23 @@ async function getServerConfig (ip?: string): Promise<ServerConfig> {
22 ) 18 )
23 19
24 const allowedForCurrentIP = isSignupAllowedForCurrentIP(ip) 20 const allowedForCurrentIP = isSignupAllowedForCurrentIP(ip)
21
22 const signup = {
23 allowed,
24 allowedForCurrentIP,
25 requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION
26 }
27
28 const htmlConfig = await getHTMLServerConfig()
29
30 return { ...htmlConfig, signup }
31}
32
33// Config injected in HTML
34let serverCommit: string
35async function getHTMLServerConfig (): Promise<HTMLServerConfig> {
36 if (serverCommit === undefined) serverCommit = await getServerCommit()
37
25 const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME) 38 const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME)
26 39
27 return { 40 return {
@@ -65,11 +78,6 @@ async function getServerConfig (ip?: string): Promise<ServerConfig> {
65 }, 78 },
66 serverVersion: PEERTUBE_VERSION, 79 serverVersion: PEERTUBE_VERSION,
67 serverCommit, 80 serverCommit,
68 signup: {
69 allowed,
70 allowedForCurrentIP,
71 requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION
72 },
73 transcoding: { 81 transcoding: {
74 hls: { 82 hls: {
75 enabled: CONFIG.TRANSCODING.HLS.ENABLED 83 enabled: CONFIG.TRANSCODING.HLS.ENABLED
@@ -223,7 +231,8 @@ export {
223 getServerConfig, 231 getServerConfig,
224 getRegisteredThemes, 232 getRegisteredThemes,
225 getEnabledResolutions, 233 getEnabledResolutions,
226 getRegisteredPlugins 234 getRegisteredPlugins,
235 getHTMLServerConfig
227} 236}
228 237
229// --------------------------------------------------------------------------- 238// ---------------------------------------------------------------------------
diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts
index ffe109c2f..3518f5c02 100644
--- a/server/models/abuse/abuse.ts
+++ b/server/models/abuse/abuse.ts
@@ -16,8 +16,7 @@ import {
16 UpdatedAt 16 UpdatedAt
17} from 'sequelize-typescript' 17} from 'sequelize-typescript'
18import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses' 18import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses'
19import { AttributesOnly } from '@shared/core-utils' 19import { abusePredefinedReasonsMap, AttributesOnly } from '@shared/core-utils'
20import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse'
21import { 20import {
22 AbuseFilter, 21 AbuseFilter,
23 AbuseObject, 22 AbuseObject,
diff --git a/server/tests/client.ts b/server/tests/client.ts
index 3c99bcd1f..a385edd26 100644
--- a/server/tests/client.ts
+++ b/server/tests/client.ts
@@ -3,7 +3,7 @@
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import * as request from 'supertest' 5import * as request from 'supertest'
6import { Account, VideoPlaylistPrivacy } from '@shared/models' 6import { Account, HTMLServerConfig, ServerConfig, VideoPlaylistPrivacy } from '@shared/models'
7import { 7import {
8 addVideoInPlaylist, 8 addVideoInPlaylist,
9 cleanupTests, 9 cleanupTests,
@@ -11,6 +11,7 @@ import {
11 doubleFollow, 11 doubleFollow,
12 flushAndRunMultipleServers, 12 flushAndRunMultipleServers,
13 getAccount, 13 getAccount,
14 getConfig,
14 getCustomConfig, 15 getCustomConfig,
15 getVideosList, 16 getVideosList,
16 makeHTMLRequest, 17 makeHTMLRequest,
@@ -25,13 +26,17 @@ import {
25 waitJobs 26 waitJobs
26} from '../../shared/extra-utils' 27} from '../../shared/extra-utils'
27import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' 28import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
29import { omit } from 'lodash'
28 30
29const expect = chai.expect 31const expect = chai.expect
30 32
31function checkIndexTags (html: string, title: string, description: string, css: string) { 33function checkIndexTags (html: string, title: string, description: string, css: string, config: ServerConfig) {
32 expect(html).to.contain('<title>' + title + '</title>') 34 expect(html).to.contain('<title>' + title + '</title>')
33 expect(html).to.contain('<meta name="description" content="' + description + '" />') 35 expect(html).to.contain('<meta name="description" content="' + description + '" />')
34 expect(html).to.contain('<style class="custom-css-style">' + css + '</style>') 36 expect(html).to.contain('<style class="custom-css-style">' + css + '</style>')
37
38 const htmlConfig: HTMLServerConfig = omit(config, 'signup')
39 expect(html).to.contain(`<script type="application/javascript">window.PeerTubeServerConfig = '${JSON.stringify(htmlConfig)}'</script>`)
35} 40}
36 41
37describe('Test a client controllers', function () { 42describe('Test a client controllers', function () {
@@ -296,10 +301,11 @@ describe('Test a client controllers', function () {
296 describe('Index HTML', function () { 301 describe('Index HTML', function () {
297 302
298 it('Should have valid index html tags (title, description...)', async function () { 303 it('Should have valid index html tags (title, description...)', async function () {
304 const resConfig = await getConfig(servers[0].url)
299 const res = await makeHTMLRequest(servers[0].url, '/videos/trending') 305 const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
300 306
301 const description = 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.' 307 const description = 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
302 checkIndexTags(res.text, 'PeerTube', description, '') 308 checkIndexTags(res.text, 'PeerTube', description, '', resConfig.body)
303 }) 309 })
304 310
305 it('Should update the customized configuration and have the correct index html tags', async function () { 311 it('Should update the customized configuration and have the correct index html tags', async function () {
@@ -318,15 +324,17 @@ describe('Test a client controllers', function () {
318 } 324 }
319 }) 325 })
320 326
327 const resConfig = await getConfig(servers[0].url)
321 const res = await makeHTMLRequest(servers[0].url, '/videos/trending') 328 const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
322 329
323 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }') 330 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
324 }) 331 })
325 332
326 it('Should have valid index html updated tags (title, description...)', async function () { 333 it('Should have valid index html updated tags (title, description...)', async function () {
334 const resConfig = await getConfig(servers[0].url)
327 const res = await makeHTMLRequest(servers[0].url, '/videos/trending') 335 const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
328 336
329 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }') 337 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
330 }) 338 })
331 339
332 it('Should use the original video URL for the canonical tag', async function () { 340 it('Should use the original video URL for the canonical tag', async function () {
@@ -350,6 +358,16 @@ describe('Test a client controllers', function () {
350 }) 358 })
351 }) 359 })
352 360
361 describe('Embed HTML', function () {
362
363 it('Should have the correct embed html tags', async function () {
364 const resConfig = await getConfig(servers[0].url)
365 const res = await makeHTMLRequest(servers[0].url, servers[0].video.embedPath)
366
367 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
368 })
369 })
370
353 after(async function () { 371 after(async function () {
354 await cleanupTests(servers) 372 await cleanupTests(servers)
355 }) 373 })