aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-07-10 14:06:19 +0200
committerChocobozzz <chocobozzz@cpy.re>2019-07-24 10:58:16 +0200
commitffb321bedca46d6987c7b31dd58e5dea96ea2ea2 (patch)
tree019f0427c1860ae0b00694c43f1be8d5fe1aa995 /server
parent7cd4d2ba10106c10602c86f74f55743ded588896 (diff)
downloadPeerTube-ffb321bedca46d6987c7b31dd58e5dea96ea2ea2.tar.gz
PeerTube-ffb321bedca46d6987c7b31dd58e5dea96ea2ea2.tar.zst
PeerTube-ffb321bedca46d6987c7b31dd58e5dea96ea2ea2.zip
WIP plugins: load theme on client side
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/config.ts5
-rw-r--r--server/controllers/themes.ts10
-rw-r--r--server/initializers/constants.ts6
-rw-r--r--server/initializers/migrations/0400-user-theme.ts2
-rw-r--r--server/lib/client-html.ts9
-rw-r--r--server/lib/plugins/theme-utils.ts10
-rw-r--r--server/models/account/user.ts6
7 files changed, 30 insertions, 18 deletions
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 088234074..81518bbb5 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -4,7 +4,7 @@ import { ServerConfig, UserRight } from '../../../shared'
4import { About } from '../../../shared/models/server/about.model' 4import { About } from '../../../shared/models/server/about.model'
5import { CustomConfig } from '../../../shared/models/server/custom-config.model' 5import { CustomConfig } from '../../../shared/models/server/custom-config.model'
6import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup' 6import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup'
7import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 7import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME } from '../../initializers/constants'
8import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares' 8import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares'
9import { customConfigUpdateValidator } from '../../middlewares/validators/config' 9import { customConfigUpdateValidator } from '../../middlewares/validators/config'
10import { ClientHtml } from '../../lib/client-html' 10import { ClientHtml } from '../../lib/client-html'
@@ -69,10 +69,11 @@ async function getConfig (req: express.Request, res: express.Response) {
69 name: t.name, 69 name: t.name,
70 version: t.version, 70 version: t.version,
71 description: t.description, 71 description: t.description,
72 css: t.css,
72 clientScripts: t.clientScripts 73 clientScripts: t.clientScripts
73 })) 74 }))
74 75
75 const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT) 76 const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME)
76 77
77 const json: ServerConfig = { 78 const json: ServerConfig = {
78 instance: { 79 instance: {
diff --git a/server/controllers/themes.ts b/server/controllers/themes.ts
index 20e7062d0..104c285ad 100644
--- a/server/controllers/themes.ts
+++ b/server/controllers/themes.ts
@@ -1,13 +1,11 @@
1import * as express from 'express' 1import * as express from 'express'
2import { PLUGIN_GLOBAL_CSS_PATH } from '../initializers/constants'
3import { join } from 'path' 2import { join } from 'path'
4import { RegisteredPlugin } from '../lib/plugins/plugin-manager' 3import { RegisteredPlugin } from '../lib/plugins/plugin-manager'
5import { servePluginStaticDirectoryValidator } from '../middlewares/validators/plugins'
6import { serveThemeCSSValidator } from '../middlewares/validators/themes' 4import { serveThemeCSSValidator } from '../middlewares/validators/themes'
7 5
8const themesRouter = express.Router() 6const themesRouter = express.Router()
9 7
10themesRouter.get('/:themeName/:themeVersion/css/:staticEndpoint', 8themesRouter.get('/:themeName/:themeVersion/css/:staticEndpoint(*)',
11 serveThemeCSSValidator, 9 serveThemeCSSValidator,
12 serveThemeCSSDirectory 10 serveThemeCSSDirectory
13) 11)
@@ -24,5 +22,9 @@ function serveThemeCSSDirectory (req: express.Request, res: express.Response) {
24 const plugin: RegisteredPlugin = res.locals.registeredPlugin 22 const plugin: RegisteredPlugin = res.locals.registeredPlugin
25 const staticEndpoint = req.params.staticEndpoint 23 const staticEndpoint = req.params.staticEndpoint
26 24
27 return express.static(join(plugin.path, staticEndpoint), { fallthrough: false }) 25 if (plugin.css.includes(staticEndpoint) === false) {
26 return res.sendStatus(404)
27 }
28
29 return res.sendFile(join(plugin.path, staticEndpoint))
28} 30}
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 9d61ed537..e5f88b71d 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -585,7 +585,8 @@ const P2P_MEDIA_LOADER_PEER_VERSION = 2
585const PLUGIN_GLOBAL_CSS_FILE_NAME = 'plugins-global.css' 585const PLUGIN_GLOBAL_CSS_FILE_NAME = 'plugins-global.css'
586const PLUGIN_GLOBAL_CSS_PATH = join(CONFIG.STORAGE.TMP_DIR, PLUGIN_GLOBAL_CSS_FILE_NAME) 586const PLUGIN_GLOBAL_CSS_PATH = join(CONFIG.STORAGE.TMP_DIR, PLUGIN_GLOBAL_CSS_FILE_NAME)
587 587
588const DEFAULT_THEME = 'default' 588const DEFAULT_THEME_NAME = 'default'
589const DEFAULT_USER_THEME_NAME = 'instance-default'
589 590
590// --------------------------------------------------------------------------- 591// ---------------------------------------------------------------------------
591 592
@@ -660,6 +661,7 @@ export {
660 PREVIEWS_SIZE, 661 PREVIEWS_SIZE,
661 REMOTE_SCHEME, 662 REMOTE_SCHEME,
662 FOLLOW_STATES, 663 FOLLOW_STATES,
664 DEFAULT_USER_THEME_NAME,
663 SERVER_ACTOR_NAME, 665 SERVER_ACTOR_NAME,
664 PLUGIN_GLOBAL_CSS_FILE_NAME, 666 PLUGIN_GLOBAL_CSS_FILE_NAME,
665 PLUGIN_GLOBAL_CSS_PATH, 667 PLUGIN_GLOBAL_CSS_PATH,
@@ -669,7 +671,7 @@ export {
669 HLS_STREAMING_PLAYLIST_DIRECTORY, 671 HLS_STREAMING_PLAYLIST_DIRECTORY,
670 FEEDS, 672 FEEDS,
671 JOB_TTL, 673 JOB_TTL,
672 DEFAULT_THEME, 674 DEFAULT_THEME_NAME,
673 NSFW_POLICY_TYPES, 675 NSFW_POLICY_TYPES,
674 STATIC_MAX_AGE, 676 STATIC_MAX_AGE,
675 STATIC_PATHS, 677 STATIC_PATHS,
diff --git a/server/initializers/migrations/0400-user-theme.ts b/server/initializers/migrations/0400-user-theme.ts
index 2c1763890..f74d76115 100644
--- a/server/initializers/migrations/0400-user-theme.ts
+++ b/server/initializers/migrations/0400-user-theme.ts
@@ -9,7 +9,7 @@ async function up (utils: {
9 const data = { 9 const data = {
10 type: Sequelize.STRING, 10 type: Sequelize.STRING,
11 allowNull: false, 11 allowNull: false,
12 defaultValue: 'default' 12 defaultValue: 'instance-default'
13 } 13 }
14 14
15 await utils.queryInterface.addColumn('user', 'theme', data) 15 await utils.queryInterface.addColumn('user', 'theme', data)
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts
index 516827a05..ccc963514 100644
--- a/server/lib/client-html.ts
+++ b/server/lib/client-html.ts
@@ -92,6 +92,7 @@ export class ClientHtml {
92 let html = buffer.toString() 92 let html = buffer.toString()
93 93
94 html = ClientHtml.addCustomCSS(html) 94 html = ClientHtml.addCustomCSS(html)
95 html = ClientHtml.addPluginCSS(html)
95 96
96 ClientHtml.htmlCache[ path ] = html 97 ClientHtml.htmlCache[ path ] = html
97 98
@@ -138,11 +139,17 @@ export class ClientHtml {
138 } 139 }
139 140
140 private static addCustomCSS (htmlStringPage: string) { 141 private static addCustomCSS (htmlStringPage: string) {
141 const styleTag = '<style class="custom-css-style">' + CONFIG.INSTANCE.CUSTOMIZATIONS.CSS + '</style>' 142 const styleTag = `<style class="custom-css-style">${CONFIG.INSTANCE.CUSTOMIZATIONS.CSS}</style>`
142 143
143 return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.CUSTOM_CSS, styleTag) 144 return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.CUSTOM_CSS, styleTag)
144 } 145 }
145 146
147 private static addPluginCSS (htmlStringPage: string) {
148 const linkTag = `<link rel="stylesheet" href="/plugins/global.css" />`
149
150 return htmlStringPage.replace('</head>', linkTag + '</head>')
151 }
152
146 private static addVideoOpenGraphAndOEmbedTags (htmlStringPage: string, video: VideoModel) { 153 private static addVideoOpenGraphAndOEmbedTags (htmlStringPage: string, video: VideoModel) {
147 const previewUrl = WEBSERVER.URL + video.getPreviewStaticPath() 154 const previewUrl = WEBSERVER.URL + video.getPreviewStaticPath()
148 const videoUrl = WEBSERVER.URL + video.getWatchStaticPath() 155 const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
diff --git a/server/lib/plugins/theme-utils.ts b/server/lib/plugins/theme-utils.ts
index 066339e65..76c671f1c 100644
--- a/server/lib/plugins/theme-utils.ts
+++ b/server/lib/plugins/theme-utils.ts
@@ -1,18 +1,18 @@
1import { DEFAULT_THEME } from '../../initializers/constants' 1import { DEFAULT_THEME_NAME, DEFAULT_USER_THEME_NAME } from '../../initializers/constants'
2import { PluginManager } from './plugin-manager' 2import { PluginManager } from './plugin-manager'
3import { CONFIG } from '../../initializers/config' 3import { CONFIG } from '../../initializers/config'
4 4
5function getThemeOrDefault (name: string) { 5function getThemeOrDefault (name: string, defaultTheme: string) {
6 if (isThemeRegistered(name)) return name 6 if (isThemeRegistered(name)) return name
7 7
8 // Fallback to admin default theme 8 // Fallback to admin default theme
9 if (name !== CONFIG.THEME.DEFAULT) return getThemeOrDefault(CONFIG.THEME.DEFAULT) 9 if (name !== CONFIG.THEME.DEFAULT) return getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME)
10 10
11 return DEFAULT_THEME 11 return defaultTheme
12} 12}
13 13
14function isThemeRegistered (name: string) { 14function isThemeRegistered (name: string) {
15 if (name === DEFAULT_THEME) return true 15 if (name === DEFAULT_THEME_NAME || name === DEFAULT_USER_THEME_NAME) return true
16 16
17 return !!PluginManager.Instance.getRegisteredThemes() 17 return !!PluginManager.Instance.getRegisteredThemes()
18 .find(r => r.name === name) 18 .find(r => r.name === name)
diff --git a/server/models/account/user.ts b/server/models/account/user.ts
index b8ca1dd5c..6f0b0e00f 100644
--- a/server/models/account/user.ts
+++ b/server/models/account/user.ts
@@ -44,7 +44,7 @@ import { VideoChannelModel } from '../video/video-channel'
44import { AccountModel } from './account' 44import { AccountModel } from './account'
45import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type' 45import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type'
46import { values } from 'lodash' 46import { values } from 'lodash'
47import { DEFAULT_THEME, NSFW_POLICY_TYPES } from '../../initializers/constants' 47import { DEFAULT_THEME_NAME, DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants'
48import { clearCacheByUserId } from '../../lib/oauth-model' 48import { clearCacheByUserId } from '../../lib/oauth-model'
49import { UserNotificationSettingModel } from './user-notification-setting' 49import { UserNotificationSettingModel } from './user-notification-setting'
50import { VideoModel } from '../video/video' 50import { VideoModel } from '../video/video'
@@ -190,7 +190,7 @@ export class UserModel extends Model<UserModel> {
190 videoQuotaDaily: number 190 videoQuotaDaily: number
191 191
192 @AllowNull(false) 192 @AllowNull(false)
193 @Default(DEFAULT_THEME) 193 @Default(DEFAULT_THEME_NAME)
194 @Is('UserTheme', value => throwIfNotValid(value, isThemeValid, 'theme')) 194 @Is('UserTheme', value => throwIfNotValid(value, isThemeValid, 'theme'))
195 @Column 195 @Column
196 theme: string 196 theme: string
@@ -568,7 +568,7 @@ export class UserModel extends Model<UserModel> {
568 autoPlayVideo: this.autoPlayVideo, 568 autoPlayVideo: this.autoPlayVideo,
569 videoLanguages: this.videoLanguages, 569 videoLanguages: this.videoLanguages,
570 role: this.role, 570 role: this.role,
571 theme: getThemeOrDefault(this.theme), 571 theme: getThemeOrDefault(this.theme, DEFAULT_USER_THEME_NAME),
572 roleLabel: USER_ROLE_LABELS[ this.role ], 572 roleLabel: USER_ROLE_LABELS[ this.role ],
573 videoQuota: this.videoQuota, 573 videoQuota: this.videoQuota,
574 videoQuotaDaily: this.videoQuotaDaily, 574 videoQuotaDaily: this.videoQuotaDaily,