From 200d21d5a67c379baac6dc633e52265cbfc2ae1f Mon Sep 17 00:00:00 2001 From: John Livingston Date: Thu, 6 Jun 2024 18:04:17 +0200 Subject: [PATCH] Custom channel emoticons WIP (#130): federation --- CHANGELOG.md | 1 - server/lib/conversejs/params.ts | 5 +++- server/lib/federation/outgoing.ts | 4 ++- server/lib/federation/sanitize.ts | 50 ++++++++++++++++++++++++++++++- server/lib/federation/types.ts | 1 + server/lib/routers/emojis.ts | 1 + 6 files changed, 58 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee878e29..81c9a60c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,4 @@ TODO: tag conversejs livechat branch, and replace commit ID in build-converse.js -TODO: handle custom emojis url for remote video. # Changelog diff --git a/server/lib/conversejs/params.ts b/server/lib/conversejs/params.ts index c9b7b388..3430dabe 100644 --- a/server/lib/conversejs/params.ts +++ b/server/lib/conversejs/params.ts @@ -272,7 +272,10 @@ async function _connectionInfos ( } roomJID = remoteConnectionInfos.roomJID - // TODO: fill customEmojisUrl (how to get the info? is the remote livechat compatible?) + // eslint-disable-next-line @typescript-eslint/prefer-optional-chain + if (remoteChatInfos && remoteChatInfos.customEmojisUrl) { + customEmojisUrl = remoteChatInfos.customEmojisUrl + } } else { try { roomJID = await _localRoomJID( diff --git a/server/lib/federation/outgoing.ts b/server/lib/federation/outgoing.ts index 4bea8ca9..92fe5e6d 100644 --- a/server/lib/federation/outgoing.ts +++ b/server/lib/federation/outgoing.ts @@ -16,6 +16,7 @@ import { getBoshUri, getWSUri, getWSS2SUri, getPublicChatUri } from '../uri/webc import { canonicalizePluginUri } from '../uri/canonicalize' import { getProsodyDomain } from '../prosody/config/domain' import { fillVideoCustomFields } from '../custom-fields' +import { Emojis } from '../emojis' import { loc } from '../loc' import { isDebugMode } from '../debug' @@ -153,7 +154,8 @@ async function videoBuildJSONLD ( type: 'xmpp', jid: roomJID, links, - xmppserver: serverInfos + xmppserver: serverInfos, + customEmojisUrl: await Emojis.singletonSafe()?.channelCustomEmojisUrl(video.channelId) } Object.assign(videoJsonld, { peertubeLiveChat diff --git a/server/lib/federation/sanitize.ts b/server/lib/federation/sanitize.ts index bfea0ac6..848a5372 100644 --- a/server/lib/federation/sanitize.ts +++ b/server/lib/federation/sanitize.ts @@ -41,10 +41,16 @@ function sanitizePeertubeLiveChatInfos ( const xmppserver = sanitizePeertubeLiveChatServerInfos(options, chatInfos.xmppserver, referenceUrl) if (!xmppserver) { return false } + let customEmojisUrl: string | undefined + if (('customEmojisUrl' in chatInfos) && chatInfos.customEmojisUrl) { + customEmojisUrl = sanitizeCustomEmojisUrl(options, chatInfos.customEmojisUrl, referenceUrl) + } + const r: LiveChatJSONLDAttributeV1 = { type: chatInfos.type, jid: chatInfos.jid, - xmppserver + xmppserver, + customEmojisUrl } return r @@ -152,6 +158,48 @@ function sanitizePeertubeLiveChatServerInfos ( return r } +/** + * Use this function for incoming custom emojis definition url. + * It will sanitize them, by checking everything is ok. + * + * @param options server options + * @param customEmojisUrl the value to test. + * @param referenceUrl optional url string. If given, we must check that urls are on the same domain, to avoid spoofing. + * @returns the url if valid, else undefined. + */ +function sanitizeCustomEmojisUrl ( + options: RegisterServerOptions, + customEmojisUrl: any, + referenceUrl?: string +): string | undefined { + let checkHost: undefined | string + + if (referenceUrl) { + checkHost = _readReferenceUrl(referenceUrl) + if (!checkHost) { + options.peertubeHelpers.logger.error( + 'sanitizeCustomEmojisUrl: got an invalid referenceUrl: ' + referenceUrl + ) + return undefined + } + } + + if ((typeof customEmojisUrl) !== 'string') { return undefined } + + if ( + !_validUrl(customEmojisUrl, { + noSearchParams: true, + protocol: 'http.', + domain: checkHost + }) + ) { + return undefined + } + + // No further verification. The frontend must use this url carefully (should only get JSON data). + return customEmojisUrl +} + interface URLConstraints { protocol: 'http.' | 'ws.' noSearchParams: boolean diff --git a/server/lib/federation/types.ts b/server/lib/federation/types.ts index fa39722f..613fbb55 100644 --- a/server/lib/federation/types.ts +++ b/server/lib/federation/types.ts @@ -55,6 +55,7 @@ interface LiveChatJSONLDInfosV1 { type: 'xmpp' jid: string // room JID xmppserver: PeertubeXMPPServerInfos + customEmojisUrl?: string // this comes with plugin v10.1.0 } // LiveChatJSONLDInfosV1CompatV0 is a mix of both interface. diff --git a/server/lib/routers/emojis.ts b/server/lib/routers/emojis.ts index f9df0291..182eab0f 100644 --- a/server/lib/routers/emojis.ts +++ b/server/lib/routers/emojis.ts @@ -42,6 +42,7 @@ export async function initEmojisRouter ( }) ) + // Note: CORS is handled by Peertube. router.get( '/emojis/channel/:channelId/files/:fileName', asyncMiddleware(async (req: Request, res: Response, _next: NextFunction): Promise => {