1
0
Fork 0
mirror of synced 2024-09-30 17:18:14 +13:00

Adding some basic cron validation to publishing, currently the error is not explained if it is hit - still need some frontend for this, but this now means that an error is provided to users when attempting to publish, and we can re-use this validation in the automation UI. Need to have both backend and frontend validation as invalid CRONs will already exist, backend makes sure these are error'd on.

This commit is contained in:
mike12345567 2024-02-09 18:04:40 +00:00
parent 7aa1176a36
commit 8bf79c5f10
7 changed files with 122 additions and 5 deletions

View file

@ -101,7 +101,13 @@
} catch (error) {
console.error(error)
analytics.captureException(error)
notifications.error("Error publishing app")
const baseMsg = "Error publishing app"
const message = error.message
if (message) {
notifications.error(`${baseMsg} - ${message}`)
} else {
notifications.error(baseMsg)
}
}
publishing = false
}

View file

@ -16,6 +16,7 @@ import {
} from "@budibase/types"
import sdk from "../sdk"
import { automationsEnabled } from "../features"
import { helpers } from "@budibase/shared-core"
import tracer from "dd-trace"
const REBOOT_CRON = "@reboot"
@ -198,6 +199,13 @@ export async function enableCronTrigger(appId: any, automation: Automation) {
!isRebootTrigger(automation) &&
trigger?.inputs.cron
) {
const cronExp = trigger.inputs.cron
const validation = helpers.cron.validate(cronExp)
if (!validation.valid) {
throw new Error(
`Invalid automation CRON "${cronExp}" - ${validation.err.join(", ")}`
)
}
// make a job id rather than letting Bull decide, makes it easier to handle on way out
const jobId = `${appId}_cron_${newid()}`
const job: any = await automationQueue.add(
@ -205,7 +213,7 @@ export async function enableCronTrigger(appId: any, automation: Automation) {
automation,
event: { appId, timestamp: Date.now() },
},
{ repeat: { cron: trigger.inputs.cron }, jobId }
{ repeat: { cron: cronExp }, jobId }
)
// Assign cron job ID from bull so we can remove it later if the cron trigger is removed
trigger.cronJobId = job.id

View file

@ -14,7 +14,8 @@
"check:types": "tsc -p tsconfig.json --noEmit --paths null"
},
"dependencies": {
"@budibase/types": "0.0.0"
"@budibase/types": "0.0.0",
"cron-validate": "^1.4.5"
},
"devDependencies": {
"rimraf": "3.0.2",

View file

@ -0,0 +1,47 @@
import cronValidate from "cron-validate"
const INPUT_CRON_START = "(Input cron: "
const ERROR_SWAPS = {
"smaller than lower limit": "less than",
"bigger than upper limit": "greater than",
daysOfMonth: "'days of the month'",
daysOfWeek: "'days of the week'",
years: "'years'",
months: "'months'",
hours: "'hours'",
minutes: "'minutes'",
seconds: "'seconds'",
}
function improveErrors(errors: string[]): string[] {
const finalErrors: string[] = []
for (let error of errors) {
if (error.includes(INPUT_CRON_START)) {
error = error.split(INPUT_CRON_START)[0].trim()
}
for (let [key, value] of Object.entries(ERROR_SWAPS)) {
if (error.includes(key)) {
error = error.replace(new RegExp(key, "g"), value)
}
}
finalErrors.push(error)
}
return finalErrors
}
export function validate(
cronExpression: string
): { valid: false; err: string[] } | { valid: true } {
const result = cronValidate(cronExpression, {
preset: "npm-node-cron",
override: {
useSeconds: false,
},
})
if (!result.isValid()) {
return { valid: false, err: improveErrors(result.getError()) }
} else {
return { valid: true }
}
}

View file

@ -1,2 +1,3 @@
export * from "./helpers"
export * from "./integrations"
export * as cron from "./cron"

View file

@ -0,0 +1,22 @@
import { expect, describe, it } from "vitest"
import { cron } from "../helpers"
describe("check valid and invalid crons", () => {
it("invalid - 0 0 0 11 *", () => {
expect(cron.validate("0 0 0 11 *")).toStrictEqual({
valid: false,
err: [expect.stringContaining("less than '1'")],
})
})
it("invalid - 5 4 32 1 1", () => {
expect(cron.validate("5 4 32 1 1")).toStrictEqual({
valid: false,
err: [expect.stringContaining("greater than '31'")],
})
})
it("valid - * * * * *", () => {
expect(cron.validate("* * * * *")).toStrictEqual({ valid: true })
})
})

View file

@ -1980,6 +1980,13 @@
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
"@babel/runtime@^7.10.5":
version "7.23.9"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7"
integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.21.0", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
version "7.23.8"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.8.tgz#8ee6fe1ac47add7122902f257b8ddf55c898f650"
@ -5431,6 +5438,11 @@
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.200.tgz#435b6035c7eba9cdf1e039af8212c9e9281e7149"
integrity sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==
"@types/lodash@^4.14.165":
version "4.14.202"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.202.tgz#f09dbd2fb082d507178b2f2a5c7e74bd72ff98f8"
integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==
"@types/long@^4.0.0":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
@ -8541,6 +8553,13 @@ cron-parser@^4.2.1:
dependencies:
luxon "^3.2.1"
cron-validate@^1.4.5:
version "1.4.5"
resolved "https://registry.yarnpkg.com/cron-validate/-/cron-validate-1.4.5.tgz#eceb221f7558e6302e5f84c7b3a454fdf4d064c3"
integrity sha512-nKlOJEnYKudMn/aNyNH8xxWczlfpaazfWV32Pcx/2St51r2bxWbGhZD7uwzMcRhunA/ZNL+Htm/i0792Z59UMQ==
dependencies:
yup "0.32.9"
cross-spawn@^6.0.0:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@ -14440,7 +14459,7 @@ lock@^1.1.0:
resolved "https://registry.yarnpkg.com/lock/-/lock-1.1.0.tgz#53157499d1653b136ca66451071fca615703fa55"
integrity sha512-NZQIJJL5Rb9lMJ0Yl1JoVr9GSdo4HTPsUEWsSFzB8dE8DSoiLCVavWZPi7Rnlv/o73u6I24S/XYc/NmG4l8EKA==
lodash-es@^4.17.21:
lodash-es@^4.17.15, lodash-es@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
@ -14590,7 +14609,7 @@ lodash.xor@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.xor/-/lodash.xor-4.5.0.tgz#4d48ed7e98095b0632582ba714d3ff8ae8fb1db6"
integrity sha512-sVN2zimthq7aZ5sPGXnSz32rZPuqcparVW50chJQe+mzTYV+IsxSsl/2gnkWWE2Of7K3myBQBqtLKOUEHJKRsQ==
lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.7.0:
lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@ -22020,6 +22039,19 @@ yocto-queue@^1.0.0:
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251"
integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==
yup@0.32.9:
version "0.32.9"
resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.9.tgz#9367bec6b1b0e39211ecbca598702e106019d872"
integrity sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==
dependencies:
"@babel/runtime" "^7.10.5"
"@types/lodash" "^4.14.165"
lodash "^4.17.20"
lodash-es "^4.17.15"
nanoclone "^0.2.1"
property-expr "^2.0.4"
toposort "^2.0.2"
yup@^0.32.11:
version "0.32.11"
resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5"