• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

telefonicaid / fiware-pep-steelskin / 8506442634

01 Apr 2024 09:32AM UTC coverage: 82.984%. Remained the same
8506442634

push

github

web-flow
Merge pull request #535 from telefonicaid/dependabot/npm_and_yarn/express-4.19.2

Bump express from 4.18.1 to 4.19.2

282 of 368 branches covered (76.63%)

Branch coverage included in aggregate %.

786 of 919 relevant lines covered (85.53%)

54.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.9
/lib/plugins/orionPlugin.js
1
/*
2
 * Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U
3
 *
4
 * This file is part of fiware-pep-steelskin
5
 *
6
 * fiware-pep-steelskin is free software: you can redistribute it and/or
7
 * modify it under the terms of the GNU Affero General Public License as
8
 * published by the Free Software Foundation, either version 3 of the License,
9
 * or (at your option) any later version.
10
 *
11
 * fiware-pep-steelskin is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 * See the GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public
17
 * License along with fiware-pep-steelskin.
18
 * If not, seehttp://www.gnu.org/licenses/.
19
 *
20
 * For those usages not covered by the GNU Affero General Public License
21
 * please contact with::[iot_support@tid.es]
22
 */
23

24
'use strict';
25

26
var sax = require('sax'),
1✔
27
    errors = require('../errors'),
28
    identificationTable = require('./orionUrls');
29

30

31
/**
32
 * Translates the updateAction value to the appropriate action name for the Access Control.
33
 *
34
 * @param {Object} logger                Instance of logops.Logger
35
 * @param {String} originalAction        String with the action name.
36
 * @return {String}                      The string representation of the action name for the Access Control.
37
 */
38
function translateAction(logger, originalAction) {
1✔
39
    var action;
97✔
40

41
    switch (originalAction.toLowerCase()) {
97!
42
        case 'append':
43
            action = 'create';
85✔
44
            break;
85✔
45

46
        case 'append_strict':  // NGSIv1
47
            action = 'create';
×
48
            break;
×
49
            
50
        case 'appendstrict': // NGSIv2
51
            action = 'create';
2✔
52
            break;
2✔
53

54
        case 'update':
55
            action = 'update';
3✔
56
            break;
3✔
57

58
        case 'delete':
59
            action = 'delete';
4✔
60
            break;
4✔
61

62
        case 'replace':
63
            action = 'update';
2✔
64
            break;
2✔
65

66
        default:
67
            action = null;
1✔
68
    }
69

70
    logger.debug('Discovered action was: %s', action);
97✔
71

72
    return action;
97✔
73
}
74

75
/**
76
 * Extract the action from an XML body.
77
 *
78
 * @param {Object} logger        Instance of logops.Logger
79
 * @param {String} body          Raw string payload.
80
 */
81
function inspectBodyXML(logger, body, callback) {
1✔
82
    var parser = sax.parser(true),
2✔
83
        readingAction = false,
84
        errorRaised = false,
85
        action;
86

87
    parser.onerror = function(e) {
2✔
88
        var error = new errors.WrongXmlPayload();
×
89

90
        logger.error('[ORION-PLUGIN-006] Wrong XML Payload. Parsing error: %s', e.message);
×
91

92
        if (!errorRaised) {
×
93
            errorRaised = true;
×
94
            error.moreInfo = e;
×
95
            callback(error);
×
96
        }
97
    };
98

99
    parser.ontext = function(t) {
2✔
100
        if (readingAction) {
60✔
101
            if (!action) {
4✔
102
                action = t;
2✔
103
            } else {
104
                action = action + t;
2✔
105
            }
106
        }
107
    };
108

109
    parser.onopentag = function(node) {
2✔
110
        if (node.name === 'updateAction') {
30✔
111
            readingAction = true;
2✔
112
        } else {
113
            readingAction = false;
28✔
114
        }
115
    };
116

117
    parser.onend = function() {
2✔
118
        if (action) {
2!
119
            var translatedAction = translateAction(logger, action.trim());
2✔
120

121
            if (translatedAction) {
2!
122
                callback(null, translatedAction);
2✔
123
            } else {
124
                callback(new errors.WrongXmlPayload());
×
125
            }
126

127
        } else {
128
            logger.error('[ORION-PLUGIN-001] Wrong XML Payload. Action not found');
×
129

130
            callback(new errors.WrongXmlPayload());
×
131
        }
132
    };
133

134
    try {
2✔
135
        parser.write(body).close();
2✔
136
    } catch (e) {
137
        var error = new errors.WrongXmlPayload();
×
138

139
        logger.error('[ORION-PLUGIN-002] Wrong XML Payload. Parsing error: %s', e.message);
×
140
        callback(error);
×
141
    }
142
}
143

144
/**
145
 * Extract the action from a JSON body.
146
 *
147
 * @param {Object} logger        Instance of logops.Logger
148
 * @param {Object} body          Javascript Object with the parsed payload.
149
 * @param {Object} field         Field that will be used to extract the type.
150
 */
151
function inspectBodyJSON(logger, body, field, callback) {
1✔
152
    if (body && body[field]) {
96✔
153
        var translatedAction = translateAction(logger, body[field]);
95✔
154

155
        if (translatedAction) {
95✔
156
            callback(null, translatedAction);
94✔
157
        } else {
158
            callback(new errors.WrongJsonPayload());
1✔
159
        }
160
    } else {
161
        logger.error('[ORION-PLUGIN-003] Wrong JSON Payload: updateAction element not found');
1✔
162

163
        callback(new errors.WrongJsonPayload());
1✔
164
    }
165
}
166

167
/**
168
 * Determines what kind of body to parse to calculate the action, and invoke the appropriate function.
169
 *
170
 * @param {Object} req           Incoming request.
171
 * @param {Object} res           Outgoing response.
172
 */
173
function inspectBodyV1(req, res, callback) {
1✔
174
    const logger = req.logger;
89✔
175
    var actionHandler = function actionHandler(error, action) {
89✔
176
        req.action = action;
89✔
177
        callback(error, req, res);
89✔
178
    };
179

180
    if (req.is('*/json')) {
89✔
181
        logger.debug('Inspecting JSON body to discover action: \n%j\n\n', req.body);
86✔
182
        inspectBodyJSON(logger, req.body, 'updateAction', actionHandler);
86✔
183
    } else if (req.is('*/xml')) {
3✔
184
        logger.debug('Inspecting XML body to discover action: \n%s\n\n', req.rawBody);
2✔
185
        inspectBodyXML(logger, req.rawBody, actionHandler);
2✔
186
    } else {
187
        // TODO: raise error if the type is not recognized.
188
        logger.error('[ORION-PLUGIN-004] Unknown content type: %s', req.headers['content-type']);
1✔
189

190
        actionHandler(new errors.UnexpectedContentType(req.headers['content-type']));
1✔
191
    }
192
}
193

194
function inspectBodyV2(req, res, callback) {
1✔
195
    const logger = req.logger;
10✔
196
    var actionHandler = function actionHandler(error, action) {
10✔
197
        req.action = action;
10✔
198
        callback(error, req, res);
10✔
199
    };
200

201
    if (req.is('*/json')) {
10!
202
        logger.debug('Inspecting JSON body to discover action: \n%j\n\n', req.body);
10✔
203
        inspectBodyJSON(logger, req.body, 'actionType', actionHandler);
10✔
204

205
    } else {
206
        // TODO: raise error if the type is not recognized.
207
        logger.error('[ORION-PLUGIN-004] Unknown content type: %s', req.headers['content-type']);
×
208

209
        actionHandler(new errors.UnexpectedContentType(req.headers['content-type']));
×
210
    }
211
}
212

213
/**
214
 * Determines what is the requested action based on the request information, knowing that it is a convenience operation.
215
 *
216
 * @param {Object} req           Incoming request.
217
 * @param {Object} res           Outgoing response.
218
 */
219
function inspectUrl(req, res, callback) {
1✔
220
    const logger = req.logger;
34✔
221
    var match = false;
34✔
222

223
    logger.debug('Extracting action from the URL "%s"', req.url);
34✔
224

225
    for (var i = 0; i < identificationTable.length; i++) {
34✔
226
        match = false;
438✔
227

228
        if (req.method === identificationTable[i][0] &&
438✔
229
            req.path.toLowerCase().match(identificationTable[i][1])) {
230

231
            match = true;
34✔
232

233
            if (identificationTable[i].length >= 4 && req.query) {
34✔
234
                for (var j in identificationTable[i][3]) {
3✔
235
                    if (!req.query[j] ||
3✔
236
                        identificationTable[i][3].hasOwnProperty(j) &&
237
                        req.query[j].split(',').indexOf(identificationTable[i][3][j]) < 0) {
238
                        match = false;
1✔
239
                    }
240
                }
241
            }
242

243
            if (match) {
34✔
244
                req.action = identificationTable[i][2];
33✔
245
                callback(null, req, res);
33✔
246
                return;
33✔
247
            }
248
        }
249
    }
250

251
    logger.error('[ORION-PLUGIN-005] Action not found');
1✔
252
    callback(new errors.ActionNotFound(), req, res);
1✔
253
}
254

255
/**
256
 * Middleware to calculate what Context Broker action has been received based on the path and the request payload.
257
 *
258
 * @param {Object} req           Incoming request.
259
 * @param {Object} res           Outgoing response.
260
 */
261
function extractCBAction(req, res, callback) {
1✔
262
    if (req.path.toLowerCase().match(/\/(ngsi10|v1)\/updatecontext$/)) {
133✔
263
        inspectBodyV1(req, res, callback);
89✔
264
    } else if (req.path.toLowerCase().match(/\/v2\/op\/update$/)) {
44✔
265
        inspectBodyV2(req, res, callback);
10✔
266
    } else {
267
        inspectUrl(req, res, callback);
34✔
268
    }
269
}
270

271
exports.extractCBAction = extractCBAction;
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc