Ver código fonte

Inject server config in HTML

Chocobozzz 3 anos atrás
pai
commit
aea0b0e7cd

+ 4 - 8
client/src/app/+videos/video-list/trending/video-trending-header.component.ts

@@ -31,7 +31,8 @@ export class VideoTrendingHeaderComponent extends VideoListHeaderComponent imple
     private route: ActivatedRoute,
     private router: Router,
     private auth: AuthService,
-    private serverService: ServerService
+    private serverService: ServerService,
+    private redirectService: RedirectService
   ) {
     super(data)
 
@@ -84,12 +85,7 @@ export class VideoTrendingHeaderComponent extends VideoListHeaderComponent imple
 
     this.algorithmChangeSub = this.route.queryParams.subscribe(
       queryParams => {
-        const algorithm = queryParams['alg']
-        if (algorithm) {
-          this.data.model = algorithm
-        } else {
-          this.data.model = RedirectService.DEFAULT_TRENDING_ALGORITHM
-        }
+        this.data.model = queryParams['alg'] || this.redirectService.getDefaultTrendingAlgorithm()
       }
     )
   }
@@ -99,7 +95,7 @@ export class VideoTrendingHeaderComponent extends VideoListHeaderComponent imple
   }
 
   setSort () {
-    const alg = this.data.model !== RedirectService.DEFAULT_TRENDING_ALGORITHM
+    const alg = this.data.model !== this.redirectService.getDefaultTrendingAlgorithm()
       ? this.data.model
       : undefined
 

+ 5 - 2
client/src/app/+videos/video-list/trending/video-trending.component.ts

@@ -35,11 +35,12 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
     protected storageService: LocalStorageService,
     protected cfr: ComponentFactoryResolver,
     private videoService: VideoService,
+    private redirectService: RedirectService,
     private hooks: HooksService
   ) {
     super()
 
-    this.defaultSort = this.parseAlgorithm(RedirectService.DEFAULT_TRENDING_ALGORITHM)
+    this.defaultSort = this.parseAlgorithm(this.redirectService.getDefaultTrendingAlgorithm())
 
     this.headerComponentInjector = this.getInjector()
   }
@@ -106,7 +107,7 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
   }
 
   protected loadPageRouteParams (queryParams: Params) {
-    const algorithm = queryParams['alg'] || RedirectService.DEFAULT_TRENDING_ALGORITHM
+    const algorithm = queryParams['alg'] || this.redirectService.getDefaultTrendingAlgorithm()
 
     this.sort = this.parseAlgorithm(algorithm)
   }
@@ -115,8 +116,10 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
     switch (algorithm) {
       case 'most-viewed':
         return '-trending'
+
       case 'most-liked':
         return '-likes'
+
       default:
         return '-' + algorithm as VideoSortField
     }

+ 1 - 1
client/src/app/app.component.ts

@@ -67,7 +67,7 @@ export class AppComponent implements OnInit, AfterViewInit {
   }
 
   goToDefaultRoute () {
-    return this.router.navigateByUrl(RedirectService.DEFAULT_ROUTE)
+    return this.router.navigateByUrl(this.redirectService.getDefaultRoute())
   }
 
   ngOnInit () {

+ 19 - 16
client/src/app/core/routing/redirect.service.ts

@@ -6,14 +6,14 @@ import { ServerService } from '../server'
 export class RedirectService {
   // Default route could change according to the instance configuration
   static INIT_DEFAULT_ROUTE = '/videos/trending'
-  static DEFAULT_ROUTE = RedirectService.INIT_DEFAULT_ROUTE
   static INIT_DEFAULT_TRENDING_ALGORITHM = 'most-viewed'
-  static DEFAULT_TRENDING_ALGORITHM = RedirectService.INIT_DEFAULT_TRENDING_ALGORITHM
 
   private previousUrl: string
   private currentUrl: string
 
   private redirectingToHomepage = false
+  private defaultTrendingAlgorithm = RedirectService.INIT_DEFAULT_TRENDING_ALGORITHM
+  private defaultRoute = RedirectService.INIT_DEFAULT_ROUTE
 
   constructor (
     private router: Router,
@@ -22,10 +22,10 @@ export class RedirectService {
     // The config is first loaded from the cache so try to get the default route
     const tmpConfig = this.serverService.getTmpConfig()
     if (tmpConfig?.instance?.defaultClientRoute) {
-      RedirectService.DEFAULT_ROUTE = tmpConfig.instance.defaultClientRoute
+      this.defaultRoute = tmpConfig.instance.defaultClientRoute
     }
     if (tmpConfig?.trending?.videos?.algorithms?.default) {
-      RedirectService.DEFAULT_TRENDING_ALGORITHM = tmpConfig.trending.videos.algorithms.default
+      this.defaultTrendingAlgorithm = tmpConfig.trending.videos.algorithms.default
     }
 
     // Load default route
@@ -34,13 +34,8 @@ export class RedirectService {
           const defaultRouteConfig = config.instance.defaultClientRoute
           const defaultTrendingConfig = config.trending.videos.algorithms.default
 
-          if (defaultRouteConfig) {
-            RedirectService.DEFAULT_ROUTE = defaultRouteConfig
-          }
-
-          if (defaultTrendingConfig) {
-            RedirectService.DEFAULT_TRENDING_ALGORITHM = defaultTrendingConfig
-          }
+          if (defaultRouteConfig) this.defaultRoute = defaultRouteConfig
+          if (defaultTrendingConfig) this.defaultTrendingAlgorithm = defaultTrendingConfig
         })
 
     // Track previous url
@@ -53,6 +48,14 @@ export class RedirectService {
     })
   }
 
+  getDefaultRoute () {
+    return this.defaultRoute
+  }
+
+  getDefaultTrendingAlgorithm () {
+    return this.defaultTrendingAlgorithm
+  }
+
   redirectToPreviousRoute () {
     const exceptions = [
       '/verify-account',
@@ -72,21 +75,21 @@ export class RedirectService {
 
     this.redirectingToHomepage = true
 
-    console.log('Redirecting to %s...', RedirectService.DEFAULT_ROUTE)
+    console.log('Redirecting to %s...', this.defaultRoute)
 
-    this.router.navigateByUrl(RedirectService.DEFAULT_ROUTE, { skipLocationChange })
+    this.router.navigateByUrl(this.defaultRoute, { skipLocationChange })
         .then(() => this.redirectingToHomepage = false)
         .catch(() => {
           this.redirectingToHomepage = false
 
           console.error(
             'Cannot navigate to %s, resetting default route to %s.',
-            RedirectService.DEFAULT_ROUTE,
+            this.defaultRoute,
             RedirectService.INIT_DEFAULT_ROUTE
           )
 
-          RedirectService.DEFAULT_ROUTE = RedirectService.INIT_DEFAULT_ROUTE
-          return this.router.navigateByUrl(RedirectService.DEFAULT_ROUTE, { skipLocationChange })
+          this.defaultRoute = RedirectService.INIT_DEFAULT_ROUTE
+          return this.router.navigateByUrl(this.defaultRoute, { skipLocationChange })
         })
 
   }

+ 8 - 17
client/src/app/core/server/server.service.ts

@@ -3,7 +3,6 @@ import { first, map, share, shareReplay, switchMap, tap } from 'rxjs/operators'
 import { HttpClient } from '@angular/common/http'
 import { Inject, Injectable, LOCALE_ID } from '@angular/core'
 import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers'
-import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
 import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n'
 import { SearchTargetType, ServerConfig, ServerStats, VideoConstant } from '@shared/models'
 import { environment } from '../../../environments/environment'
@@ -16,8 +15,6 @@ export class ServerService {
   private static BASE_LOCALE_URL = environment.apiUrl + '/client/locales/'
   private static BASE_STATS_URL = environment.apiUrl + '/api/v1/server/stats'
 
-  private static CONFIG_LOCAL_STORAGE_KEY = 'server-config'
-
   configReloaded = new Subject<ServerConfig>()
 
   private localeObservable: Observable<any>
@@ -212,7 +209,6 @@ export class ServerService {
     if (!this.configObservable) {
       this.configObservable = this.http.get<ServerConfig>(ServerService.BASE_CONFIG_URL)
                                   .pipe(
-                                    tap(config => this.saveConfigLocally(config)),
                                     tap(config => {
                                       this.config = config
                                       this.configLoaded = true
@@ -343,20 +339,15 @@ export class ServerService {
                )
   }
 
-  private saveConfigLocally (config: ServerConfig) {
-    peertubeLocalStorage.setItem(ServerService.CONFIG_LOCAL_STORAGE_KEY, JSON.stringify(config))
-  }
-
   private loadConfigLocally () {
-    const configString = peertubeLocalStorage.getItem(ServerService.CONFIG_LOCAL_STORAGE_KEY)
-
-    if (configString) {
-      try {
-        const parsed = JSON.parse(configString)
-        Object.assign(this.config, parsed)
-      } catch (err) {
-        console.error('Cannot parse config saved in local storage.', err)
-      }
+    const configString = window['PeerTubeServerConfig']
+    if (!configString) return
+
+    try {
+      const parsed = JSON.parse(configString)
+      Object.assign(this.config, parsed)
+    } catch (err) {
+      console.error('Cannot parse config saved in from index.html.', err)
     }
   }
 }

+ 1 - 0
client/src/index.html

@@ -29,6 +29,7 @@
     <!-- description tag -->
     <!-- custom css tag -->
     <!-- meta tags -->
+    <!-- server config -->
 
     <!-- /!\ Do not remove it /!\ -->
   </head>

+ 10 - 2
client/src/standalone/videos/embed.html

@@ -1,14 +1,22 @@
 <!DOCTYPE html>
 <html>
   <head>
-    <!-- title tag -->
-
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <meta name="robots" content="noindex">
     <meta property="og:platform" content="PeerTube" />
 
+
+    <!-- /!\ The following comment is used by the server to prerender some tags /!\ -->
+
+    <!-- title tag -->
+    <!-- description tag -->
     <!-- custom css tag -->
+    <!-- meta tags -->
+    <!-- server config -->
+
+    <!-- /!\ Do not remove it /!\ -->
+
     <link rel="icon" type="image/png" href="/client/assets/images/favicon.png" />
   </head>
 

+ 29 - 23
client/src/standalone/videos/embed.ts

@@ -1,28 +1,28 @@
 import './embed.scss'
 import videojs from 'video.js'
 import { peertubeTranslate } from '../../../../shared/core-utils/i18n'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 import {
+  ClientHookName,
+  HTMLServerConfig,
+  PluginType,
   ResultList,
-  ServerConfig,
   UserRefreshToken,
   VideoCaption,
   VideoDetails,
   VideoPlaylist,
   VideoPlaylistElement,
-  VideoStreamingPlaylistType,
-  PluginType,
-  ClientHookName
+  VideoStreamingPlaylistType
 } from '../../../../shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 import { P2PMediaLoaderOptions, PeertubePlayerManagerOptions, PlayerMode } from '../../assets/player/peertube-player-manager'
 import { VideoJSCaption } from '../../assets/player/peertube-videojs-typings'
 import { TranslationsManager } from '../../assets/player/translations-manager'
+import { peertubeLocalStorage } from '../../root-helpers/peertube-web-storage'
 import { Hooks, loadPlugin, runHook } from '../../root-helpers/plugins'
 import { Tokens } from '../../root-helpers/users'
-import { peertubeLocalStorage } from '../../root-helpers/peertube-web-storage'
 import { objectToUrlEncoded } from '../../root-helpers/utils'
-import { PeerTubeEmbedApi } from './embed-api'
 import { RegisterClientHelpers } from '../../types/register-client-option.model'
+import { PeerTubeEmbedApi } from './embed-api'
 
 type Translations = { [ id: string ]: string }
 
@@ -56,8 +56,9 @@ export class PeerTubeEmbed {
     CLIENT_SECRET: 'client_secret'
   }
 
+  config: HTMLServerConfig
+
   private translationsPromise: Promise<{ [id: string]: string }>
-  private configPromise: Promise<ServerConfig>
   private PeertubePlayerManagerModulePromise: Promise<any>
 
   private playlist: VideoPlaylist
@@ -77,6 +78,12 @@ export class PeerTubeEmbed {
 
   constructor (private videoWrapperId: string) {
     this.wrapperElement = document.getElementById(this.videoWrapperId)
+
+    try {
+      this.config = JSON.parse(window['PeerTubeServerConfig'])
+    } catch (err) {
+      console.error('Cannot parse HTML config.', err)
+    }
   }
 
   getVideoUrl (id: string) {
@@ -166,11 +173,6 @@ export class PeerTubeEmbed {
     return this.refreshFetch(url.toString(), { headers: this.headers })
   }
 
-  loadConfig (): Promise<ServerConfig> {
-    return this.refreshFetch('/api/v1/config')
-      .then(res => res.json())
-  }
-
   removeElement (element: HTMLElement) {
     element.parentElement.removeChild(element)
   }
@@ -466,6 +468,12 @@ export class PeerTubeEmbed {
     this.playerElement.setAttribute('playsinline', 'true')
     this.wrapperElement.appendChild(this.playerElement)
 
+    // Issue when we parsed config from HTML, fallback to API
+    if (!this.config) {
+      this.config = await this.refreshFetch('/api/v1/config')
+                              .then(res => res.json())
+    }
+
     const videoInfoPromise = videoResponse.json()
       .then((videoInfo: VideoDetails) => {
         if (!alreadyHadPlayer) this.loadPlaceholder(videoInfo)
@@ -473,15 +481,14 @@ export class PeerTubeEmbed {
         return videoInfo
       })
 
-    const [ videoInfoTmp, serverTranslations, captionsResponse, config, PeertubePlayerManagerModule ] = await Promise.all([
+    const [ videoInfoTmp, serverTranslations, captionsResponse, PeertubePlayerManagerModule ] = await Promise.all([
       videoInfoPromise,
       this.translationsPromise,
       captionsPromise,
-      this.configPromise,
       this.PeertubePlayerManagerModulePromise
     ])
 
-    await this.ensurePluginsAreLoaded(config, serverTranslations)
+    await this.ensurePluginsAreLoaded(serverTranslations)
 
     const videoInfo: VideoDetails = videoInfoTmp
 
@@ -576,7 +583,7 @@ export class PeerTubeEmbed {
 
     this.buildCSS()
 
-    await this.buildDock(videoInfo, config)
+    await this.buildDock(videoInfo)
 
     this.initializeApi()
 
@@ -598,7 +605,6 @@ export class PeerTubeEmbed {
   private async initCore () {
     if (this.userTokens) this.setHeadersFromTokens()
 
-    this.configPromise = this.loadConfig()
     this.translationsPromise = TranslationsManager.getServerTranslations(window.location.origin, navigator.language)
     this.PeertubePlayerManagerModulePromise = import('../../assets/player/peertube-player-manager')
 
@@ -653,7 +659,7 @@ export class PeerTubeEmbed {
     }
   }
 
-  private async buildDock (videoInfo: VideoDetails, config: ServerConfig) {
+  private async buildDock (videoInfo: VideoDetails) {
     if (!this.controls) return
 
     // On webtorrent fallback, player may have been disposed
@@ -661,7 +667,7 @@ export class PeerTubeEmbed {
 
     const title = this.title ? videoInfo.name : undefined
 
-    const description = config.tracker.enabled && this.warningTitle
+    const description = this.config.tracker.enabled && this.warningTitle
       ? '<span class="text">' + peertubeTranslate('Watching this video may reveal your IP address to others.') + '</span>'
       : undefined
 
@@ -733,10 +739,10 @@ export class PeerTubeEmbed {
     return window.location.pathname.split('/')[1] === 'video-playlists'
   }
 
-  private async ensurePluginsAreLoaded (config: ServerConfig, translations?: { [ id: string ]: string }) {
-    if (config.plugin.registered.length === 0) return
+  private async ensurePluginsAreLoaded (translations?: { [ id: string ]: string }) {
+    if (this.config.plugin.registered.length === 0) return
 
-    for (const plugin of config.plugin.registered) {
+    for (const plugin of this.config.plugin.registered) {
       for (const key of Object.keys(plugin.clientScripts)) {
         const clientScript = plugin.clientScripts[key]
 

+ 2 - 1
server/initializers/constants.ts

@@ -702,7 +702,8 @@ const CUSTOM_HTML_TAG_COMMENTS = {
   TITLE: '<!-- title tag -->',
   DESCRIPTION: '<!-- description tag -->',
   CUSTOM_CSS: '<!-- custom css tag -->',
-  META_TAGS: '<!-- meta tags -->'
+  META_TAGS: '<!-- meta tags -->',
+  SERVER_CONFIG: '<!-- server config -->'
 }
 
 // ---------------------------------------------------------------------------

+ 16 - 2
server/lib/client-html.ts

@@ -2,12 +2,14 @@ import * as express from 'express'
 import { readFile } from 'fs-extra'
 import { join } from 'path'
 import validator from 'validator'
+import { escapeHTML } from '@shared/core-utils/renderer'
+import { HTMLServerConfig } from '@shared/models'
 import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
 import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
 import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos'
 import { isTestInstance, sha256 } from '../helpers/core-utils'
-import { escapeHTML } from '@shared/core-utils/renderer'
 import { logger } from '../helpers/logger'
+import { mdToPlainText } from '../helpers/markdown'
 import { CONFIG } from '../initializers/config'
 import {
   ACCEPT_HEADERS,
@@ -24,7 +26,7 @@ import { VideoChannelModel } from '../models/video/video-channel'
 import { getActivityStreamDuration } from '../models/video/video-format-utils'
 import { VideoPlaylistModel } from '../models/video/video-playlist'
 import { MAccountActor, MChannelActor } from '../types/models'
-import { mdToPlainText } from '../helpers/markdown'
+import { getHTMLServerConfig } from './config'
 
 type Tags = {
   ogType: string
@@ -209,11 +211,14 @@ class ClientHtml {
     if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path]
 
     const buffer = await readFile(path)
+    const serverConfig = await getHTMLServerConfig()
 
     let html = buffer.toString()
     html = await ClientHtml.addAsyncPluginCSS(html)
     html = ClientHtml.addCustomCSS(html)
     html = ClientHtml.addTitleTag(html)
+    html = ClientHtml.addDescriptionTag(html)
+    html = ClientHtml.addServerConfig(html, serverConfig)
 
     ClientHtml.htmlCache[path] = html
 
@@ -275,6 +280,7 @@ class ClientHtml {
     if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path]
 
     const buffer = await readFile(path)
+    const serverConfig = await getHTMLServerConfig()
 
     let html = buffer.toString()
 
@@ -283,6 +289,7 @@ class ClientHtml {
     html = ClientHtml.addFaviconContentHash(html)
     html = ClientHtml.addLogoContentHash(html)
     html = ClientHtml.addCustomCSS(html)
+    html = ClientHtml.addServerConfig(html, serverConfig)
     html = await ClientHtml.addAsyncPluginCSS(html)
 
     ClientHtml.htmlCache[path] = html
@@ -355,6 +362,13 @@ class ClientHtml {
     return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.CUSTOM_CSS, styleTag)
   }
 
+  private static addServerConfig (htmlStringPage: string, serverConfig: HTMLServerConfig) {
+    const serverConfigString = JSON.stringify(serverConfig)
+    const configScriptTag = `<script type="application/javascript">window.PeerTubeServerConfig = '${serverConfigString}'</script>`
+
+    return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.SERVER_CONFIG, configScriptTag)
+  }
+
   private static async addAsyncPluginCSS (htmlStringPage: string) {
     const globalCSSContent = await readFile(PLUGIN_GLOBAL_CSS_PATH)
     if (globalCSSContent.byteLength === 0) return htmlStringPage

+ 20 - 11
server/lib/config.ts

@@ -2,17 +2,13 @@ import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/helpers/si
 import { getServerCommit } from '@server/helpers/utils'
 import { CONFIG, isEmailEnabled } from '@server/initializers/config'
 import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants'
-import { RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models'
+import { HTMLServerConfig, RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models'
 import { Hooks } from './plugins/hooks'
 import { PluginManager } from './plugins/plugin-manager'
 import { getThemeOrDefault } from './plugins/theme-utils'
 import { VideoTranscodingProfilesManager } from './transcoding/video-transcoding-profiles'
 
-let serverCommit: string
-
 async function getServerConfig (ip?: string): Promise<ServerConfig> {
-  if (serverCommit === undefined) serverCommit = await getServerCommit()
-
   const { allowed } = await Hooks.wrapPromiseFun(
     isSignupAllowed,
     {
@@ -22,6 +18,23 @@ async function getServerConfig (ip?: string): Promise<ServerConfig> {
   )
 
   const allowedForCurrentIP = isSignupAllowedForCurrentIP(ip)
+
+  const signup = {
+    allowed,
+    allowedForCurrentIP,
+    requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION
+  }
+
+  const htmlConfig = await getHTMLServerConfig()
+
+  return { ...htmlConfig, signup }
+}
+
+// Config injected in HTML
+let serverCommit: string
+async function getHTMLServerConfig (): Promise<HTMLServerConfig> {
+  if (serverCommit === undefined) serverCommit = await getServerCommit()
+
   const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME)
 
   return {
@@ -65,11 +78,6 @@ async function getServerConfig (ip?: string): Promise<ServerConfig> {
     },
     serverVersion: PEERTUBE_VERSION,
     serverCommit,
-    signup: {
-      allowed,
-      allowedForCurrentIP,
-      requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION
-    },
     transcoding: {
       hls: {
         enabled: CONFIG.TRANSCODING.HLS.ENABLED
@@ -223,7 +231,8 @@ export {
   getServerConfig,
   getRegisteredThemes,
   getEnabledResolutions,
-  getRegisteredPlugins
+  getRegisteredPlugins,
+  getHTMLServerConfig
 }
 
 // ---------------------------------------------------------------------------

+ 1 - 2
server/models/abuse/abuse.ts

@@ -16,8 +16,7 @@ import {
   UpdatedAt
 } from 'sequelize-typescript'
 import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses'
-import { AttributesOnly } from '@shared/core-utils'
-import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse'
+import { abusePredefinedReasonsMap, AttributesOnly } from '@shared/core-utils'
 import {
   AbuseFilter,
   AbuseObject,

+ 23 - 5
server/tests/client.ts

@@ -3,7 +3,7 @@
 import 'mocha'
 import * as chai from 'chai'
 import * as request from 'supertest'
-import { Account, VideoPlaylistPrivacy } from '@shared/models'
+import { Account, HTMLServerConfig, ServerConfig, VideoPlaylistPrivacy } from '@shared/models'
 import {
   addVideoInPlaylist,
   cleanupTests,
@@ -11,6 +11,7 @@ import {
   doubleFollow,
   flushAndRunMultipleServers,
   getAccount,
+  getConfig,
   getCustomConfig,
   getVideosList,
   makeHTMLRequest,
@@ -25,13 +26,17 @@ import {
   waitJobs
 } from '../../shared/extra-utils'
 import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { omit } from 'lodash'
 
 const expect = chai.expect
 
-function checkIndexTags (html: string, title: string, description: string, css: string) {
+function checkIndexTags (html: string, title: string, description: string, css: string, config: ServerConfig) {
   expect(html).to.contain('<title>' + title + '</title>')
   expect(html).to.contain('<meta name="description" content="' + description + '" />')
   expect(html).to.contain('<style class="custom-css-style">' + css + '</style>')
+
+  const htmlConfig: HTMLServerConfig = omit(config, 'signup')
+  expect(html).to.contain(`<script type="application/javascript">window.PeerTubeServerConfig = '${JSON.stringify(htmlConfig)}'</script>`)
 }
 
 describe('Test a client controllers', function () {
@@ -296,10 +301,11 @@ describe('Test a client controllers', function () {
   describe('Index HTML', function () {
 
     it('Should have valid index html tags (title, description...)', async function () {
+      const resConfig = await getConfig(servers[0].url)
       const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
 
       const description = 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
-      checkIndexTags(res.text, 'PeerTube', description, '')
+      checkIndexTags(res.text, 'PeerTube', description, '', resConfig.body)
     })
 
     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 () {
         }
       })
 
+      const resConfig = await getConfig(servers[0].url)
       const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
 
-      checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }')
+      checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
     })
 
     it('Should have valid index html updated tags (title, description...)', async function () {
+      const resConfig = await getConfig(servers[0].url)
       const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
 
-      checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }')
+      checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
     })
 
     it('Should use the original video URL for the canonical tag', async function () {
@@ -350,6 +358,16 @@ describe('Test a client controllers', function () {
     })
   })
 
+  describe('Embed HTML', function () {
+
+    it('Should have the correct embed html tags', async function () {
+      const resConfig = await getConfig(servers[0].url)
+      const res = await makeHTMLRequest(servers[0].url, servers[0].video.embedPath)
+
+      checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
+    })
+  })
+
   after(async function () {
     await cleanupTests(servers)
   })

+ 3 - 0
shared/extra-utils/server/servers.ts

@@ -45,9 +45,12 @@ interface ServerInfo {
     uuid: string
     name?: string
     url?: string
+
     account?: {
       name: string
     }
+
+    embedPath?: string
   }
 
   remoteVideo?: {

+ 2 - 0
shared/models/server/server-config.model.ts

@@ -215,3 +215,5 @@ export interface ServerConfig {
     dismissable: boolean
   }
 }
+
+export type HTMLServerConfig = Omit<ServerConfig, 'signup'>