Add server-side validation for snippet names

This commit is contained in:
Andrew Kingston 2024-03-13 11:48:17 +00:00
parent 74a2b54880
commit 2d12a1a8fa
3 changed files with 26 additions and 13 deletions

View File

@ -13,13 +13,13 @@
import { snippets } from "stores/builder"
import { getSequentialName } from "helpers/duplicate"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { ValidSnippetNameRegex } from "@budibase/shared-core"
export let snippet
export const show = () => drawer.show()
export const hide = () => drawer.hide()
const roughValidNameRegex = /^[_$A-Z\xA0-\uFFFF][_$A-Z0-9\xA0-\uFFFF]*$/i
const firstCharNumberRegex = /^[0-9].*$/
let drawer
@ -43,7 +43,7 @@
drawer.hide()
notifications.success(`Snippet ${newSnippet.name} saved`)
} catch (error) {
notifications.error("Error saving snippet")
notifications.error(error.message || "Error saving snippet")
}
loading = false
}
@ -69,21 +69,16 @@
if (!name?.length) {
return "Name is required"
}
if (firstCharNumberRegex.test(name)) {
return "Can't start with a number"
}
if (!roughValidNameRegex.test(name)) {
return "No special characters or spaces"
}
if (snippets.some(snippet => snippet.name === name)) {
return "That name is already in use"
}
const js = `(function ${name}(){return true})()`
try {
return eval(js) === true ? null : "Invalid name"
} catch (error) {
return "Invalid name"
if (firstCharNumberRegex.test(name)) {
return "Can't start with a number"
}
if (!ValidSnippetNameRegex.test(name)) {
return "No special characters or spaces"
}
return null
}
</script>

View File

@ -2,6 +2,7 @@ import { auth, permissions } from "@budibase/backend-core"
import { DataSourceOperation } from "../../../constants"
import { WebhookActionType } from "@budibase/types"
import Joi from "joi"
import { ValidSnippetNameRegex } from "@budibase/shared-core"
const OPTIONAL_STRING = Joi.string().optional().allow(null).allow("")
const OPTIONAL_NUMBER = Joi.number().optional().allow(null)
@ -226,6 +227,21 @@ export function applicationValidator(opts = { isCreate: true }) {
base.name = appNameValidator.optional()
}
const snippetValidator = Joi.array()
.optional()
.items(
Joi.object({
name: Joi.string()
.pattern(new RegExp(ValidSnippetNameRegex))
.error(
new Error(
"Snippet name cannot include spaces or special characters, and cannot start with a number"
)
),
code: OPTIONAL_STRING,
})
)
return auth.joiValidator.body(
Joi.object({
_id: OPTIONAL_STRING,
@ -235,6 +251,7 @@ export function applicationValidator(opts = { isCreate: true }) {
template: Joi.object({
templateString: OPTIONAL_STRING,
}).unknown(true),
snippets: snippetValidator,
}).unknown(true)
)
}

View File

@ -98,6 +98,7 @@ export enum BuilderSocketEvent {
export const SocketSessionTTL = 60
export const ValidQueryNameRegex = /^[^()]*$/
export const ValidColumnNameRegex = /^[_a-zA-Z0-9\s]*$/g
export const ValidSnippetNameRegex = /^[a-z-_][a-z0-9-_]*$/i
export const REBOOT_CRON = "@reboot"