From da363fa24bb991cdc925f5e2111f1d4311e9cf0a Mon Sep 17 00:00:00 2001 From: Dillon Shook Date: Thu, 31 Oct 2024 22:35:55 -0400 Subject: [PATCH] Self review and validate cron schedules --- src/routes/user/system/SystemRouter.ts | 4 +--- src/user/system/CaptainManager.ts | 14 ++++++++++++-- src/user/system/DiskCleanupManager.ts | 14 ++------------ src/utils/Utils.ts | 18 ++++++++++++++++++ 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/routes/user/system/SystemRouter.ts b/src/routes/user/system/SystemRouter.ts index 28a1c82..5c99695 100644 --- a/src/routes/user/system/SystemRouter.ts +++ b/src/routes/user/system/SystemRouter.ts @@ -12,8 +12,8 @@ import VersionManager from '../../../user/system/VersionManager' import CaptainConstants from '../../../utils/CaptainConstants' import Logger from '../../../utils/Logger' import Utils from '../../../utils/Utils' -import SystemRouteSelfHostRegistry from './selfhostregistry/SystemRouteSelfHostRegistry' import ThemesRouter from './ThemesRouter' +import SystemRouteSelfHostRegistry from './selfhostregistry/SystemRouteSelfHostRegistry' const router = express.Router() @@ -308,8 +308,6 @@ router.get('/goaccess/', function (req, res, next) { router.post('/goaccess/', function (req, res, next) { const goAccessInfo = req.body.goAccessInfo - // goAccessInfo.netDataUrl = undefined // Frontend app returns this value, but we really don't wanna save this. - // // root address is subject to change. return Promise.resolve() .then(function () { diff --git a/src/user/system/CaptainManager.ts b/src/user/system/CaptainManager.ts index dac15b1..56e8976 100644 --- a/src/user/system/CaptainManager.ts +++ b/src/user/system/CaptainManager.ts @@ -676,6 +676,18 @@ class CaptainManager { const self = this const dockerApi = this.dockerApi const enabled = goAccessInfo.isEnabled + + // Validate cron schedules + if ( + !Utils.validateCron(goAccessInfo.data.catchupFrequencyCron) || + !Utils.validateCron(goAccessInfo.data.rotationFrequencyCron) + ) { + throw ApiStatusCodes.createError( + ApiStatusCodes.ILLEGAL_PARAMETER, + 'Invalid cron schedule' + ) + } + const crontabFilePath = `${ CaptainConstants.goaccessConfigPathBase }/crontab.txt` @@ -698,8 +710,6 @@ class CaptainManager { }) .then(function () { if (enabled) { - // const crontab = self.generateGoAccessCrontab(goAccessInfo); - return dockerApi.createStickyContainer( CaptainConstants.goAccessContainerName, CaptainConstants.configs.goAccessImageName, diff --git a/src/user/system/DiskCleanupManager.ts b/src/user/system/DiskCleanupManager.ts index 13033ce..e538e79 100644 --- a/src/user/system/DiskCleanupManager.ts +++ b/src/user/system/DiskCleanupManager.ts @@ -5,6 +5,7 @@ import DataStore from '../../datastore/DataStore' import DockerApi from '../../docker/DockerApi' import { IAutomatedCleanupConfigs } from '../../models/AutomatedCleanupConfigs' import Logger from '../../utils/Logger' +import Utils from '../../utils/Utils' export default class DiskCleanupManager { private job: CronJob | undefined @@ -171,18 +172,7 @@ export default class DiskCleanupManager { return // no need to validate cron schedule } - try { - const testJob = new CronJob( - configs.cronSchedule, // cronTime - function () { - // nothing - }, // onTick - null, // onComplete - false, // start - configs.timezone // timezone - ) - testJob.stop() - } catch (e) { + if (!Utils.validateCron(configs.cronSchedule)) { throw ApiStatusCodes.createError( ApiStatusCodes.ILLEGAL_PARAMETER, 'Invalid cron schedule' diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index 55c1255..04f6d40 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -1,3 +1,4 @@ +import { CronJob } from 'cron' import * as crypto from 'crypto' import { remove } from 'fs-extra' import * as yaml from 'yaml' @@ -162,4 +163,21 @@ export default class Utils { throw 'Domain name is not accepted. Custom domain cannot be subdomain of root domain.' } } + + static validateCron(schedule: string) { + try { + const testJob = new CronJob( + schedule, // cronTime + function () {}, // onTick + null, // onComplete + false, // start + 'UTC' // timezone + ) + testJob.stop() + } catch (e) { + return false + } + + return true + } }