WIP on Prosody integration.

This commit is contained in:
John Livingston 2021-04-13 17:13:41 +02:00
parent 4690d97384
commit cc21305f6a
5 changed files with 164 additions and 22 deletions

View File

@ -1,5 +1,6 @@
import { getWorkingDir } from '../prosody/config'
import { getProsodyConfigContent, getProsodyConfigPath, getWorkingDir } from '../prosody/config'
import { newResult, TestResult } from './utils'
import * as fs from 'fs'
export async function diagProsody (test: string, options: RegisterServerOptions): Promise<TestResult> {
const result = newResult(test)
@ -13,6 +14,26 @@ export async function diagProsody (test: string, options: RegisterServerOptions)
return result
}
// Testing the prosody config file.
try {
const filePath = await getProsodyConfigPath(options)
await fs.promises.access(filePath, fs.constants.R_OK) // throw an error if file does not exist.
result.messages.push(`The prosody configuration file (${filePath}) exists`)
const actualContent = await fs.promises.readFile(filePath, {
encoding: 'utf-8'
})
const wantedContent = await getProsodyConfigContent(options)
if (actualContent === wantedContent) {
result.messages.push('Prosody configuration file content is correct.')
} else {
result.messages.push('Prosody configuration file content is not correct.')
return result
}
} catch (error) {
result.messages.push('Error when requiring the prosody config file: ' + (error as string))
return result
}
result.ok = true
return result
}

View File

@ -1,4 +1,5 @@
import * as fs from 'fs'
import * as path from 'path'
import { pluginName } from '../helpers'
type LogMode = 'debug' | 'info'
@ -13,10 +14,15 @@ async function getWorkingDir ({ peertubeHelpers, storageManager }: RegisterServe
const tmpBaseDir = '/tmp/'
await fs.promises.access(tmpBaseDir, fs.constants.W_OK) // will throw an error if no access
let value: string = await storageManager.getData('tempDirId')
function getPath (value: string): string {
return path.resolve(tmpBaseDir, pluginName + '-' + value)
}
while (!value) {
peertubeHelpers.logger.info('Generating an id for temp dir')
value = Math.random().toString(36).slice(2, 12)
const name = tmpBaseDir + pluginName + '-' + value
const name = getPath(value)
if (fs.existsSync(name)) {
peertubeHelpers.logger.info('The folder ' + name + ' already exists, generating another name...')
value = ''
@ -25,7 +31,7 @@ async function getWorkingDir ({ peertubeHelpers, storageManager }: RegisterServe
await storageManager.storeData('tempDirId', value)
}
const name = tmpBaseDir + pluginName + '-' + value
const name = getPath(value)
if (!fs.existsSync(name)) {
await fs.promises.mkdir(name)
}
@ -33,9 +39,25 @@ async function getWorkingDir ({ peertubeHelpers, storageManager }: RegisterServe
return name
}
async function getProsodyConfig (_options: RegisterServerOptions): Promise<string> {
interface ProsodyFilePaths {
pid: string
error: string
log: string
config: string
}
async function getProsodyFilePaths (options: RegisterServerOptions): Promise<ProsodyFilePaths> {
const dir = await getWorkingDir(options)
return {
pid: path.resolve(dir, 'prosody.pid'),
error: path.resolve(dir, 'prosody.err'),
log: path.resolve(dir, 'prosody.log'),
config: path.resolve(dir, 'prosody.cfg.lua')
}
}
async function getProsodyConfigContent (options: RegisterServerOptions): Promise<string> {
const peertubeDomain = 'localhost'
const workingDirectory = '/tmp/'
const paths = await getProsodyFilePaths(options)
const logMode: LogMode = 'debug'
return `
@ -62,7 +84,7 @@ allow_registration = false
daemonize = true;
pidfile = "${workingDirectory}prosody.pid";
pidfile = "${paths.pid}";
c2s_require_encryption = false
@ -70,8 +92,8 @@ archive_expires_after = "1w" -- Remove archived messages after 1 week
log = {
-- Log files (change 'info' to 'debug' for debug logs):
${logMode} = "${workingDirectory}prosody.log";
error = "${workingDirectory}prosody.err";
${logMode} = "${paths.log}";
error = "${paths.error}";
-- Syslog:
-- { levels = { "error" }; to = "syslog"; };
}
@ -110,7 +132,23 @@ Component "room.localhost" "muc"
`
}
export {
getProsodyConfig,
getWorkingDir
async function getProsodyConfigPath (options: RegisterServerOptions): Promise<string> {
const paths = await getProsodyFilePaths(options)
return paths.config
}
async function writeProsodyConfig (options: RegisterServerOptions): Promise<void> {
const logger = options.peertubeHelpers.logger
const content = await getProsodyConfigContent(options)
const fileName = await getProsodyConfigPath(options)
logger.info(`Writing prosody configuration file to ${fileName}`)
await fs.promises.writeFile(fileName, content)
}
export {
getProsodyConfigContent,
getWorkingDir,
getProsodyFilePaths,
getProsodyConfigPath,
writeProsodyConfig
}

56
server/lib/prosody/ctl.ts Normal file
View File

@ -0,0 +1,56 @@
import { writeProsodyConfig } from './config'
/**
* @param options
* @returns true if prosody is running with up to date parameters. A string array of messages otherwise.
*/
async function testProsodyCorrectlyRunning (options: RegisterServerOptions): Promise<true | string[]> {
const { peertubeHelpers } = options
peertubeHelpers.logger.info('Checking if Prosody is correctly running')
// TODO
peertubeHelpers.logger.error('testProsodyCorrectlyRunning not implemented yet.')
return ['Process not found']
}
async function ensureProsodyRunning (options: RegisterServerOptions): Promise<void> {
const { peertubeHelpers, settingsManager } = options
const logger = peertubeHelpers.logger
const setting = await settingsManager.getSetting('chat-use-prosody')
if (!setting) {
logger.info('Prosody is not activated, we wont launch it')
return
}
const r = await testProsodyCorrectlyRunning(options)
if (r === true) {
logger.info('Prosody is already running correctly')
return
}
logger.info('Prosody is not running correctly: ' + r.join(', '))
// Shutting down...
await ensureProsodyNotRunning(options)
// writing the configuration file
await writeProsodyConfig(options)
// TODO: launch prosody
logger.error('ensureProsodyRunning not implemented yet.')
// TODO: listen for kill signal and kill prosody?
}
async function ensureProsodyNotRunning (options: RegisterServerOptions): Promise<void> {
const { peertubeHelpers } = options
peertubeHelpers.logger.info('Checking if Prosody is running, and shutting it down if so')
// TODO: implement this.
peertubeHelpers.logger.error('ensureProsodyNotRunning not implemented yet.')
}
export {
testProsodyCorrectlyRunning,
ensureProsodyRunning,
ensureProsodyNotRunning
}

View File

@ -1,8 +1,9 @@
import { getBaseRouter } from './helpers'
import { ensureProsodyRunning, ensureProsodyNotRunning } from './prosody/ctl'
export function initSettings (options: RegisterServerOptions): void {
const { peertubeHelpers, registerSetting, settingsManager } = options
export function initSettings ({
registerSetting
}: RegisterServerOptions): void {
registerSetting({
name: 'chat-read-documentation',
label: 'I have read the documentation',
@ -157,4 +158,20 @@ export function initSettings ({
'Example: height:400px;',
private: false
})
// settings changes management
// FIXME: Peertube <= 3.1.0 wrongly consider that the callback should not be async
// eslint-disable-next-line @typescript-eslint/no-misused-promises
settingsManager.onSettingsChange(async (settings: any) => {
if ('chat-use-prosody' in settings) {
if (settings['chat-use-prosody'] === true) {
peertubeHelpers.logger.info('Saving settings, ensuring prosody is running')
await ensureProsodyRunning(options)
} else if (settings['chat-use-prody'] === false) {
peertubeHelpers.logger.info('Saving settings, ensuring prosody is not running')
await ensureProsodyNotRunning(options)
}
}
})
}

View File

@ -1,26 +1,36 @@
import { initSettings } from './lib/settings'
import { initRouters } from './lib/routers/index'
import type { Logger } from 'winston'
import { ensureProsodyRunning, ensureProsodyNotRunning } from './lib/prosody/ctl'
import decache from 'decache'
let logger: Logger | undefined
// FIXME: in Peertube <= 3.1.0, unregister don't have any parameter.
// Using this global variable to fix this.
let OPTIONS: RegisterServerOptions | undefined
async function register (options: RegisterServerOptions): Promise<any> {
const { peertubeHelpers } = options
logger = peertubeHelpers.logger
OPTIONS = options
await initSettings(options)
await initRouters(options)
await ensureProsodyRunning(options)
}
async function unregister (): Promise<any> {
if (OPTIONS) {
try {
await ensureProsodyNotRunning(OPTIONS)
} catch (error) {
OPTIONS.peertubeHelpers.logger.error('Error when trying to unload Prosody: ' + (error as string))
}
}
const module = __filename
logger?.info(`Unloading module ${module}...`)
OPTIONS?.peertubeHelpers.logger.info(`Unloading module ${module}...`)
// In peertube <= 3.1.0 sub modules are not removed from require.cache
decache(module)
logger?.info(`Successfully unloaded the module ${module}`)
logger = undefined
OPTIONS?.peertubeHelpers.logger.info(`Successfully unloaded the module ${module}`)
OPTIONS = undefined
}
module.exports = {