From ffb321bedca46d6987c7b31dd58e5dea96ea2ea2 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 10 Jul 2019 14:06:19 +0200 Subject: WIP plugins: load theme on client side --- server/controllers/api/config.ts | 5 +++-- server/controllers/themes.ts | 10 ++++++---- server/initializers/constants.ts | 6 ++++-- server/initializers/migrations/0400-user-theme.ts | 2 +- server/lib/client-html.ts | 9 ++++++++- server/lib/plugins/theme-utils.ts | 10 +++++----- server/models/account/user.ts | 6 +++--- 7 files changed, 30 insertions(+), 18 deletions(-) (limited to 'server') 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' import { About } from '../../../shared/models/server/about.model' import { CustomConfig } from '../../../shared/models/server/custom-config.model' import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup' -import { CONSTRAINTS_FIELDS } from '../../initializers/constants' +import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME } from '../../initializers/constants' import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares' import { customConfigUpdateValidator } from '../../middlewares/validators/config' import { ClientHtml } from '../../lib/client-html' @@ -69,10 +69,11 @@ async function getConfig (req: express.Request, res: express.Response) { name: t.name, version: t.version, description: t.description, + css: t.css, clientScripts: t.clientScripts })) - const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT) + const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME) const json: ServerConfig = { 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 @@ import * as express from 'express' -import { PLUGIN_GLOBAL_CSS_PATH } from '../initializers/constants' import { join } from 'path' import { RegisteredPlugin } from '../lib/plugins/plugin-manager' -import { servePluginStaticDirectoryValidator } from '../middlewares/validators/plugins' import { serveThemeCSSValidator } from '../middlewares/validators/themes' const themesRouter = express.Router() -themesRouter.get('/:themeName/:themeVersion/css/:staticEndpoint', +themesRouter.get('/:themeName/:themeVersion/css/:staticEndpoint(*)', serveThemeCSSValidator, serveThemeCSSDirectory ) @@ -24,5 +22,9 @@ function serveThemeCSSDirectory (req: express.Request, res: express.Response) { const plugin: RegisteredPlugin = res.locals.registeredPlugin const staticEndpoint = req.params.staticEndpoint - return express.static(join(plugin.path, staticEndpoint), { fallthrough: false }) + if (plugin.css.includes(staticEndpoint) === false) { + return res.sendStatus(404) + } + + return res.sendFile(join(plugin.path, staticEndpoint)) } 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 const PLUGIN_GLOBAL_CSS_FILE_NAME = 'plugins-global.css' const PLUGIN_GLOBAL_CSS_PATH = join(CONFIG.STORAGE.TMP_DIR, PLUGIN_GLOBAL_CSS_FILE_NAME) -const DEFAULT_THEME = 'default' +const DEFAULT_THEME_NAME = 'default' +const DEFAULT_USER_THEME_NAME = 'instance-default' // --------------------------------------------------------------------------- @@ -660,6 +661,7 @@ export { PREVIEWS_SIZE, REMOTE_SCHEME, FOLLOW_STATES, + DEFAULT_USER_THEME_NAME, SERVER_ACTOR_NAME, PLUGIN_GLOBAL_CSS_FILE_NAME, PLUGIN_GLOBAL_CSS_PATH, @@ -669,7 +671,7 @@ export { HLS_STREAMING_PLAYLIST_DIRECTORY, FEEDS, JOB_TTL, - DEFAULT_THEME, + DEFAULT_THEME_NAME, NSFW_POLICY_TYPES, STATIC_MAX_AGE, 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: { const data = { type: Sequelize.STRING, allowNull: false, - defaultValue: 'default' + defaultValue: 'instance-default' } 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 { let html = buffer.toString() html = ClientHtml.addCustomCSS(html) + html = ClientHtml.addPluginCSS(html) ClientHtml.htmlCache[ path ] = html @@ -138,11 +139,17 @@ export class ClientHtml { } private static addCustomCSS (htmlStringPage: string) { - const styleTag = '' + const styleTag = `` return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.CUSTOM_CSS, styleTag) } + private static addPluginCSS (htmlStringPage: string) { + const linkTag = `` + + return htmlStringPage.replace('', linkTag + '') + } + private static addVideoOpenGraphAndOEmbedTags (htmlStringPage: string, video: VideoModel) { const previewUrl = WEBSERVER.URL + video.getPreviewStaticPath() 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 @@ -import { DEFAULT_THEME } from '../../initializers/constants' +import { DEFAULT_THEME_NAME, DEFAULT_USER_THEME_NAME } from '../../initializers/constants' import { PluginManager } from './plugin-manager' import { CONFIG } from '../../initializers/config' -function getThemeOrDefault (name: string) { +function getThemeOrDefault (name: string, defaultTheme: string) { if (isThemeRegistered(name)) return name // Fallback to admin default theme - if (name !== CONFIG.THEME.DEFAULT) return getThemeOrDefault(CONFIG.THEME.DEFAULT) + if (name !== CONFIG.THEME.DEFAULT) return getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME) - return DEFAULT_THEME + return defaultTheme } function isThemeRegistered (name: string) { - if (name === DEFAULT_THEME) return true + if (name === DEFAULT_THEME_NAME || name === DEFAULT_USER_THEME_NAME) return true return !!PluginManager.Instance.getRegisteredThemes() .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' import { AccountModel } from './account' import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type' import { values } from 'lodash' -import { DEFAULT_THEME, NSFW_POLICY_TYPES } from '../../initializers/constants' +import { DEFAULT_THEME_NAME, DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants' import { clearCacheByUserId } from '../../lib/oauth-model' import { UserNotificationSettingModel } from './user-notification-setting' import { VideoModel } from '../video/video' @@ -190,7 +190,7 @@ export class UserModel extends Model { videoQuotaDaily: number @AllowNull(false) - @Default(DEFAULT_THEME) + @Default(DEFAULT_THEME_NAME) @Is('UserTheme', value => throwIfNotValid(value, isThemeValid, 'theme')) @Column theme: string @@ -568,7 +568,7 @@ export class UserModel extends Model { autoPlayVideo: this.autoPlayVideo, videoLanguages: this.videoLanguages, role: this.role, - theme: getThemeOrDefault(this.theme), + theme: getThemeOrDefault(this.theme, DEFAULT_USER_THEME_NAME), roleLabel: USER_ROLE_LABELS[ this.role ], videoQuota: this.videoQuota, videoQuotaDaily: this.videoQuotaDaily, -- cgit v1.2.3