2021-04-15 10:17:08 +00:00
|
|
|
import type { Router, RequestHandler, Request, Response, NextFunction } from 'express'
|
2021-04-15 13:21:58 +00:00
|
|
|
import type { ProxyOptions } from 'express-http-proxy'
|
2021-06-03 09:46:11 +00:00
|
|
|
import type { ChatType } from '../../../shared/lib/types'
|
2021-05-18 16:17:13 +00:00
|
|
|
import { getBaseRouterRoute, getBaseStaticRoute } from '../helpers'
|
2021-05-03 18:37:23 +00:00
|
|
|
import { asyncMiddleware } from '../middlewares/async'
|
2021-05-06 11:31:55 +00:00
|
|
|
import { getProsodyDomain } from '../prosody/config/domain'
|
2021-04-08 00:43:13 +00:00
|
|
|
import * as path from 'path'
|
2021-04-16 11:46:51 +00:00
|
|
|
const bodyParser = require('body-parser')
|
2021-04-16 11:42:07 +00:00
|
|
|
|
2021-04-08 00:43:13 +00:00
|
|
|
const fs = require('fs').promises
|
2021-04-15 13:21:58 +00:00
|
|
|
const proxy = require('express-http-proxy')
|
2021-04-15 10:17:08 +00:00
|
|
|
|
|
|
|
let httpBindRoute: RequestHandler
|
|
|
|
|
|
|
|
async function initWebchatRouter (options: RegisterServerOptions): Promise<Router> {
|
|
|
|
const {
|
|
|
|
getRouter,
|
|
|
|
peertubeHelpers,
|
|
|
|
settingsManager
|
|
|
|
} = options
|
2021-04-08 00:43:13 +00:00
|
|
|
|
2021-04-09 17:29:44 +00:00
|
|
|
const converseJSIndex = await fs.readFile(path.resolve(__dirname, '../../conversejs/index.html'))
|
2021-04-08 00:43:13 +00:00
|
|
|
|
2021-04-15 10:17:08 +00:00
|
|
|
const router: Router = getRouter()
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
2021-05-03 18:37:23 +00:00
|
|
|
router.get('/room/:videoUUID', asyncMiddleware(
|
|
|
|
async (req: Request, res: Response, _next: NextFunction): Promise<void> => {
|
2021-05-07 14:45:55 +00:00
|
|
|
res.removeHeader('X-Frame-Options') // this route can be opened in an iframe
|
|
|
|
|
2021-04-08 00:43:13 +00:00
|
|
|
const settings = await settingsManager.getSettings([
|
2021-06-03 09:46:11 +00:00
|
|
|
'chat-type', 'chat-room', 'chat-server',
|
2021-04-08 00:43:13 +00:00
|
|
|
'chat-bosh-uri', 'chat-ws-uri'
|
|
|
|
])
|
2021-06-03 09:46:11 +00:00
|
|
|
const chatType: ChatType = (settings['chat-type'] ?? 'disabled') as ChatType
|
2021-04-08 00:43:13 +00:00
|
|
|
|
2021-04-14 16:47:23 +00:00
|
|
|
let server: string
|
|
|
|
let room: string
|
|
|
|
let boshUri: string
|
|
|
|
let wsUri: string
|
2021-05-04 11:00:44 +00:00
|
|
|
let authenticationUrl: string = ''
|
2021-05-05 15:20:06 +00:00
|
|
|
let advancedControls: boolean = false
|
2021-06-03 09:46:11 +00:00
|
|
|
if (chatType === 'builtin-prosody') {
|
2021-05-06 11:31:55 +00:00
|
|
|
const prosodyDomain = await getProsodyDomain(options)
|
|
|
|
server = 'anon.' + prosodyDomain
|
|
|
|
room = '{{VIDEO_UUID}}@room.' + prosodyDomain
|
2021-05-18 16:06:11 +00:00
|
|
|
boshUri = getBaseRouterRoute(options) + 'webchat/http-bind'
|
2021-04-14 16:47:23 +00:00
|
|
|
wsUri = ''
|
2021-05-04 11:00:44 +00:00
|
|
|
authenticationUrl = options.peertubeHelpers.config.getWebserverUrl() +
|
2021-05-18 16:06:11 +00:00
|
|
|
getBaseRouterRoute(options) +
|
2021-05-04 11:00:44 +00:00
|
|
|
'api/auth'
|
2021-05-05 15:20:06 +00:00
|
|
|
advancedControls = true
|
2021-06-03 09:46:11 +00:00
|
|
|
} else if (chatType === 'builtin-converse') {
|
2021-04-14 16:47:23 +00:00
|
|
|
if (!settings['chat-server']) {
|
|
|
|
throw new Error('Missing chat-server settings.')
|
|
|
|
}
|
|
|
|
if (!settings['chat-room']) {
|
|
|
|
throw new Error('Missing chat-room settings.')
|
|
|
|
}
|
|
|
|
if (!settings['chat-bosh-uri'] && !settings['chat-ws-uri']) {
|
|
|
|
throw new Error('Missing BOSH or Websocket uri.')
|
|
|
|
}
|
|
|
|
server = settings['chat-server'] as string
|
|
|
|
room = settings['chat-room'] as string
|
|
|
|
boshUri = settings['chat-bosh-uri'] as string
|
|
|
|
wsUri = settings['chat-ws-uri'] as string
|
|
|
|
} else {
|
2021-04-08 00:43:13 +00:00
|
|
|
throw new Error('Builtin chat disabled.')
|
|
|
|
}
|
|
|
|
|
2021-04-30 15:39:27 +00:00
|
|
|
const uuid = req.params.videoUUID
|
|
|
|
const video = await peertubeHelpers.videos.loadByIdOrUUID(uuid)
|
2021-04-08 00:43:13 +00:00
|
|
|
if (!video) {
|
|
|
|
throw new Error('Video not found')
|
|
|
|
}
|
|
|
|
|
|
|
|
let page = '' + (converseJSIndex as string)
|
2021-05-18 16:17:13 +00:00
|
|
|
const baseStaticUrl = getBaseStaticRoute(options)
|
|
|
|
page = page.replace(/{{BASE_STATIC_URL}}/g, baseStaticUrl)
|
2021-04-14 16:47:23 +00:00
|
|
|
page = page.replace(/{{JID}}/g, server)
|
|
|
|
room = room.replace(/{{VIDEO_UUID}}/g, video.uuid)
|
2021-04-08 00:43:13 +00:00
|
|
|
page = page.replace(/{{ROOM}}/g, room)
|
2021-04-14 16:47:23 +00:00
|
|
|
page = page.replace(/{{BOSH_SERVICE_URL}}/g, boshUri)
|
|
|
|
page = page.replace(/{{WS_SERVICE_URL}}/g, wsUri)
|
2021-05-04 11:00:44 +00:00
|
|
|
page = page.replace(/{{AUTHENTICATION_URL}}/g, authenticationUrl)
|
2021-05-05 15:20:06 +00:00
|
|
|
page = page.replace(/{{ADVANCEDCONTROLS}}/g, advancedControls ? 'true' : 'false')
|
2021-04-08 00:43:13 +00:00
|
|
|
|
|
|
|
res.status(200)
|
|
|
|
res.type('html')
|
|
|
|
res.send(page)
|
|
|
|
}
|
2021-05-03 18:37:23 +00:00
|
|
|
))
|
2021-04-15 10:17:08 +00:00
|
|
|
|
|
|
|
changeHttpBindRoute(options, null)
|
2021-04-16 11:44:24 +00:00
|
|
|
router.all('/http-bind',
|
|
|
|
bodyParser.raw({ type: 'text/xml' }),
|
|
|
|
(req: Request, res: Response, next: NextFunction) => {
|
|
|
|
httpBindRoute(req, res, next)
|
|
|
|
}
|
|
|
|
)
|
2021-04-09 17:29:44 +00:00
|
|
|
return router
|
|
|
|
}
|
|
|
|
|
2021-04-15 10:17:08 +00:00
|
|
|
function changeHttpBindRoute ({ peertubeHelpers }: RegisterServerOptions, port: string | null): void {
|
|
|
|
const logger = peertubeHelpers.logger
|
|
|
|
logger.info('Changing http-bind port for ' + (port ?? 'null'))
|
|
|
|
if (port !== null && !/^\d+$/.test(port)) {
|
|
|
|
logger.error('Port is not valid. Replacing by null')
|
|
|
|
port = null
|
|
|
|
}
|
|
|
|
if (port === null) {
|
|
|
|
httpBindRoute = (_req: Request, res: Response, _next: NextFunction) => {
|
|
|
|
res.status(404)
|
|
|
|
res.send('Not found')
|
|
|
|
}
|
|
|
|
} else {
|
2021-04-15 13:21:58 +00:00
|
|
|
const options: ProxyOptions = {
|
|
|
|
https: false,
|
|
|
|
proxyReqPathResolver: async (_req: Request): Promise<string> => {
|
|
|
|
return '/http-bind' // should not be able to access anything else
|
|
|
|
},
|
2021-05-06 12:04:16 +00:00
|
|
|
// preserveHostHdr: true,
|
2021-04-16 11:42:07 +00:00
|
|
|
parseReqBody: true // Note that setting this to false overrides reqAsBuffer and reqBodyEncoding below.
|
|
|
|
// FIXME: should we remove cookies?
|
2021-04-15 13:21:58 +00:00
|
|
|
}
|
2021-04-16 11:42:07 +00:00
|
|
|
httpBindRoute = proxy('http://localhost:' + port, options)
|
2021-04-15 10:17:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-09 17:29:44 +00:00
|
|
|
export {
|
2021-04-15 10:17:08 +00:00
|
|
|
initWebchatRouter,
|
|
|
|
changeHttpBindRoute
|
2021-04-08 00:43:13 +00:00
|
|
|
}
|