Skip to content

Commit dfdfbcb

Browse files
authored
Merge branch 'master' into task/remove_casts_by_type_after_apply_expression
2 parents 297602a + 856a050 commit dfdfbcb

File tree

4 files changed

+57
-28
lines changed

4 files changed

+57
-28
lines changed

CHANGES_NEXT_RELEASE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
- Fix: Do not transform attribute value using attribute type after apply expression plugin JEXL (#1036)
2+
- Fix: check entityId is valid after apply expression in multientity plugin (#1039)
23
- Fix: check access to data in fillService facility
34
- Fix: use expressionLanguage defined in group is not defined at device level (#1027)
45
- Fix: ensure service of groups, device and commands is stored in mongo in lowercase (#1023)

lib/plugins/expressionParser.js

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ function parse(expression, context, type, callback) {
107107

108108
try {
109109
result = parser.parse(expression);
110+
logger.debug(logContext, 'parse expression "[%j]" over "[%j]" result "[%j]" ', expression, context, result);
110111
} catch (e) {
111112
error = new errors.InvalidExpression(expression);
112113

@@ -129,12 +130,12 @@ function extractContext(attributeList) {
129130
const context = {};
130131

131132
for (let i = 0; i < attributeList.length; i++) {
132-
if (attributeList[i].name) {
133-
context[attributeList[i].name] = attributeList[i].value;
134-
}
135-
if (attributeList[i].object_id) {
136-
context[attributeList[i].object_id] = attributeList[i].value;
137-
}
133+
if (attributeList[i].name) {
134+
context[attributeList[i].name] = attributeList[i].value;
135+
}
136+
if (attributeList[i].object_id) {
137+
context[attributeList[i].object_id] = attributeList[i].value;
138+
}
138139
}
139140

140141
return context;
@@ -163,7 +164,13 @@ function applyExpression(expression, context, typeInformation) {
163164
for (let i = 0; i < substitutions.length; i++) {
164165
expressionResult = expressionResult.replace(substitutions[i].original, substitutions[i].value);
165166
}
166-
logger.debug(logContext, 'applyExpression "[%j]" over "[%j]" result "[%j]" ', expression, context, expressionResult);
167+
logger.debug(
168+
logContext,
169+
'applyExpression "[%j]" over "[%j]" result "[%j]" ',
170+
expression,
171+
context,
172+
expressionResult
173+
);
167174
return expressionResult;
168175
}
169176

@@ -206,12 +213,26 @@ function expressionApplier(context, typeInformation) {
206213
}
207214

208215
function contextAvailable(expression, context) {
209-
const variables = expression.match(/@[a-zA-Z0-9]+/g).map(function (item) {
210-
return item.substr(1);
211-
});
212-
const keys = Object.keys(context);
213-
214-
return _.difference(variables, keys).length === 0;
216+
let error;
217+
try {
218+
const variables = expression.match(/@[a-zA-Z0-9]+/g).map(function (item) {
219+
return item.substr(1);
220+
});
221+
const keys = Object.keys(context);
222+
let validContext = _.difference(variables, keys).length === 0;
223+
if (!validContext) {
224+
logger.warn(
225+
logContext,
226+
'For expression "[%s]" context "[%j]" does not have element to match',
227+
expression,
228+
context
229+
);
230+
}
231+
return validContext;
232+
} catch (e) {
233+
error = new errors.InvalidExpression(expression);
234+
throw error;
235+
}
215236
}
216237

217238
function processExpressionAttributes(typeInformation, list, context) {

lib/plugins/multiEntity.js

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,19 @@ const utils = require('./pluginUtils');
4141
/* eslint-disable-next-line no-unused-vars */
4242
const aliasPlugin = require('./attributeAlias');
4343

44-
4544
function checkJexl(typeInformation) {
4645
if (
4746
config.getConfig().defaultExpressionLanguage === 'jexl' &&
48-
typeInformation.expressionLanguage &&
49-
typeInformation.expressionLanguage !== 'legacy'
47+
typeInformation.expressionLanguage &&
48+
typeInformation.expressionLanguage !== 'legacy'
5049
) {
5150
return true;
5251
} else if (config.getConfig().defaultExpressionLanguage === 'jexl' && !typeInformation.expressionLanguage) {
5352
return true;
5453
} else if (
5554
config.getConfig().defaultExpressionLanguage === 'legacy' &&
56-
typeInformation.expressionLanguage &&
57-
typeInformation.expressionLanguage === 'jexl'
55+
typeInformation.expressionLanguage &&
56+
typeInformation.expressionLanguage === 'jexl'
5857
) {
5958
return true;
6059
}
@@ -65,6 +64,11 @@ function hasEntityName(item) {
6564
return item.entity_name;
6665
}
6766

67+
function ensureEntityId(entityName, originalEntityName) {
68+
// ensure no return null, 0, false, NaN and other invalids entityIDs
69+
return entityName ? entityName : originalEntityName;
70+
}
71+
6872
/**
6973
* Return a list of all the attributes that don't have a multientity option. It considers NGSIv1.
7074
*
@@ -87,20 +91,23 @@ function filterOutMultientitiesNgsi1(originalAttrs, meAttributes) {
8791
*/
8892
function filterOutMultientitiesNgsi2(originalAttrs, meAttributes) {
8993
const result = {};
90-
const meNamesList = _.pluck( meAttributes, 'name');
91-
const meObjectsList = _.pluck( meAttributes, 'object_id');
94+
const meNamesList = _.pluck(meAttributes, 'name');
95+
const meObjectsList = _.pluck(meAttributes, 'object_id');
9296
let toBeFilteredByObj = [];
9397

9498
for (const att in originalAttrs) {
9599
if (originalAttrs.hasOwnProperty(att)) {
96100
if (!_.contains(meNamesList, att)) {
97101
result[att] = originalAttrs[att];
98102
}
99-
if (originalAttrs[att].hasOwnProperty('multi')){
100-
let cleanAttributes = _.union([_.clone(originalAttrs[att])], originalAttrs[att].multi);
101-
delete cleanAttributes[0].multi;
102-
cleanAttributes = _.map(cleanAttributes, function(val){ val['name'] = att; return val; });
103-
toBeFilteredByObj = _.union(toBeFilteredByObj, cleanAttributes);
103+
if (originalAttrs[att].hasOwnProperty('multi')) {
104+
let cleanAttributes = _.union([_.clone(originalAttrs[att])], originalAttrs[att].multi);
105+
delete cleanAttributes[0].multi;
106+
cleanAttributes = _.map(cleanAttributes, function (val) {
107+
val['name'] = att;
108+
return val;
109+
});
110+
toBeFilteredByObj = _.union(toBeFilteredByObj, cleanAttributes);
104111
}
105112
}
106113
}
@@ -157,7 +164,7 @@ function generateNewCEsNgsi1(entity, newEntities, entityTypes, typeInformation,
157164
result.push({
158165
type: entityTypes[newEntities[i]],
159166
isPattern: 'false',
160-
id: entityName,
167+
id: ensureEntityId(entityName, newEntities[i]),
161168
attributes: newEntityAttributes
162169
});
163170
}
@@ -231,7 +238,7 @@ function generateNewCEsNgsi2(entity, newEntities, entityTypes, typeInformation,
231238
entityName = parser.applyExpression(newEntities[i], ctx, typeInformation);
232239

233240
newEntityAttributes.type = entityTypes[newEntities[i]];
234-
newEntityAttributes.id = entityName;
241+
newEntityAttributes.id = ensureEntityId(entityName, newEntities[i]);
235242

236243
result.push(newEntityAttributes);
237244
}

lib/services/northBound/contextServer-NGSI-v2.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ function handleUpdateNgsi2(req, res, next) {
204204
[apply(async.map, req.body.entities, apply(generateUpdateActionsNgsi2, req)), reduceActions, async.series],
205205
function (error, result) {
206206
if (error) {
207-
logger.debug(context, 'There was an error handling the update action: %s.', error);
207+
logger.debug(context, 'There was an error handling the update action: %j.', error);
208208

209209
next(error);
210210
} else {

0 commit comments

Comments
 (0)