From 8fe48a068fb949c5c518fafe568421a7fea31aea Mon Sep 17 00:00:00 2001 From: John Livingston Date: Tue, 23 May 2023 12:39:05 +0200 Subject: [PATCH] Refactoring the debug mode code, and adding some options. --- CHANGELOG.md | 2 + server/lib/debug.ts | 193 +++++++++++++----- server/lib/prosody/certificates.ts | 7 +- server/lib/prosody/logrotate.ts | 9 +- server/main.ts | 3 + .../content/contributing/develop/_index.de.md | 2 + .../content/contributing/develop/_index.en.md | 2 + .../content/contributing/develop/_index.fr.md | 2 + 8 files changed, 157 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16a3fd0e..ffd72458 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ TODO: write the new prosody modules README. TODO: mod_s2s_peertubelivechat: dont allow to connect to remote server that are not Peertube servers. TODO: when sanitizing remote chat endpoint, check that the domain is the same as the video domain (or is room.videodomain.tld). TODO: get remote server chat informations if missing (for now, it can be missing if there is no known remote video from that server). +TODO: outgoing s2s connection have a session.secure=true hardcoded. Should not. ### Minor changes and fixes @@ -21,6 +22,7 @@ TODO: get remote server chat informations if missing (for now, it can be missing * Using process.spawn instead of process.exec to launch Prosody (safer, and more optimal). * Prosody AppImage: fix path mapping: we only map necessary /etc/ subdir, so that the AppImage can access to /etc/resolv.conf, /etc/hosts, ... * Prosody AppImage: hidden debug mode to disable lua-unbound, that seems broken in some docker dev environments. +* Debug Mode: can change some parameters. ## 6.3.0 diff --git a/server/lib/debug.ts b/server/lib/debug.ts index 5bfb0e7f..84083eba 100644 --- a/server/lib/debug.ts +++ b/server/lib/debug.ts @@ -2,72 +2,121 @@ import type { RegisterServerOptions } from '@peertube/peertube-types' import * as path from 'path' import * as fs from 'fs' -/** - * Check if debug mode is enabled - * @param options server options - * @returns true if debug mode enabled - */ -export function isDebugMode (options: RegisterServerOptions): boolean { - const peertubeHelpers = options.peertubeHelpers - const logger = peertubeHelpers.logger - - if (!peertubeHelpers.plugin) { - return false - } - const filepath = path.resolve(peertubeHelpers.plugin.getDataDirectoryPath(), 'debug_mode') - logger.debug('Testing debug mode by testing if file exists: ' + filepath) - if (fs.existsSync(filepath)) { - logger.info('Plugin livechat Debug mode is on.') - return true - } - return false -} - interface ProsodyDebuggerOptions { mobdebugPath: string mobdebugHost: string mobdebugPort: string } +interface DebugContent { + renewCertCheckInterval?: number + renewSelfSignedCertInterval?: number + logRotateCheckInterval?: number + logRotateEvery?: number + prosodyDebuggerOptions?: ProsodyDebuggerOptions +} + +type DebugNumericValue = 'renewCertCheckInterval' +| 'renewSelfSignedCertInterval' +| 'logRotateEvery' +| 'logRotateCheckInterval' + +let debugContent: DebugContent | null | false = null +function _readDebugFile (options: RegisterServerOptions): DebugContent | false { + if (debugContent !== null) { return debugContent } + + const peertubeHelpers = options.peertubeHelpers + const logger = peertubeHelpers.logger + if (!peertubeHelpers.plugin) { + return false + } + + const filepath = path.resolve(peertubeHelpers.plugin.getDataDirectoryPath(), 'debug_mode') + logger.debug('Testing debug mode by testing if file exists: ' + filepath) + if (!fs.existsSync(filepath)) { + debugContent = false + return false + } + + 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') + } catch (err) { + logger.error('Failed to read the debug_mode file content:', err) + } + + return debugContent +} + +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 } + + const mobdebugPath = json.debug_prosody.debugger_path + + 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] +} + +function unloadDebugMode (): void { + debugContent = null +} + +/** + * Check if debug mode is enabled + * @param options server options + * @returns true if debug mode enabled + */ +function isDebugMode (options: RegisterServerOptions): boolean { + const debugContent = _readDebugFile(options) + return !!debugContent +} + /** * 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. */ -export function prosodyDebuggerOptions (options: RegisterServerOptions): false | ProsodyDebuggerOptions { +function prosodyDebuggerOptions (options: RegisterServerOptions): false | ProsodyDebuggerOptions { + // Additional security: testing NODE_ENV. + // It should absolutly not be possible to enable Prosody debugger on production ev. if (process.env.NODE_ENV !== 'dev') { return false } - if (!isDebugMode(options)) { return false } - - const peertubeHelpers = options.peertubeHelpers - const logger = peertubeHelpers.logger - - try { - const filepath = path.resolve(peertubeHelpers.plugin.getDataDirectoryPath(), 'debug_mode') - const content = fs.readFileSync(filepath).toString() - if (!content) { return false } - const json = JSON.parse(content) - if (!json) { return false } - if (typeof json !== 'object') { return false } - if (!json.debug_prosody) { return false } - if (typeof json.debug_prosody !== 'object') { return false } - if (!json.debug_prosody.debugger_path) { return false } - if (typeof json.debug_prosody.debugger_path !== 'string') { return false } - const mobdebugPath = json.debug_prosody.debugger_path - if (!fs.statSync(mobdebugPath).isDirectory()) { - logger.error('The should be a debugger, but cant find it. Path should be: ', mobdebugPath) - return false - } - const mobdebugHost = json.debug_prosody.host?.toString() || 'localhost' - const mobdebugPort = json.debug_prosody.port?.toString() || '8172' - return { - mobdebugPath, - mobdebugHost, - mobdebugPort - } - } catch (err) { - logger.error('Failed to read the debug_mode file content:', err) - return false - } + const debugContent = _readDebugFile(options) + if (debugContent === false) { return false } + if (!debugContent.prosodyDebuggerOptions) { return false } + return debugContent.prosodyDebuggerOptions } /** @@ -79,7 +128,7 @@ export function prosodyDebuggerOptions (options: RegisterServerOptions): false | * @param options server options * @param squashfsPath the folder where the AppImage is extracted */ -export function disableLuaUnboundIfNeeded (options: RegisterServerOptions, squashfsPath: string): void { +function disableLuaUnboundIfNeeded (options: RegisterServerOptions, squashfsPath: string): void { const peertubeHelpers = options.peertubeHelpers const logger = peertubeHelpers.logger @@ -103,3 +152,37 @@ export function disableLuaUnboundIfNeeded (options: RegisterServerOptions, squas logger.error(err) } } + +/** + * 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 +} + +export { + unloadDebugMode, + isDebugMode, + prosodyDebuggerOptions, + disableLuaUnboundIfNeeded, + debugNumericParameter +} diff --git a/server/lib/prosody/certificates.ts b/server/lib/prosody/certificates.ts index 45e37d5a..95061d3a 100644 --- a/server/lib/prosody/certificates.ts +++ b/server/lib/prosody/certificates.ts @@ -1,6 +1,6 @@ import type { RegisterServerOptions } from '@peertube/peertube-types' import type { ProsodyConfig } from './config' -import { isDebugMode } from '../debug' +import { debugNumericParameter } from '../debug' import { prosodyCtl, reloadProsody } from './ctl' import * as path from 'path' import * as fs from 'fs' @@ -18,9 +18,8 @@ function startProsodyCertificatesRenewCheck (options: RegisterServerOptions, con return } - const debugMode = isDebugMode(options) // check every day (or every minutes in debug mode) - const checkInterval = debugMode ? 60000 : 3600000 * 24 + const checkInterval = debugNumericParameter(options, 'renewCertCheckInterval', 60000, 3600000 * 24) if (renew) { stopProsodyCertificatesRenewCheck(options) @@ -91,8 +90,8 @@ async function renewCheckSelfSigned (options: RegisterServerOptions, config: Pro // We have to check if the self signed certificate is still valid. // Prosodyctl generated certificates are valid 365 days. // We will renew it every 10 months (and every X minutes in debug mode) + const renewEvery = debugNumericParameter(options, 'renewSelfSignedCertInterval', 5 * 60000, 3600000 * 24 * 30 * 10) - const renewEvery = isDebugMode(options) ? 5 * 60000 : 3600000 * 24 * 30 * 10 // getting the file date... const filepath = _filePathToTest(options, config) if (!filepath) { return } diff --git a/server/lib/prosody/logrotate.ts b/server/lib/prosody/logrotate.ts index 881e704c..2d3fc094 100644 --- a/server/lib/prosody/logrotate.ts +++ b/server/lib/prosody/logrotate.ts @@ -1,6 +1,6 @@ import type { RegisterServerOptions } from '@peertube/peertube-types' import type { ProsodyFilePaths } from './config/paths' -import { isDebugMode } from '../debug' +import { debugNumericParameter } from '../debug' import { reloadProsody } from './ctl' type Rotate = (file: string, options: { @@ -33,9 +33,10 @@ async function _rotate (options: RegisterServerOptions, path: string): Promise { } } + unloadDebugMode() + const module = __filename OPTIONS?.peertubeHelpers.logger.info(`Unloading module ${module}...`) // Peertube calls decache(plugin) on register, not unregister. diff --git a/support/documentation/content/contributing/develop/_index.de.md b/support/documentation/content/contributing/develop/_index.de.md index 7c2fe496..6259ca95 100644 --- a/support/documentation/content/contributing/develop/_index.de.md +++ b/support/documentation/content/contributing/develop/_index.de.md @@ -79,6 +79,8 @@ The simple existence of this file is sufficient to trigger the debug mode. To make sure it's taken into account, you can restart your Peertube instance. This file can contain some JSON to enable more advances options. +To have a list of existing parameters, check `server/lib/debug.ts`. +Restart Peertube after each content modification. {{% notice warning %}} Don't enable this mode on a production server, neither on a public server. diff --git a/support/documentation/content/contributing/develop/_index.en.md b/support/documentation/content/contributing/develop/_index.en.md index 3f2a22f3..503317d8 100644 --- a/support/documentation/content/contributing/develop/_index.en.md +++ b/support/documentation/content/contributing/develop/_index.en.md @@ -81,6 +81,8 @@ The simple existence of this file is sufficient to trigger the debug mode. To make sure it's taken into account, you can restart your Peertube instance. This file can contain some JSON to enable more advances options. +To have a list of existing parameters, check `server/lib/debug.ts`. +Restart Peertube after each content modification. {{% notice warning %}} Don't enable this mode on a production server, neither on a public server. diff --git a/support/documentation/content/contributing/develop/_index.fr.md b/support/documentation/content/contributing/develop/_index.fr.md index 5ddc2fdf..896fb615 100644 --- a/support/documentation/content/contributing/develop/_index.fr.md +++ b/support/documentation/content/contributing/develop/_index.fr.md @@ -80,6 +80,8 @@ La simple existance de ce fichier suffit à déclencher le mode debug. Pour être sûr qu'il est pris en compte, vous pouvez redémarrer votre instance Peertube. Ce fichier peut également contenir du JSON qui pourra activer d'autres options. +Pour en avoir la liste, vous pouvez regarder le code de `server/lib/debug.ts`. +Redémarrez Peertube après chaque modification de son contenu. {{% notice warning %}} N'activer jamais ce mode sur un serveur de production, ni même sur un serveur public.