2024-05-23 09:42:14 +00:00
|
|
|
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
2023-04-13 13:41:46 +00:00
|
|
|
import type { RegisterServerOptions } from '@peertube/peertube-types'
|
|
|
|
import * as path from 'path'
|
|
|
|
import * as fs from 'fs'
|
|
|
|
|
2023-05-23 10:39:05 +00:00
|
|
|
interface ProsodyDebuggerOptions {
|
|
|
|
mobdebugPath: string
|
|
|
|
mobdebugHost: string
|
|
|
|
mobdebugPort: string
|
|
|
|
}
|
|
|
|
|
|
|
|
interface DebugContent {
|
|
|
|
renewCertCheckInterval?: number
|
|
|
|
renewSelfSignedCertInterval?: number
|
2023-09-27 12:29:17 +00:00
|
|
|
useOpenSSL?: boolean
|
2023-05-23 10:39:05 +00:00
|
|
|
logRotateCheckInterval?: number
|
|
|
|
logRotateEvery?: number
|
2023-05-24 14:26:57 +00:00
|
|
|
remoteServerInfosMaxAge?: number
|
2023-05-23 10:39:05 +00:00
|
|
|
prosodyDebuggerOptions?: ProsodyDebuggerOptions
|
2023-07-06 14:39:32 +00:00
|
|
|
alwaysPublishXMPPRoom?: boolean
|
|
|
|
enablePodcastChatTagForNonLive?: boolean
|
2024-02-29 14:58:41 +00:00
|
|
|
mucAdmins?: string[]
|
2024-04-18 18:16:44 +00:00
|
|
|
externalAccountPruneInterval?: number
|
2023-05-23 10:39:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type DebugNumericValue = 'renewCertCheckInterval'
|
|
|
|
| 'renewSelfSignedCertInterval'
|
|
|
|
| 'logRotateEvery'
|
|
|
|
| 'logRotateCheckInterval'
|
2023-05-24 14:26:57 +00:00
|
|
|
| 'remoteServerInfosMaxAge'
|
2024-04-18 18:16:44 +00:00
|
|
|
| 'externalAccountPruneInterval'
|
2023-05-23 10:39:05 +00:00
|
|
|
|
2023-09-27 12:29:17 +00:00
|
|
|
type DebugBooleanValue = 'alwaysPublishXMPPRoom' | 'enablePodcastChatTagForNonLive' | 'useOpenSSL'
|
2023-07-06 14:39:32 +00:00
|
|
|
|
2023-05-23 10:39:05 +00:00
|
|
|
let debugContent: DebugContent | null | false = null
|
|
|
|
function _readDebugFile (options: RegisterServerOptions): DebugContent | false {
|
|
|
|
if (debugContent !== null) { return debugContent }
|
|
|
|
|
2023-04-13 13:41:46 +00:00
|
|
|
const peertubeHelpers = options.peertubeHelpers
|
|
|
|
const logger = peertubeHelpers.logger
|
|
|
|
if (!peertubeHelpers.plugin) {
|
|
|
|
return false
|
|
|
|
}
|
2023-05-23 10:39:05 +00:00
|
|
|
|
2023-04-13 13:41:46 +00:00
|
|
|
const filepath = path.resolve(peertubeHelpers.plugin.getDataDirectoryPath(), 'debug_mode')
|
|
|
|
logger.debug('Testing debug mode by testing if file exists: ' + filepath)
|
2023-05-23 10:39:05 +00:00
|
|
|
if (!fs.existsSync(filepath)) {
|
|
|
|
debugContent = false
|
|
|
|
return false
|
2023-04-13 13:41:46 +00:00
|
|
|
}
|
2023-05-23 10:39:05 +00:00
|
|
|
|
|
|
|
logger.info('Plugin livechat Debug mode is on.')
|
|
|
|
debugContent = {}
|
|
|
|
|
|
|
|
try {
|
|
|
|
// content is optional, the file can be empty!
|
|
|
|
const content = fs.readFileSync(filepath).toString()
|
|
|
|
let json: any = !content ? {} : JSON.parse(content)
|
|
|
|
if (!json || (typeof json !== 'object')) { json = {} }
|
|
|
|
|
|
|
|
debugContent.prosodyDebuggerOptions = _getProsodyDebuggerOptions(options, json)
|
|
|
|
debugContent.logRotateCheckInterval = _getNumericOptions(options, json, 'log_rotate_check_interval')
|
|
|
|
debugContent.logRotateEvery = _getNumericOptions(options, json, 'log_rotate_every')
|
|
|
|
debugContent.renewCertCheckInterval = _getNumericOptions(options, json, 'renew_cert_check_interval')
|
|
|
|
debugContent.renewSelfSignedCertInterval = _getNumericOptions(options, json, 'renew_self_signed_cert_interval')
|
2023-09-27 12:29:17 +00:00
|
|
|
debugContent.useOpenSSL = json.use_openssl === true
|
2023-05-24 14:26:57 +00:00
|
|
|
debugContent.remoteServerInfosMaxAge = _getNumericOptions(options, json, 'remote_server_infos_max_age')
|
2023-07-06 14:39:32 +00:00
|
|
|
debugContent.alwaysPublishXMPPRoom = json.always_publish_xmpp_room === true
|
|
|
|
debugContent.enablePodcastChatTagForNonLive = json.enable_podcast_chat_tag_for_nonlive === true
|
2024-02-29 14:58:41 +00:00
|
|
|
debugContent.mucAdmins = _getJIDs(options, json, 'muc_admins')
|
2024-04-18 18:16:44 +00:00
|
|
|
debugContent.externalAccountPruneInterval = _getNumericOptions(options, json, 'external_account_prune_interval')
|
2023-05-23 10:39:05 +00:00
|
|
|
} catch (err) {
|
|
|
|
logger.error('Failed to read the debug_mode file content:', err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return debugContent
|
2023-04-13 13:41:46 +00:00
|
|
|
}
|
2023-05-19 10:52:52 +00:00
|
|
|
|
2023-05-23 10:39:05 +00:00
|
|
|
function _getProsodyDebuggerOptions (options: RegisterServerOptions, json: any): ProsodyDebuggerOptions | undefined {
|
|
|
|
if (!json) { return undefined }
|
|
|
|
if (typeof json !== 'object') { return undefined }
|
|
|
|
if (!json.debug_prosody) { return undefined }
|
|
|
|
if (typeof json.debug_prosody !== 'object') { return undefined }
|
|
|
|
if (!json.debug_prosody.debugger_path) { return undefined }
|
|
|
|
if (typeof json.debug_prosody.debugger_path !== 'string') { return undefined }
|
|
|
|
|
2024-09-07 12:49:27 +00:00
|
|
|
const mobdebugPath = json.debug_prosody.debugger_path as string
|
2023-05-23 10:39:05 +00:00
|
|
|
|
|
|
|
if (!fs.statSync(mobdebugPath).isDirectory()) {
|
|
|
|
options.peertubeHelpers.logger.error('There should be a debugger, but cant find it. Path should be: ', mobdebugPath)
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
const mobdebugHost = json.debug_prosody.host?.toString() || 'localhost'
|
|
|
|
const mobdebugPort = json.debug_prosody.port?.toString() || '8172'
|
|
|
|
return {
|
|
|
|
mobdebugPath,
|
|
|
|
mobdebugHost,
|
|
|
|
mobdebugPort
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function _getNumericOptions (options: RegisterServerOptions, json: any, name: string): number | undefined {
|
|
|
|
if (!(name in json)) { return undefined }
|
|
|
|
const v = json[name]
|
|
|
|
if (typeof v !== 'number') { return undefined }
|
|
|
|
return json[name]
|
|
|
|
}
|
|
|
|
|
2024-02-29 14:58:41 +00:00
|
|
|
function _getJIDs (options: RegisterServerOptions, json: any, name: string): string[] | undefined {
|
|
|
|
if (!(name in json)) { return undefined }
|
|
|
|
const v = json[name]
|
|
|
|
if (!Array.isArray(v)) { return undefined }
|
|
|
|
return v.filter(jid => {
|
|
|
|
if (typeof jid !== 'string') { return false }
|
|
|
|
if (!/^[a-zA-Z0-9_.-]+(?:@[a-zA-Z0-9_.-]+)?$/.test(jid)) { return false }
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-05-23 10:39:05 +00:00
|
|
|
function unloadDebugMode (): void {
|
|
|
|
debugContent = null
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if debug mode is enabled
|
|
|
|
* @param options server options
|
2023-07-06 14:39:32 +00:00
|
|
|
* @param feature optional feature name.
|
|
|
|
* Returns true only if the debug_mode file contains a key with that name, and that is true.
|
2023-05-23 10:39:05 +00:00
|
|
|
* @returns true if debug mode enabled
|
|
|
|
*/
|
2023-07-06 14:39:32 +00:00
|
|
|
function isDebugMode (options: RegisterServerOptions, feature?: DebugBooleanValue): boolean {
|
2023-05-23 10:39:05 +00:00
|
|
|
const debugContent = _readDebugFile(options)
|
2023-07-06 14:39:32 +00:00
|
|
|
if (!debugContent) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if (!feature) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return debugContent[feature] === true
|
2023-05-19 10:52:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* On dev environnement, it is possible to enable a Lua debugger.
|
|
|
|
* @param options server options
|
|
|
|
* @returns false if we dont use the Prosody debugger. Else the need information to launch the debugger.
|
|
|
|
*/
|
2023-05-23 10:39:05 +00:00
|
|
|
function prosodyDebuggerOptions (options: RegisterServerOptions): false | ProsodyDebuggerOptions {
|
|
|
|
// Additional security: testing NODE_ENV.
|
2024-02-29 14:58:41 +00:00
|
|
|
// It should absolutly not be possible to enable Prosody debugger on production env.
|
2023-05-19 10:52:52 +00:00
|
|
|
if (process.env.NODE_ENV !== 'dev') { return false }
|
2023-05-23 10:39:05 +00:00
|
|
|
const debugContent = _readDebugFile(options)
|
|
|
|
if (debugContent === false) { return false }
|
|
|
|
if (!debugContent.prosodyDebuggerOptions) { return false }
|
|
|
|
return debugContent.prosodyDebuggerOptions
|
2023-05-19 10:52:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* In some dev environment, Prosody will fail DNS queries when using Lua-unbound.
|
|
|
|
* I did not managed to properly configure lua-unbound.
|
|
|
|
* So, here is a dirty hack to disable lua-unbound: just put a `no_lua_unbound`
|
|
|
|
* file in the plugin data dir. This will delete the lua file from the AppImage extraction.
|
|
|
|
* You must restart Peertube after adding or deleting this file.
|
|
|
|
* @param options server options
|
|
|
|
* @param squashfsPath the folder where the AppImage is extracted
|
|
|
|
*/
|
2023-05-23 10:39:05 +00:00
|
|
|
function disableLuaUnboundIfNeeded (options: RegisterServerOptions, squashfsPath: string): void {
|
2023-05-19 10:52:52 +00:00
|
|
|
const peertubeHelpers = options.peertubeHelpers
|
|
|
|
const logger = peertubeHelpers.logger
|
|
|
|
|
|
|
|
if (!peertubeHelpers.plugin) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
const filepath = path.resolve(peertubeHelpers.plugin.getDataDirectoryPath(), 'no_lua_unbound')
|
|
|
|
logger.debug('Testing if file exists: ' + filepath)
|
|
|
|
if (!fs.existsSync(filepath)) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.info('Must disable lua-unbound.')
|
|
|
|
try {
|
|
|
|
for (const luaVersion of ['5.1', '5.2', '5.3', '5.4']) {
|
|
|
|
const fp = path.resolve(squashfsPath, 'squashfs-root/usr/lib/x86_64-linux-gnu/lua/', luaVersion, 'lunbound.so')
|
|
|
|
if (fs.existsSync(fp)) {
|
|
|
|
fs.rmSync(fp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
logger.error(err)
|
|
|
|
}
|
|
|
|
}
|
2023-05-23 10:39:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a numerical parameter value. There are 3 kind of values:
|
|
|
|
* - classic production value
|
|
|
|
* - value when debug mode is activated
|
|
|
|
* - value when debut mode is activated, and the debug_mode file overrides it
|
|
|
|
* @param options server options
|
|
|
|
* @param name name of the wanted value
|
|
|
|
* @param defaultDebug default value when debug is activated
|
|
|
|
* @param defaultValue default value when debug is disabled
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
function debugNumericParameter (
|
|
|
|
options: RegisterServerOptions,
|
|
|
|
name: DebugNumericValue,
|
|
|
|
defaultDebug: number,
|
|
|
|
defaultValue: number
|
|
|
|
): number {
|
|
|
|
const debugContent = _readDebugFile(options)
|
|
|
|
if (!debugContent) { return defaultValue }
|
|
|
|
if (name in debugContent) {
|
|
|
|
const v: any = debugContent[name]
|
|
|
|
if (typeof v === 'number') { return v }
|
|
|
|
}
|
|
|
|
return defaultDebug
|
|
|
|
}
|
|
|
|
|
2024-02-29 14:58:41 +00:00
|
|
|
function debugMucAdmins (options: RegisterServerOptions): string[] | undefined {
|
|
|
|
const debugContent = _readDebugFile(options)
|
|
|
|
if (!debugContent) { return undefined }
|
|
|
|
return debugContent.mucAdmins
|
|
|
|
}
|
|
|
|
|
2023-05-23 10:39:05 +00:00
|
|
|
export {
|
|
|
|
unloadDebugMode,
|
|
|
|
isDebugMode,
|
|
|
|
prosodyDebuggerOptions,
|
|
|
|
disableLuaUnboundIfNeeded,
|
2024-02-29 14:58:41 +00:00
|
|
|
debugNumericParameter,
|
|
|
|
debugMucAdmins
|
2023-05-23 10:39:05 +00:00
|
|
|
}
|