1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Handle context.get with multiple levels of unknown key

Fixes #1883
This commit is contained in:
Nick O'Leary 2018-09-09 23:47:31 +01:00
parent 0f4d46671f
commit fc0cf1ff51
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
5 changed files with 50 additions and 20 deletions

View File

@ -230,14 +230,31 @@ LocalFileSystem.prototype.get = function(scope, key, callback) {
} }
var storagePath = getStoragePath(this.storageBaseDir ,scope); var storagePath = getStoragePath(this.storageBaseDir ,scope);
loadFile(storagePath + ".json").then(function(data){ loadFile(storagePath + ".json").then(function(data){
var value;
if(data){ if(data){
data = JSON.parse(data); data = JSON.parse(data);
if (!Array.isArray(key)) { if (!Array.isArray(key)) {
callback(null, util.getObjectProperty(data,key)); try {
value = util.getObjectProperty(data,key);
} catch(err) {
if (err.code === "INVALID_EXPR") {
throw err;
}
value = undefined;
}
callback(null, value);
} else { } else {
var results = [undefined]; var results = [undefined];
for (var i=0;i<key.length;i++) { for (var i=0;i<key.length;i++) {
results.push(util.getObjectProperty(data,key[i])) try {
value = util.getObjectProperty(data,key[i]);
} catch(err) {
if (err.code === "INVALID_EXPR") {
throw err;
}
value = undefined;
}
results.push(value)
} }
callback.apply(null,results); callback.apply(null,results);
} }

View File

@ -32,7 +32,14 @@ Memory.prototype._getOne = function(scope, key) {
var value; var value;
var error; var error;
if(this.data[scope]){ if(this.data[scope]){
try {
value = util.getObjectProperty(this.data[scope], key); value = util.getObjectProperty(this.data[scope], key);
} catch(err) {
if (err.code === "INVALID_EXPR") {
throw err;
}
value = undefined;
}
} }
return value; return value;
} }

View File

@ -130,13 +130,19 @@ function compareObjects(obj1,obj2) {
return true; return true;
} }
function createError(code, message) {
var e = new Error(message);
e.code = code;
return e;
}
function normalisePropertyExpression(str) { function normalisePropertyExpression(str) {
// This must be kept in sync with validatePropertyExpression // This must be kept in sync with validatePropertyExpression
// in editor/js/ui/utils.js // in editor/js/ui/utils.js
var length = str.length; var length = str.length;
if (length === 0) { if (length === 0) {
throw new Error("Invalid property expression: zero-length"); throw createError("INVALID_EXPR","Invalid property expression: zero-length");
} }
var parts = []; var parts = [];
var start = 0; var start = 0;
@ -149,14 +155,14 @@ function normalisePropertyExpression(str) {
if (!inString) { if (!inString) {
if (c === "'" || c === '"') { if (c === "'" || c === '"') {
if (i != start) { if (i != start) {
throw new Error("Invalid property expression: unexpected "+c+" at position "+i); throw createError("INVALID_EXPR","Invalid property expression: unexpected "+c+" at position "+i);
} }
inString = true; inString = true;
quoteChar = c; quoteChar = c;
start = i+1; start = i+1;
} else if (c === '.') { } else if (c === '.') {
if (i===0) { if (i===0) {
throw new Error("Invalid property expression: unexpected . at position 0"); throw createError("INVALID_EXPR","Invalid property expression: unexpected . at position 0");
} }
if (start != i) { if (start != i) {
v = str.substring(start,i); v = str.substring(start,i);
@ -167,57 +173,57 @@ function normalisePropertyExpression(str) {
} }
} }
if (i===length-1) { if (i===length-1) {
throw new Error("Invalid property expression: unterminated expression"); throw createError("INVALID_EXPR","Invalid property expression: unterminated expression");
} }
// Next char is first char of an identifier: a-z 0-9 $ _ // Next char is first char of an identifier: a-z 0-9 $ _
if (!/[a-z0-9\$\_]/i.test(str[i+1])) { if (!/[a-z0-9\$\_]/i.test(str[i+1])) {
throw new Error("Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1)); throw createError("INVALID_EXPR","Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
} }
start = i+1; start = i+1;
} else if (c === '[') { } else if (c === '[') {
if (i === 0) { if (i === 0) {
throw new Error("Invalid property expression: unexpected "+c+" at position "+i); throw createError("INVALID_EXPR","Invalid property expression: unexpected "+c+" at position "+i);
} }
if (start != i) { if (start != i) {
parts.push(str.substring(start,i)); parts.push(str.substring(start,i));
} }
if (i===length-1) { if (i===length-1) {
throw new Error("Invalid property expression: unterminated expression"); throw createError("INVALID_EXPR","Invalid property expression: unterminated expression");
} }
// Next char is either a quote or a number // Next char is either a quote or a number
if (!/["'\d]/.test(str[i+1])) { if (!/["'\d]/.test(str[i+1])) {
throw new Error("Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1)); throw createError("INVALID_EXPR","Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
} }
start = i+1; start = i+1;
inBox = true; inBox = true;
} else if (c === ']') { } else if (c === ']') {
if (!inBox) { if (!inBox) {
throw new Error("Invalid property expression: unexpected "+c+" at position "+i); throw createError("INVALID_EXPR","Invalid property expression: unexpected "+c+" at position "+i);
} }
if (start != i) { if (start != i) {
v = str.substring(start,i); v = str.substring(start,i);
if (/^\d+$/.test(v)) { if (/^\d+$/.test(v)) {
parts.push(parseInt(v)); parts.push(parseInt(v));
} else { } else {
throw new Error("Invalid property expression: unexpected array expression at position "+start); throw createError("INVALID_EXPR","Invalid property expression: unexpected array expression at position "+start);
} }
} }
start = i+1; start = i+1;
inBox = false; inBox = false;
} else if (c === ' ') { } else if (c === ' ') {
throw new Error("Invalid property expression: unexpected ' ' at position "+i); throw createError("INVALID_EXPR","Invalid property expression: unexpected ' ' at position "+i);
} }
} else { } else {
if (c === quoteChar) { if (c === quoteChar) {
if (i-start === 0) { if (i-start === 0) {
throw new Error("Invalid property expression: zero-length string at position "+start); throw createError("INVALID_EXPR","Invalid property expression: zero-length string at position "+start);
} }
parts.push(str.substring(start,i)); parts.push(str.substring(start,i));
// If inBox, next char must be a ]. Otherwise it may be [ or . // If inBox, next char must be a ]. Otherwise it may be [ or .
if (inBox && !/\]/.test(str[i+1])) { if (inBox && !/\]/.test(str[i+1])) {
throw new Error("Invalid property expression: unexpected array expression at position "+start); throw createError("INVALID_EXPR","Invalid property expression: unexpected array expression at position "+start);
} else if (!inBox && i+1!==length && !/[\[\.]/.test(str[i+1])) { } else if (!inBox && i+1!==length && !/[\[\.]/.test(str[i+1])) {
throw new Error("Invalid property expression: unexpected "+str[i+1]+" expression at position "+(i+1)); throw createError("INVALID_EXPR","Invalid property expression: unexpected "+str[i+1]+" expression at position "+(i+1));
} }
start = i+1; start = i+1;
inString = false; inString = false;
@ -226,7 +232,7 @@ function normalisePropertyExpression(str) {
} }
if (inBox || inString) { if (inBox || inString) {
throw new Error("Invalid property expression: unterminated expression"); throw new createError("INVALID_EXPR","Invalid property expression: unterminated expression");
} }
if (start < length) { if (start < length) {
parts.push(str.substring(start)); parts.push(str.substring(start));

View File

@ -672,7 +672,7 @@ describe('localfilesystem',function() {
it('should enumerate context keys in the cache',function() { it('should enumerate context keys in the cache',function() {
var globalData = {foo:"bar"}; var globalData = {foo:"bar"};
fs.outputFile(path.join(resourcesDir,defaultContextBase,"global","global.json"), JSON.stringify(globalData,null,4), "utf8").then(function(){ return fs.outputFile(path.join(resourcesDir,defaultContextBase,"global","global.json"), JSON.stringify(globalData,null,4), "utf8").then(function(){
context = LocalFileSystem({dir: resourcesDir, cache: true, flushInterval: 2}); context = LocalFileSystem({dir: resourcesDir, cache: true, flushInterval: 2});
return context.open() return context.open()
}).then(function(){ }).then(function(){

View File

@ -96,7 +96,7 @@ describe('memory',function() {
context.set("nodeX","three","test3"); context.set("nodeX","three","test3");
context.set("nodeX","four","test4"); context.set("nodeX","four","test4");
var values = context.get("nodeX",["one","unknown"]); var values = context.get("nodeX",["one","unknown.with.multiple.levels"]);
values.should.eql(["test1",undefined]) values.should.eql(["test1",undefined])
}) })
it('should throw error if bad key included in multiple keys', function() { it('should throw error if bad key included in multiple keys', function() {