From 2961513d2201a63c1338216b0a571b1bc381c8be Mon Sep 17 00:00:00 2001 From: John Livingston Date: Wed, 24 May 2023 16:26:57 +0200 Subject: [PATCH] Refresh remote server infos when outdated. --- server/lib/debug.ts | 3 +++ server/lib/federation/fetch-infos.ts | 8 ++++-- server/lib/federation/storage.ts | 38 ++++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/server/lib/debug.ts b/server/lib/debug.ts index 84083eba..c032ede5 100644 --- a/server/lib/debug.ts +++ b/server/lib/debug.ts @@ -13,6 +13,7 @@ interface DebugContent { renewSelfSignedCertInterval?: number logRotateCheckInterval?: number logRotateEvery?: number + remoteServerInfosMaxAge?: number prosodyDebuggerOptions?: ProsodyDebuggerOptions } @@ -20,6 +21,7 @@ type DebugNumericValue = 'renewCertCheckInterval' | 'renewSelfSignedCertInterval' | 'logRotateEvery' | 'logRotateCheckInterval' +| 'remoteServerInfosMaxAge' let debugContent: DebugContent | null | false = null function _readDebugFile (options: RegisterServerOptions): DebugContent | false { @@ -52,6 +54,7 @@ function _readDebugFile (options: RegisterServerOptions): DebugContent | false { 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') + debugContent.remoteServerInfosMaxAge = _getNumericOptions(options, json, 'remote_server_infos_max_age') } catch (err) { logger.error('Failed to read the debug_mode file content:', err) } diff --git a/server/lib/federation/fetch-infos.ts b/server/lib/federation/fetch-infos.ts index 9b5f75f8..2c405e11 100644 --- a/server/lib/federation/fetch-infos.ts +++ b/server/lib/federation/fetch-infos.ts @@ -3,6 +3,7 @@ import { hasRemoteServerInfos, storeRemoteServerInfos } from './storage' import { getBaseRouterRoute } from '../helpers' import { canonicalizePluginUri } from '../uri/canonicalize' import { sanitizePeertubeLiveChatServerInfos } from './sanitize' +import { debugNumericParameter } from '../debug' import { URL } from 'url' const got = require('got') @@ -42,8 +43,11 @@ async function fetchMissingRemoteServerInfos ( const logger = options.peertubeHelpers.logger logger.debug(`remoteServerInfos: checking if we have remote server infos for host ${remoteInstanceUrl}.`) - // FIXME: add a max age. - if (await hasRemoteServerInfos(options, remoteInstanceUrl)) { + // maxAge: max allowed aged for stored remote server infos (in milliseconds). + // In production: 24 hours + // In debug mode: 1hour + const maxAge = debugNumericParameter(options, 'remoteServerInfosMaxAge', 3600000, 3600 * 1000 * 24) + if (await hasRemoteServerInfos(options, remoteInstanceUrl, maxAge)) { return } diff --git a/server/lib/federation/storage.ts b/server/lib/federation/storage.ts index 3c24ec75..92f81a27 100644 --- a/server/lib/federation/storage.ts +++ b/server/lib/federation/storage.ts @@ -171,8 +171,13 @@ async function storeRemoteServerInfos ( * Indicate if we have the remote hosts informations. * @param options server options * @param host host domain + * @param maxAge if given, the max age (in milliseconds) allowed for remote server informations */ -async function hasRemoteServerInfos (options: RegisterServerOptions, hostParam: any): Promise { +async function hasRemoteServerInfos ( + options: RegisterServerOptions, + hostParam: any, + maxAge?: number +): Promise { const host = sanitizeXMPPHostFromInstanceUrl(options, hostParam) if (!host) { return false @@ -187,7 +192,36 @@ async function hasRemoteServerInfos (options: RegisterServerOptions, hostParam: host, 'last-update' ) - return fs.existsSync(filePath) + if (!fs.existsSync(filePath)) { + return false + } + if (maxAge === undefined) { + return true + } + + // We must check the 'last-update' to be newer than maxAge + try { + const content = await fs.promises.readFile(filePath, { + encoding: 'utf-8' + }) + const json = JSON.parse(content) + if (!json) { return false } + if (typeof json !== 'object') { return false } + if (!json.timestamp) { return false } + if ((typeof json.timestamp) !== 'number') { return false } + const now = (new Date()).getTime() + if (now - (json.timestamp as number) > maxAge) { + options.peertubeHelpers.logger.info( + `Remote informations for server ${host} are outdated.` + ) + return false + } + } catch (err) { + options.peertubeHelpers.logger.error('Failed reading the last-update file:', err) + return false + } + + return true } async function _getFilePath (