mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #4368 from node-red/4340-switch-validation
Improve validation of switch/change node rules
This commit is contained in:
commit
c261f6625a
@ -1215,11 +1215,9 @@
|
|||||||
"validator": {
|
"validator": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"invalid-json": "Invalid JSON data: __error__",
|
"invalid-json": "Invalid JSON data: __error__",
|
||||||
"invalid-json-prop": "__prop__: invalid JSON data: __error__",
|
"invalid-expr": "Invalid JSONata expression: __error__",
|
||||||
"invalid-prop": "Invalid property expression",
|
"invalid-prop": "Invalid property expression",
|
||||||
"invalid-prop-prop": "__prop__: invalid property expression",
|
|
||||||
"invalid-num": "Invalid number",
|
"invalid-num": "Invalid number",
|
||||||
"invalid-num-prop": "__prop__: invalid number",
|
|
||||||
"invalid-regexp": "Invalid input pattern",
|
"invalid-regexp": "Invalid input pattern",
|
||||||
"invalid-regex-prop": "__prop__: invalid input pattern",
|
"invalid-regex-prop": "__prop__: invalid input pattern",
|
||||||
"missing-required-prop": "__prop__: property value missing",
|
"missing-required-prop": "__prop__: property value missing",
|
||||||
|
@ -1215,11 +1215,8 @@
|
|||||||
"validator": {
|
"validator": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"invalid-json": "Données JSON invalides : __error__",
|
"invalid-json": "Données JSON invalides : __error__",
|
||||||
"invalid-json-prop": "__prop__: données JSON invalides : __error__",
|
|
||||||
"invalid-prop": "Expression de propriété non valide",
|
"invalid-prop": "Expression de propriété non valide",
|
||||||
"invalid-prop-prop": "__prop__: expression de propriété invalide",
|
|
||||||
"invalid-num": "Numéro invalide",
|
"invalid-num": "Numéro invalide",
|
||||||
"invalid-num-prop": "__prop__: numéro invalide",
|
|
||||||
"invalid-regexp": "Modèle d'entrée non valide",
|
"invalid-regexp": "Modèle d'entrée non valide",
|
||||||
"invalid-regex-prop": "__prop__: modèle d'entrée non valide",
|
"invalid-regex-prop": "__prop__: modèle d'entrée non valide",
|
||||||
"missing-required-prop": "__prop__: valeur de la propriété manquante",
|
"missing-required-prop": "__prop__: valeur de la propriété manquante",
|
||||||
|
@ -1215,11 +1215,8 @@
|
|||||||
"validator": {
|
"validator": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"invalid-json": "JSONデータが不正: __error__",
|
"invalid-json": "JSONデータが不正: __error__",
|
||||||
"invalid-json-prop": "__prop__: JSONデータが不正: __error__",
|
|
||||||
"invalid-prop": "プロパティ式が不正",
|
"invalid-prop": "プロパティ式が不正",
|
||||||
"invalid-prop-prop": "__prop__: プロパティ式が不正",
|
|
||||||
"invalid-num": "数値が不正",
|
"invalid-num": "数値が不正",
|
||||||
"invalid-num-prop": "__prop__: 数値が不正",
|
|
||||||
"invalid-regexp": "入力パターンが不正",
|
"invalid-regexp": "入力パターンが不正",
|
||||||
"invalid-regex-prop": "__prop__: 入力パターンが不正",
|
"invalid-regex-prop": "__prop__: 入力パターンが不正",
|
||||||
"missing-required-prop": "__prop__: プロパティが未設定",
|
"missing-required-prop": "__prop__: プロパティが未設定",
|
||||||
|
@ -1186,11 +1186,8 @@
|
|||||||
"validator": {
|
"validator": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"invalid-json": "Dados JSON inválidos: __error__",
|
"invalid-json": "Dados JSON inválidos: __error__",
|
||||||
"invalid-json-prop": "__prop__: dados JSON inválidos: __error__",
|
|
||||||
"invalid-prop": "Expressão de propriedade inválida",
|
"invalid-prop": "Expressão de propriedade inválida",
|
||||||
"invalid-prop-prop": "__prop__: expressão de propriedade inválida",
|
|
||||||
"invalid-num": "Número inválido",
|
"invalid-num": "Número inválido",
|
||||||
"invalid-num-prop": "__prop__: número inválido",
|
|
||||||
"invalid-regexp": "Padrão de entrada inválido",
|
"invalid-regexp": "Padrão de entrada inválido",
|
||||||
"invalid-regex-prop": "__prop__: Padrão de entrada inválido",
|
"invalid-regex-prop": "__prop__: Padrão de entrada inválido",
|
||||||
"missing-required-prop": "__prop__: valor de propriedade ausente",
|
"missing-required-prop": "__prop__: valor de propriedade ausente",
|
||||||
|
@ -1199,11 +1199,8 @@
|
|||||||
"validator": {
|
"validator": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"invalid-json": "无效的 JSON 数据: __error__",
|
"invalid-json": "无效的 JSON 数据: __error__",
|
||||||
"invalid-json-prop": "__prop__: 无效的 JSON 数据: __error__",
|
|
||||||
"invalid-prop": "无效的属性表达式",
|
"invalid-prop": "无效的属性表达式",
|
||||||
"invalid-prop-prop": "__prop__: 无效的属性表达式",
|
|
||||||
"invalid-num": "无效的数字",
|
"invalid-num": "无效的数字",
|
||||||
"invalid-num-prop": "__prop__: 无效的数字",
|
|
||||||
"invalid-regexp": "输入格式无效",
|
"invalid-regexp": "输入格式无效",
|
||||||
"invalid-regex-prop": "__prop__: 输入格式无效",
|
"invalid-regex-prop": "__prop__: 输入格式无效",
|
||||||
"missing-required-prop": "__prop__: 缺少属性值",
|
"missing-required-prop": "__prop__: 缺少属性值",
|
||||||
|
@ -115,8 +115,9 @@ RED.editor = (function() {
|
|||||||
var valid = validateNodeProperty(node, definition, prop, properties[prop]);
|
var valid = validateNodeProperty(node, definition, prop, properties[prop]);
|
||||||
if ((typeof valid) === "string") {
|
if ((typeof valid) === "string") {
|
||||||
result.push(valid);
|
result.push(valid);
|
||||||
}
|
} else if (Array.isArray(valid)) {
|
||||||
else if(!valid) {
|
result = result.concat(valid)
|
||||||
|
} else if(!valid) {
|
||||||
result.push(prop);
|
result.push(prop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,7 +166,7 @@ RED.editor = (function() {
|
|||||||
// If the validator takes two arguments, it is a 3.x validator that
|
// If the validator takes two arguments, it is a 3.x validator that
|
||||||
// can return a String to mean 'invalid' and provide a reason
|
// can return a String to mean 'invalid' and provide a reason
|
||||||
if ((definition[property].validate.length === 2) &&
|
if ((definition[property].validate.length === 2) &&
|
||||||
((typeof valid) === "string")) {
|
((typeof valid) === "string") || Array.isArray(valid)) {
|
||||||
return valid;
|
return valid;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, a 2.x returns a truth-like/false-like value that
|
// Otherwise, a 2.x returns a truth-like/false-like value that
|
||||||
|
@ -917,6 +917,51 @@ RED.utils = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks a typed property is valid according to the type.
|
||||||
|
* Returns true if valid.
|
||||||
|
* Return String error message if invalid
|
||||||
|
* @param {*} propertyType
|
||||||
|
* @param {*} propertyValue
|
||||||
|
* @returns true if valid, String if invalid
|
||||||
|
*/
|
||||||
|
function validateTypedProperty(propertyValue, propertyType, opt) {
|
||||||
|
|
||||||
|
let error
|
||||||
|
if (propertyType === 'json') {
|
||||||
|
try {
|
||||||
|
JSON.parse(propertyValue);
|
||||||
|
} catch(err) {
|
||||||
|
error = RED._("validator.errors.invalid-json", {
|
||||||
|
error: err.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if (propertyType === 'msg' || propertyType === 'flow' || propertyType === 'global' ) {
|
||||||
|
if (!RED.utils.validatePropertyExpression(propertyValue)) {
|
||||||
|
error = RED._("validator.errors.invalid-prop")
|
||||||
|
}
|
||||||
|
} else if (propertyType === 'num') {
|
||||||
|
if (!/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(propertyValue)) {
|
||||||
|
error = RED._("validator.errors.invalid-num")
|
||||||
|
}
|
||||||
|
} else if (propertyType === 'jsonata') {
|
||||||
|
try {
|
||||||
|
jsonata(propertyValue)
|
||||||
|
} catch(err) {
|
||||||
|
error = RED._("validator.errors.invalid-expr", {
|
||||||
|
error: err.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
if (opt && opt.label) {
|
||||||
|
return opt.label+': '+error
|
||||||
|
}
|
||||||
|
return error
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
function getMessageProperty(msg,expr) {
|
function getMessageProperty(msg,expr) {
|
||||||
var result = null;
|
var result = null;
|
||||||
var msgPropParts;
|
var msgPropParts;
|
||||||
@ -1451,6 +1496,7 @@ RED.utils = (function() {
|
|||||||
getDarkerColor: getDarkerColor,
|
getDarkerColor: getDarkerColor,
|
||||||
parseModuleList: parseModuleList,
|
parseModuleList: parseModuleList,
|
||||||
checkModuleAllowed: checkModuleAllowed,
|
checkModuleAllowed: checkModuleAllowed,
|
||||||
getBrowserInfo: getBrowserInfo
|
getBrowserInfo: getBrowserInfo,
|
||||||
|
validateTypedProperty: validateTypedProperty
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -43,43 +43,13 @@ RED.validators = {
|
|||||||
typedInput: function(ptypeName,isConfig,mopt) {
|
typedInput: function(ptypeName,isConfig,mopt) {
|
||||||
return function(v, opt) {
|
return function(v, opt) {
|
||||||
var ptype = $("#node-"+(isConfig?"config-":"")+"input-"+ptypeName).val() || this[ptypeName];
|
var ptype = $("#node-"+(isConfig?"config-":"")+"input-"+ptypeName).val() || this[ptypeName];
|
||||||
if (ptype === 'json') {
|
const result = RED.utils.validateTypedProperty(v, ptype, opt)
|
||||||
try {
|
if (result === true || opt) {
|
||||||
JSON.parse(v);
|
// Valid, or opt provided - return result as-is
|
||||||
return true;
|
return result
|
||||||
} catch(err) {
|
|
||||||
if (opt && opt.label) {
|
|
||||||
return RED._("validator.errors.invalid-json-prop", {
|
|
||||||
error: err.message,
|
|
||||||
prop: opt.label,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return opt ? RED._("validator.errors.invalid-json", {
|
|
||||||
error: err.message
|
|
||||||
}) : false;
|
|
||||||
}
|
|
||||||
} else if (ptype === 'msg' || ptype === 'flow' || ptype === 'global' ) {
|
|
||||||
if (RED.utils.validatePropertyExpression(v)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (opt && opt.label) {
|
|
||||||
return RED._("validator.errors.invalid-prop-prop", {
|
|
||||||
prop: opt.label
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return opt ? RED._("validator.errors.invalid-prop") : false;
|
|
||||||
} else if (ptype === 'num') {
|
|
||||||
if (/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (opt && opt.label) {
|
|
||||||
return RED._("validator.errors.invalid-num-prop", {
|
|
||||||
prop: opt.label
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return opt ? RED._("validator.errors.invalid-num") : false;
|
|
||||||
}
|
}
|
||||||
return true;
|
// No opt - need to return false for backwards compatibilty
|
||||||
};
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -167,7 +167,33 @@
|
|||||||
label:RED._("node-red:common.label.payload"),
|
label:RED._("node-red:common.label.payload"),
|
||||||
validate: RED.validators.typedInput("propertyType", false)},
|
validate: RED.validators.typedInput("propertyType", false)},
|
||||||
propertyType: { value:"msg" },
|
propertyType: { value:"msg" },
|
||||||
rules: {value:[{t:"eq", v:"", vt:"str"}]},
|
rules: {
|
||||||
|
value:[{t:"eq", v:"", vt:"str"}],
|
||||||
|
validate: function (rules, opt) {
|
||||||
|
let msg;
|
||||||
|
const errors = []
|
||||||
|
if (!rules || rules.length === 0) { return true }
|
||||||
|
for (var i=0;i<rules.length;i++) {
|
||||||
|
const opt = { label: RED._('node-red:switch.label.rule')+' '+(i+1) }
|
||||||
|
const r = rules[i];
|
||||||
|
if (r.hasOwnProperty('v')) {
|
||||||
|
if ((msg = RED.utils.validateTypedProperty(r.v,r.vt,opt)) !== true) {
|
||||||
|
errors.push(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r.hasOwnProperty('v2')) {
|
||||||
|
if ((msg = RED.utils.validateTypedProperty(r.v2,r.v2t,opt)) !== true) {
|
||||||
|
errors.push(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errors.length) {
|
||||||
|
console.log(errors)
|
||||||
|
return errors
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
checkall: {value:"true", required:true},
|
checkall: {value:"true", required:true},
|
||||||
repair: {value:false},
|
repair: {value:false},
|
||||||
outputs: {value:1}
|
outputs: {value:1}
|
||||||
|
@ -19,71 +19,42 @@
|
|||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
(function() {
|
(function() {
|
||||||
function isInvalidProperty(v,vt) {
|
|
||||||
if (/msg|flow|global/.test(vt)) {
|
|
||||||
if (!RED.utils.validatePropertyExpression(v)) {
|
|
||||||
return RED._("node-red:change.errors.invalid-prop", {
|
|
||||||
property: v
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (vt === "jsonata") {
|
|
||||||
try{ jsonata(v); } catch(e) {
|
|
||||||
return RED._("node-red:change.errors.invalid-expr", {
|
|
||||||
error: e.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (vt === "json") {
|
|
||||||
try{ JSON.parse(v); } catch(e) {
|
|
||||||
return RED._("node-red:change.errors.invalid-json-data", {
|
|
||||||
error: e.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RED.nodes.registerType('change', {
|
RED.nodes.registerType('change', {
|
||||||
color: "#E2D96E",
|
color: "#E2D96E",
|
||||||
category: 'function',
|
category: 'function',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: {value:""},
|
name: {value:""},
|
||||||
rules:{value:[{t:"set",p:"payload",pt:"msg",to:"",tot:"str"}],validate: function(rules, opt) {
|
rules:{
|
||||||
var msg;
|
value:[{t:"set",p:"payload",pt:"msg",to:"",tot:"str"}],
|
||||||
if (!rules || rules.length === 0) { return true }
|
validate: function(rules, opt) {
|
||||||
for (var i=0;i<rules.length;i++) {
|
let msg;
|
||||||
var r = rules[i];
|
const errors = []
|
||||||
if (r.t === 'set') {
|
if (!rules || rules.length === 0) { return true }
|
||||||
if (msg = isInvalidProperty(r.p,r.pt)) {
|
for (var i=0;i<rules.length;i++) {
|
||||||
return msg;
|
const opt = { label: RED._('node-red:change.label.rule')+' '+(i+1) }
|
||||||
|
const r = rules[i];
|
||||||
|
if (r.t === 'set' || r.t === 'change' || r.t === 'delete' || r.t === 'move') {
|
||||||
|
if ((msg = RED.utils.validateTypedProperty(r.p,r.pt,opt)) !== true) {
|
||||||
|
errors.push(msg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (msg = isInvalidProperty(r.to,r.tot)) {
|
if (r.t === 'set' || r.t === 'change' || r.t === 'move') {
|
||||||
return msg;
|
if ((msg = RED.utils.validateTypedProperty(r.to,r.tot,opt)) !== true) {
|
||||||
|
errors.push(msg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (r.t === 'change') {
|
if (r.t === 'change') {
|
||||||
if (msg = isInvalidProperty(r.p,r.pt)) {
|
if ((msg = RED.utils.validateTypedProperty(r.from,r.fromt,opt)) !== true) {
|
||||||
return msg;
|
errors.push(msg)
|
||||||
}
|
}
|
||||||
if(msg = isInvalidProperty(r.from,r.fromt)) {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
if(msg = isInvalidProperty(r.to,r.tot)) {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
} else if (r.t === 'delete') {
|
|
||||||
if (msg = isInvalidProperty(r.p,r.pt)) {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
} else if (r.t === 'move') {
|
|
||||||
if (msg = isInvalidProperty(r.p,r.pt)) {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
if (msg = isInvalidProperty(r.to,r.tot)) {
|
|
||||||
return msg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (errors.length) {
|
||||||
|
return errors
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
},
|
||||||
}},
|
|
||||||
// legacy
|
// legacy
|
||||||
action: {value:""},
|
action: {value:""},
|
||||||
property: {value:""},
|
property: {value:""},
|
||||||
|
Loading…
Reference in New Issue
Block a user