From 2539932e16129992a2c0889b4ff527c265a8e2c7 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 27 May 2021 15:59:55 +0200 Subject: Instance homepage support (#4007) * Prepare homepage parsers * Add ability to update instance hompage * Add ability to set homepage as landing page * Add homepage preview in admin * Dynamically update left menu for homepage * Inject home content in homepage * Add videos list and channel miniature custom markup * Remove unused elements in markup service --- shared/core-utils/miscs/miscs.ts | 17 ++++++- shared/core-utils/renderer/html.ts | 52 +++++++++++++++------- shared/extra-utils/custom-pages/custom-pages.ts | 31 +++++++++++++ shared/extra-utils/index.ts | 2 + shared/models/actors/custom-page.model.ts | 3 ++ shared/models/actors/index.ts | 1 + .../custom-markup/custom-markup-data.model.ts | 28 ++++++++++++ shared/models/custom-markup/index.ts | 1 + shared/models/index.ts | 1 + shared/models/server/server-config.model.ts | 4 ++ shared/models/users/user-right.enum.ts | 1 + 11 files changed, 124 insertions(+), 17 deletions(-) create mode 100644 shared/extra-utils/custom-pages/custom-pages.ts create mode 100644 shared/models/actors/custom-page.model.ts create mode 100644 shared/models/custom-markup/custom-markup-data.model.ts create mode 100644 shared/models/custom-markup/index.ts (limited to 'shared') diff --git a/shared/core-utils/miscs/miscs.ts b/shared/core-utils/miscs/miscs.ts index 71703faac..4780ca922 100644 --- a/shared/core-utils/miscs/miscs.ts +++ b/shared/core-utils/miscs/miscs.ts @@ -28,9 +28,24 @@ function isCatchable (value: any) { return value && typeof value.catch === 'function' } +function sortObjectComparator (key: string, order: 'asc' | 'desc') { + return (a: any, b: any) => { + if (a[key] < b[key]) { + return order === 'asc' ? -1 : 1 + } + + if (a[key] > b[key]) { + return order === 'asc' ? 1 : -1 + } + + return 0 + } +} + export { randomInt, compareSemVer, isPromise, - isCatchable + isCatchable, + sortObjectComparator } diff --git a/shared/core-utils/renderer/html.ts b/shared/core-utils/renderer/html.ts index de4ad47ac..bbf8b3fbd 100644 --- a/shared/core-utils/renderer/html.ts +++ b/shared/core-utils/renderer/html.ts @@ -1,25 +1,45 @@ -export const SANITIZE_OPTIONS = { - allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ], - allowedSchemes: [ 'http', 'https' ], - allowedAttributes: { - a: [ 'href', 'class', 'target', 'rel' ] - }, - transformTags: { - a: (tagName: string, attribs: any) => { - let rel = 'noopener noreferrer' - if (attribs.rel === 'me') rel += ' me' +export function getSanitizeOptions () { + return { + allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ], + allowedSchemes: [ 'http', 'https' ], + allowedAttributes: { + 'a': [ 'href', 'class', 'target', 'rel' ], + '*': [ 'data-*' ] + }, + transformTags: { + a: (tagName: string, attribs: any) => { + let rel = 'noopener noreferrer' + if (attribs.rel === 'me') rel += ' me' - return { - tagName, - attribs: Object.assign(attribs, { - target: '_blank', - rel - }) + return { + tagName, + attribs: Object.assign(attribs, { + target: '_blank', + rel + }) + } } } } } +export function getCustomMarkupSanitizeOptions (additionalAllowedTags: string[] = []) { + const base = getSanitizeOptions() + + return { + allowedTags: [ + ...base.allowedTags, + ...additionalAllowedTags, + 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' + ], + allowedSchemes: base.allowedSchemes, + allowedAttributes: { + ...base.allowedAttributes, + '*': [ 'data-*', 'style' ] + } + } +} + // Thanks: https://stackoverflow.com/a/12034334 export function escapeHTML (stringParam: string) { if (!stringParam) return '' diff --git a/shared/extra-utils/custom-pages/custom-pages.ts b/shared/extra-utils/custom-pages/custom-pages.ts new file mode 100644 index 000000000..bf2d16c70 --- /dev/null +++ b/shared/extra-utils/custom-pages/custom-pages.ts @@ -0,0 +1,31 @@ +import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { makeGetRequest, makePutBodyRequest } from '../requests/requests' + +function getInstanceHomepage (url: string, statusCodeExpected = HttpStatusCode.OK_200) { + const path = '/api/v1/custom-pages/homepage/instance' + + return makeGetRequest({ + url, + path, + statusCodeExpected + }) +} + +function updateInstanceHomepage (url: string, token: string, content: string) { + const path = '/api/v1/custom-pages/homepage/instance' + + return makePutBodyRequest({ + url, + path, + token, + fields: { content }, + statusCodeExpected: HttpStatusCode.NO_CONTENT_204 + }) +} + +// --------------------------------------------------------------------------- + +export { + getInstanceHomepage, + updateInstanceHomepage +} diff --git a/shared/extra-utils/index.ts b/shared/extra-utils/index.ts index 720db19cb..3bc09ead5 100644 --- a/shared/extra-utils/index.ts +++ b/shared/extra-utils/index.ts @@ -2,6 +2,8 @@ export * from './bulk/bulk' export * from './cli/cli' +export * from './custom-pages/custom-pages' + export * from './feeds/feeds' export * from './mock-servers/mock-instances-index' diff --git a/shared/models/actors/custom-page.model.ts b/shared/models/actors/custom-page.model.ts new file mode 100644 index 000000000..1e33584c1 --- /dev/null +++ b/shared/models/actors/custom-page.model.ts @@ -0,0 +1,3 @@ +export interface CustomPage { + content: string +} diff --git a/shared/models/actors/index.ts b/shared/models/actors/index.ts index 156f83248..e03f168cd 100644 --- a/shared/models/actors/index.ts +++ b/shared/models/actors/index.ts @@ -2,4 +2,5 @@ export * from './account.model' export * from './actor-image.model' export * from './actor-image.type' export * from './actor.model' +export * from './custom-page.model' export * from './follow.model' diff --git a/shared/models/custom-markup/custom-markup-data.model.ts b/shared/models/custom-markup/custom-markup-data.model.ts new file mode 100644 index 000000000..af697428e --- /dev/null +++ b/shared/models/custom-markup/custom-markup-data.model.ts @@ -0,0 +1,28 @@ +export type EmbedMarkupData = { + // Video or playlist uuid + uuid: string +} + +export type VideoMiniatureMarkupData = { + // Video uuid + uuid: string +} + +export type PlaylistMiniatureMarkupData = { + // Playlist uuid + uuid: string +} + +export type ChannelMiniatureMarkupData = { + // Channel name (username) + name: string +} + +export type VideosListMarkupData = { + title: string + description: string + sort: string + categoryOneOf: string // coma separated values + languageOneOf: string // coma separated values + count: string +} diff --git a/shared/models/custom-markup/index.ts b/shared/models/custom-markup/index.ts new file mode 100644 index 000000000..2898dfa90 --- /dev/null +++ b/shared/models/custom-markup/index.ts @@ -0,0 +1 @@ +export * from './custom-markup-data.model' diff --git a/shared/models/index.ts b/shared/models/index.ts index dff5fdf0e..4db1f234e 100644 --- a/shared/models/index.ts +++ b/shared/models/index.ts @@ -1,6 +1,7 @@ export * from './activitypub' export * from './actors' export * from './moderation' +export * from './custom-markup' export * from './bulk' export * from './redundancy' export * from './users' diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts index 2c5026b30..1667bc0e2 100644 --- a/shared/models/server/server-config.model.ts +++ b/shared/models/server/server-config.model.ts @@ -214,6 +214,10 @@ export interface ServerConfig { level: BroadcastMessageLevel dismissable: boolean } + + homepage: { + enabled: boolean + } } export type HTMLServerConfig = Omit diff --git a/shared/models/users/user-right.enum.ts b/shared/models/users/user-right.enum.ts index bbedc9f00..950b22bad 100644 --- a/shared/models/users/user-right.enum.ts +++ b/shared/models/users/user-right.enum.ts @@ -16,6 +16,7 @@ export const enum UserRight { MANAGE_JOBS, MANAGE_CONFIGURATION, + MANAGE_INSTANCE_CUSTOM_PAGE, MANAGE_ACCOUNTS_BLOCKLIST, MANAGE_SERVERS_BLOCKLIST, -- cgit v1.2.3