@sap/xsodata 8.2.1 → 8.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/index.js +2 -2
- package/lib/configuration.js +1 -1
- package/lib/db/connect.js +1 -1
- package/lib/db/dbSegment.js +68 -123
- package/lib/db/dbVersionChecks.js +2 -8
- package/lib/handlerConfiguration.js +2 -2
- package/lib/http/conditionalHttpHandler.js +27 -34
- package/lib/http/simpleHttpRequest.js +14 -18
- package/lib/http/simpleHttpResponse.js +9 -6
- package/lib/http/uriParser.js +9 -9
- package/lib/http/validator/httpRequestValidator.js +9 -9
- package/lib/model/annotationFactory.js +11 -11
- package/lib/model/association.js +3 -3
- package/lib/model/entityType.js +33 -67
- package/lib/model/metadataReader.js +31 -52
- package/lib/model/model.js +0 -1
- package/lib/model/validator/xsoDataConcurrencyTokenValidator.js +6 -6
- package/lib/model/xsodataReader.js +36 -28
- package/lib/processor/authorizationProcessor.js +22 -33
- package/lib/processor/batchProcessor.js +22 -33
- package/lib/processor/errorProcessor.js +4 -4
- package/lib/processor/exitProcessor.js +19 -19
- package/lib/processor/processor.js +9 -9
- package/lib/processor/resourceProcessor.js +31 -61
- package/lib/processor/resourceProcessorDelete.js +16 -16
- package/lib/processor/resourceProcessorDeleteLinks.js +25 -25
- package/lib/processor/resourceProcessorGet.js +5 -5
- package/lib/processor/resourceProcessorPost.js +43 -45
- package/lib/processor/resourceProcessorPut.js +35 -39
- package/lib/processor/resourceProcessorPutPostLinks.js +38 -39
- package/lib/security/securityContext.js +5 -5
- package/lib/serializer/atomSerializer.js +54 -55
- package/lib/serializer/atomXmlToJsonSerializer.js +32 -44
- package/lib/serializer/content.js +5 -5
- package/lib/serializer/json.js +31 -33
- package/lib/serializer/jsonSerializer.js +4 -4
- package/lib/serializer/metadataSerializer.js +32 -35
- package/lib/serializer/serializer.js +29 -43
- package/lib/serializer/serviceSerializer.js +19 -24
- package/lib/serializer/value.js +1 -2
- package/lib/serializer/xmlToJsonSerializer.js +18 -18
- package/lib/sql/createDeleteLinksStatements.js +10 -10
- package/lib/sql/createDeleteStatements.js +12 -12
- package/lib/sql/createGetStatements.js +49 -107
- package/lib/sql/createLinksSQLStatements_1_n.js +27 -27
- package/lib/sql/createPutPostLinksStatements.js +9 -9
- package/lib/sql/createPutStatements.js +0 -1
- package/lib/sql/dataCollectorDelete.js +9 -9
- package/lib/sql/dataCollectorDeleteLinks.js +3 -3
- package/lib/sql/dataCollectorGet.js +9 -17
- package/lib/sql/dataCollectorLinks.js +23 -27
- package/lib/sql/dataCollectorPost.js +20 -20
- package/lib/sql/dataCollectorPut.js +36 -36
- package/lib/sql/dataCollectorPutPostLinks.js +3 -3
- package/lib/sql/sqlStatement.js +81 -128
- package/lib/sql/sqlTools.js +3 -7
- package/lib/sql/statementProcessor.js +7 -14
- package/lib/uri/applyChecks.js +3 -3
- package/lib/uri/checks/checkAllowedMethod.js +3 -3
- package/lib/uri/checks/checkAllowedMethodForBatch.js +2 -2
- package/lib/uri/checks/checkAllowedMethodsForResourcePath.js +3 -3
- package/lib/uri/checks/checkFilterOnAggregatedColumn.js +5 -5
- package/lib/uri/checks/checkFilterOrderByOnGenKeyColumn.js +6 -6
- package/lib/uri/checks/checkGenKeyRestrictions.js +2 -2
- package/lib/uri/checks/checkModificationForbidden.js +3 -3
- package/lib/uri/checks/checkPostPutDeleteChecks.js +5 -5
- package/lib/uri/checks/checkSystemQueryOptions.js +10 -10
- package/lib/uri/checks.js +15 -15
- package/lib/uri/expandSelectTreeBuilder.js +12 -16
- package/lib/uri/oDataUriParser.js +20 -20
- package/lib/uri/queryParameterParser.js +25 -33
- package/lib/uri/resourcePathParser.js +47 -62
- package/lib/uri/uriType.js +4 -4
- package/lib/utils/associations.js +4 -4
- package/lib/utils/batch/batchExecutor.js +49 -51
- package/lib/utils/batch/batchObjects.js +10 -10
- package/lib/utils/batch/batchParser.js +27 -28
- package/lib/utils/batch/batchWriter.js +1 -1
- package/lib/utils/checkContentType.js +34 -39
- package/lib/utils/debugView.js +35 -36
- package/lib/utils/errors/applicationError.js +2 -2
- package/lib/utils/errors/debugInfo.js +2 -2
- package/lib/utils/errors/http/badRequest.js +2 -2
- package/lib/utils/errors/http/forbidden.js +2 -2
- package/lib/utils/errors/http/methodNotAllowed.js +2 -2
- package/lib/utils/errors/http/notAcceptable.js +2 -2
- package/lib/utils/errors/http/notFound.js +2 -2
- package/lib/utils/errors/http/notImplemented.js +2 -2
- package/lib/utils/errors/http/notModified.js +2 -2
- package/lib/utils/errors/http/notSupported.js +2 -2
- package/lib/utils/errors/http/preconditionFailed.js +2 -2
- package/lib/utils/errors/http/preconditionRequired.js +2 -2
- package/lib/utils/errors/http/unauthorized.js +2 -2
- package/lib/utils/errors/http/unsupportedMediaType.js +2 -2
- package/lib/utils/errors/httpError.js +2 -2
- package/lib/utils/errors/internalError.js +2 -2
- package/lib/utils/errors/modelFileError.js +2 -2
- package/lib/utils/errors/sqlError.js +2 -2
- package/lib/utils/errors/testError.js +2 -2
- package/lib/utils/errors/typeError.js +5 -5
- package/lib/utils/errors/xsODataError.js +1 -1
- package/lib/utils/logger.js +21 -32
- package/lib/utils/measurement.js +14 -13
- package/lib/utils/requestContext.js +2 -2
- package/lib/utils/stateMaschine.js +6 -6
- package/lib/utils/tableCleanup.js +3 -3
- package/lib/utils/typeConverter.js +21 -21
- package/lib/utils/typeConverters/converterTools.js +25 -331
- package/lib/utils/typeConverters/dbToJson.js +3 -3
- package/lib/utils/typeConverters/dbToUri.js +7 -7
- package/lib/utils/typeConverters/dbToXml.js +9 -9
- package/lib/utils/typeConverters/jsonToDb.js +20 -27
- package/lib/utils/typeConverters/uriToDb.js +45 -92
- package/lib/utils/typeConverters/xmlValueToJson.js +9 -13
- package/lib/utils/typedObjects.js +11 -79
- package/lib/utils/utils.js +20 -23
- package/lib/xsodata.js +37 -47
- package/package.json +9 -11
- package/.npmignore +0 -40
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
//Include
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const peg_parser = require('../parsers/peg_xsodata_parser');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const ModelFileError = require('./../utils/errors/modelFileError');
|
|
14
|
+
const Rwlock = require('rwlock');
|
|
15
|
+
const locks = new Rwlock();
|
|
16
|
+
const model = require('./model');
|
|
17
|
+
const async = require('async');
|
|
18
|
+
const utils = require('../utils/utils');
|
|
19
|
+
const InternalError = require('../utils/errors/internalError');
|
|
20
20
|
|
|
21
21
|
//Testing API
|
|
22
22
|
exports.parseContent = parseContent;
|
|
@@ -29,7 +29,7 @@ exports.loadXsodataConfiguration = loadXsodataConfiguration;
|
|
|
29
29
|
//Code
|
|
30
30
|
function parseContent(content, done) {
|
|
31
31
|
try {
|
|
32
|
-
|
|
32
|
+
const data = peg_parser.parse(content);
|
|
33
33
|
done(null, data);
|
|
34
34
|
} catch (ex) {
|
|
35
35
|
return done(ex);
|
|
@@ -87,7 +87,7 @@ function loadXsodataConfiguration(context, asyncDone) {
|
|
|
87
87
|
|
|
88
88
|
], function (endErr, context) {
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
const id = getConfigurationId(context);
|
|
91
91
|
context.logger.info('model', 'using model id: ' + id);
|
|
92
92
|
|
|
93
93
|
return asyncDone(endErr, context);
|
|
@@ -105,14 +105,14 @@ function loadXsodataConfiguration(context, asyncDone) {
|
|
|
105
105
|
* @since v0.2.0-beta.3
|
|
106
106
|
*/
|
|
107
107
|
function readXsodataConfigFromCache(context, asyncDone) {
|
|
108
|
-
|
|
108
|
+
const locale = context.locale;
|
|
109
109
|
context.logger.silly('model', 'readXsodataConfigFromCache');
|
|
110
110
|
|
|
111
111
|
if (!context.modelData[locale]) {
|
|
112
112
|
context.modelData[locale] = {};
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
const id = getConfigurationId(context);
|
|
116
116
|
context.gModel = context.modelData[locale][id];
|
|
117
117
|
|
|
118
118
|
return asyncDone(null, context);
|
|
@@ -163,10 +163,10 @@ function extendXsodataConfig(context, asyncDone) {
|
|
|
163
163
|
*/
|
|
164
164
|
function checkSchema(context, asyncDone) {
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
const parsedXsodata = context._initialParsedXsodata;
|
|
167
|
+
let entityTypes;
|
|
168
|
+
let entityType;
|
|
169
|
+
let key;
|
|
170
170
|
|
|
171
171
|
|
|
172
172
|
context.logger.silly('model', 'checkSchema');
|
|
@@ -199,6 +199,18 @@ function checkSchema(context, asyncDone) {
|
|
|
199
199
|
return asyncDone(null, context);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
/**
|
|
203
|
+
* Check if the parsed xsodata configuration is valid
|
|
204
|
+
*
|
|
205
|
+
* @param parsedXsodata {Object} Parsed xsodata configuration
|
|
206
|
+
* @return {boolean} true if valid, false otherwise
|
|
207
|
+
* @since v0.2.0-beta.3
|
|
208
|
+
*/
|
|
209
|
+
function isParsedXsodataValid(parsedXsodata) {
|
|
210
|
+
return parsedXsodata && parsedXsodata.service &&
|
|
211
|
+
parsedXsodata.service.entityTypes && parsedXsodata.service.associations;
|
|
212
|
+
}
|
|
213
|
+
|
|
202
214
|
/**
|
|
203
215
|
* Extending the configuration model by adding navigates --> from principal|dependent
|
|
204
216
|
*
|
|
@@ -218,7 +230,7 @@ function checkSchema(context, asyncDone) {
|
|
|
218
230
|
*/
|
|
219
231
|
function extendNavigatesFromProperty(context, asyncDone) {
|
|
220
232
|
|
|
221
|
-
|
|
233
|
+
let parsedXsodata = context._initialParsedXsodata,
|
|
222
234
|
entityTypes,
|
|
223
235
|
associations,
|
|
224
236
|
key,
|
|
@@ -231,11 +243,7 @@ function extendNavigatesFromProperty(context, asyncDone) {
|
|
|
231
243
|
|
|
232
244
|
context.logger.silly('model', 'extendNavigatesFromProperty');
|
|
233
245
|
|
|
234
|
-
if (!parsedXsodata
|
|
235
|
-
return asyncDone(null, context);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (!parsedXsodata.service.entityTypes || !parsedXsodata.service.associations) {
|
|
246
|
+
if (!isParsedXsodataValid(parsedXsodata)) {
|
|
239
247
|
return asyncDone(null, context);
|
|
240
248
|
}
|
|
241
249
|
|
|
@@ -342,14 +350,14 @@ function validateModel(context, asyncDone) {
|
|
|
342
350
|
* @since v0.2.0-beta.3
|
|
343
351
|
*/
|
|
344
352
|
function addConfigToCache(context, asyncDone) {
|
|
345
|
-
|
|
353
|
+
const locale = context.locale;
|
|
346
354
|
context.logger.silly('model', 'addConfigToCache');
|
|
347
355
|
|
|
348
356
|
if (!context.gModel) {
|
|
349
357
|
return asyncDone(new ModelFileError("Xsodata configuration model does not exist. Can not add to internal cache.", context), context);
|
|
350
358
|
}
|
|
351
359
|
|
|
352
|
-
|
|
360
|
+
const id = getConfigurationId(context);
|
|
353
361
|
context.modelData[locale][id] = context.gModel;
|
|
354
362
|
|
|
355
363
|
return asyncDone(null, context);
|
|
@@ -372,13 +380,13 @@ function readXsodataConfigFromFile(context, asyncDone) {
|
|
|
372
380
|
return asyncDone(null, context);
|
|
373
381
|
}
|
|
374
382
|
|
|
375
|
-
|
|
383
|
+
const id = getConfigurationId(context);
|
|
376
384
|
|
|
377
385
|
context.logger.silly('model', 'readXsodataConfigFromFile');
|
|
378
386
|
context.logger.silly('model', 'serviceConfiguration : ' + context.serviceConfiguration);
|
|
379
387
|
context.logger.silly('model', 'xsoFile: ' + context.uriTree.xsoFile);
|
|
380
388
|
|
|
381
|
-
|
|
389
|
+
let fullName;
|
|
382
390
|
if (context.uriTree.xsoFile) {
|
|
383
391
|
fullName = path.join(context.serviceConfiguration, context.uriTree.xsoFile);
|
|
384
392
|
if (fullName.indexOf(context.serviceConfiguration) !== 0) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
const async = require('async');
|
|
4
|
+
const ForbiddenError = require('../utils/errors/http/forbidden.js');
|
|
5
|
+
const utils = require('../utils/utils.js');
|
|
6
|
+
const securityContext = require("../security/securityContext");
|
|
7
|
+
const uriTypes = require("../uri/uriType");
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -19,12 +19,12 @@ var uriTypes = require("../uri/uriType");
|
|
|
19
19
|
*/
|
|
20
20
|
exports.processAuthorization = function (context, asyncDone) {
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
let strategies;
|
|
23
|
+
let builtStrategies;
|
|
24
|
+
let hasScopes;
|
|
25
|
+
let token;
|
|
26
|
+
const contextUriType = context.uriTree.uriType;
|
|
27
|
+
const innerContext = {
|
|
28
28
|
parentContext: context,
|
|
29
29
|
isAuthorized: false,
|
|
30
30
|
scopes: []
|
|
@@ -120,11 +120,7 @@ exports.contextHasScopes = function (context) {
|
|
|
120
120
|
context.logger.debug("authorizationProcessor", "context.getScopes(): " +
|
|
121
121
|
JSON.stringify(context.getScopes()));
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
return true;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return false;
|
|
123
|
+
return context.getScopes() ? true : false;
|
|
128
124
|
};
|
|
129
125
|
|
|
130
126
|
|
|
@@ -139,7 +135,7 @@ exports.contextHasScopes = function (context) {
|
|
|
139
135
|
*/
|
|
140
136
|
exports.buildStrategies = function (token, context) {
|
|
141
137
|
|
|
142
|
-
|
|
138
|
+
let strategies = [], uType = context.uriTree.uriType;
|
|
143
139
|
|
|
144
140
|
context.logger.debug("authorizationProcessor", "buildStrategies()");
|
|
145
141
|
context.logger.debug("authorizationProcessor", " uriType: " + uType);
|
|
@@ -227,7 +223,7 @@ exports.buildServiceRootStrategy = function buildServiceRootStrategy(token, cont
|
|
|
227
223
|
|
|
228
224
|
return function (innerContext, done) {
|
|
229
225
|
|
|
230
|
-
|
|
226
|
+
const scopes = innerContext.parentContext.getScopes(),
|
|
231
227
|
method = innerContext.parentContext.request.method,
|
|
232
228
|
isLinks = innerContext.parentContext.oData.isLinks,
|
|
233
229
|
collectedScopes = exports.collectScopes(method, scopes, isLinks);
|
|
@@ -253,7 +249,7 @@ exports.buildDbSegmentLastStrategy =
|
|
|
253
249
|
|
|
254
250
|
return function (innerContext, done) {
|
|
255
251
|
|
|
256
|
-
|
|
252
|
+
const scopes = innerContext.parentContext.oData.dbSegmentLast.entityType.getScopes(),
|
|
257
253
|
method = innerContext.parentContext.request.method,
|
|
258
254
|
collectedScopes = exports.collectScopes(method, scopes);
|
|
259
255
|
|
|
@@ -278,7 +274,7 @@ exports.buildMultipleDbSegmentsStrategy = function (token, context) {
|
|
|
278
274
|
|
|
279
275
|
return function (innerContext, done) {
|
|
280
276
|
|
|
281
|
-
|
|
277
|
+
let currentSegment,
|
|
282
278
|
scopes,
|
|
283
279
|
method = innerContext.parentContext.request.method,
|
|
284
280
|
collectedScopes;
|
|
@@ -312,19 +308,16 @@ exports.build$linksStrategy = function build$linksStrategy(token, context) {
|
|
|
312
308
|
context.logger.debug("authorizationProcessor", "build$linksStrategy()");
|
|
313
309
|
|
|
314
310
|
return function (innerContext, done) {
|
|
315
|
-
|
|
316
|
-
var method = innerContext.parentContext.request.method,
|
|
311
|
+
const method = innerContext.parentContext.request.method,
|
|
317
312
|
toBeUpdated = innerContext.parentContext.oData.links.toBeUpdated,
|
|
318
313
|
keySource = innerContext.parentContext.oData.links.keySource,
|
|
319
314
|
toBeUpdatedScopes = toBeUpdated.entityType.getScopes(),
|
|
320
315
|
keySourceScopes = keySource.entityType.getScopes(),
|
|
321
316
|
m2n = innerContext.parentContext.oData.links.m2n;
|
|
322
|
-
|
|
323
317
|
// This block checks if the keySource (source) or the toBeUpdated entity has to be checked.
|
|
324
318
|
// In a $links request it is possible to have one --> many association or many --> one
|
|
325
319
|
// association or many --> many association. This is handled by the different else if
|
|
326
320
|
// blocks and the m2n property.
|
|
327
|
-
|
|
328
321
|
if (method === "GET") {
|
|
329
322
|
if (toBeUpdatedScopes && toBeUpdatedScopes.read) {
|
|
330
323
|
innerContext.scopes = innerContext.scopes.concat(toBeUpdatedScopes.read);
|
|
@@ -340,7 +333,6 @@ exports.build$linksStrategy = function build$linksStrategy(token, context) {
|
|
|
340
333
|
if (keySourceScopes && keySourceScopes.read) {
|
|
341
334
|
innerContext.scopes = innerContext.scopes.concat(keySourceScopes.read);
|
|
342
335
|
}
|
|
343
|
-
|
|
344
336
|
// For MxN relationships, both segments must have the scopes of: read AND create
|
|
345
337
|
if (m2n === true) {
|
|
346
338
|
if (toBeUpdatedScopes && toBeUpdatedScopes.read) {
|
|
@@ -358,7 +350,6 @@ exports.build$linksStrategy = function build$linksStrategy(token, context) {
|
|
|
358
350
|
if (keySourceScopes && keySourceScopes.read) {
|
|
359
351
|
innerContext.scopes = innerContext.scopes.concat(keySourceScopes.read);
|
|
360
352
|
}
|
|
361
|
-
|
|
362
353
|
// For MxN relationships, both segments must have the scopes of: read AND update
|
|
363
354
|
if (m2n === true) {
|
|
364
355
|
if (toBeUpdatedScopes && toBeUpdatedScopes.read) {
|
|
@@ -376,7 +367,6 @@ exports.build$linksStrategy = function build$linksStrategy(token, context) {
|
|
|
376
367
|
if (keySourceScopes && keySourceScopes.read) {
|
|
377
368
|
innerContext.scopes = innerContext.scopes.concat(keySourceScopes.read);
|
|
378
369
|
}
|
|
379
|
-
|
|
380
370
|
// For MxN relationships, both segments must have the scopes of: read AND delete
|
|
381
371
|
if (m2n === true) {
|
|
382
372
|
if (toBeUpdatedScopes && toBeUpdatedScopes.read) {
|
|
@@ -387,7 +377,6 @@ exports.build$linksStrategy = function build$linksStrategy(token, context) {
|
|
|
387
377
|
}
|
|
388
378
|
}
|
|
389
379
|
}
|
|
390
|
-
|
|
391
380
|
return done(null, innerContext);
|
|
392
381
|
};
|
|
393
382
|
};
|
|
@@ -406,7 +395,7 @@ exports.build$expandStrategy = function (token, context) {
|
|
|
406
395
|
context.logger.debug("authorizationProcessor", "build$expandStrategy()");
|
|
407
396
|
|
|
408
397
|
return function (innerContext, done) {
|
|
409
|
-
|
|
398
|
+
const dbSeg = innerContext.parentContext.oData.dbSegmentLast;
|
|
410
399
|
|
|
411
400
|
innerContext.scopes = innerContext.scopes.concat(
|
|
412
401
|
getScopesFromExpandTree(dbSeg._ExpandedNavigationsDBSeg)
|
|
@@ -433,7 +422,7 @@ exports.build$expandStrategy = function (token, context) {
|
|
|
433
422
|
*/
|
|
434
423
|
function getScopesFromExpandTree(expTree) {
|
|
435
424
|
|
|
436
|
-
|
|
425
|
+
let expandScopes = [],
|
|
437
426
|
expandTreeHasProperties,
|
|
438
427
|
elem,
|
|
439
428
|
elemScopes;
|
|
@@ -470,7 +459,7 @@ exports.buildDebugStrategy = function buildDebugStrategy(token, context) {
|
|
|
470
459
|
|
|
471
460
|
return function (innerContext, done) {
|
|
472
461
|
|
|
473
|
-
|
|
462
|
+
const scopes = innerContext.parentContext.getScopes();
|
|
474
463
|
|
|
475
464
|
if (scopes && scopes.debug) {
|
|
476
465
|
innerContext.scopes = innerContext.scopes.concat(scopes.debug);
|
|
@@ -497,7 +486,7 @@ exports.buildSecurityContextStrategy = function buildSecurityContextStrategy(tok
|
|
|
497
486
|
|
|
498
487
|
return function (innerContext, done) {
|
|
499
488
|
|
|
500
|
-
|
|
489
|
+
const scopes = innerContext.scopes;
|
|
501
490
|
|
|
502
491
|
securityContext.checkScopes(context, token, scopes, function (err, isAuthorized) {
|
|
503
492
|
innerContext.isAuthorized = isAuthorized;
|
|
@@ -519,7 +508,7 @@ exports.buildSecurityContextStrategy = function buildSecurityContextStrategy(tok
|
|
|
519
508
|
*/
|
|
520
509
|
exports.collectScopes = function collectScopes(method, scopes, isLinks) {
|
|
521
510
|
|
|
522
|
-
|
|
511
|
+
let collection = [];
|
|
523
512
|
|
|
524
513
|
// The "read" scope is always needed for $links regardless of HTTP method, because when you
|
|
525
514
|
// want to update/create/delete from an entitySet, you always have to READ the key from the
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
const async = require('async');
|
|
4
|
+
const connect = require('../db/connect');
|
|
5
|
+
const batchParser = require('./../utils/batch/batchParser');
|
|
6
|
+
const batchExecutor = require('./../utils/batch/batchExecutor');
|
|
7
|
+
const simpleRequest = require('./../http/simpleHttpRequest');
|
|
8
|
+
const simpleResponse = require('./../http/simpleHttpResponse');
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
const batchRunState = require('./../utils/batch/batchConst').runState;
|
|
11
|
+
const utils = require('./../utils/utils');
|
|
12
12
|
|
|
13
13
|
function parseBatchBody(batchContext, asyncDone) {
|
|
14
14
|
batchContext.logger.silly('batchProcessor', 'parseBody');
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const req = batchContext.parentContext.request;
|
|
16
|
+
const boundary = batchParser.getBoundary(req.headers['content-type']);
|
|
17
17
|
|
|
18
18
|
return req.getBodyAsString(function (err, body) {
|
|
19
19
|
if (err) {
|
|
@@ -50,20 +50,15 @@ function processApp(batchContext, app, resultDone) {
|
|
|
50
50
|
batchExecutor.process(app.request, app.response, batchContext, app.context, function (err) {
|
|
51
51
|
return resultDone(batchContext.inChangeSet ? err : null, app);
|
|
52
52
|
});
|
|
53
|
-
} else if (batchContext.status === batchRunState.preCommitRun) {
|
|
53
|
+
} else if (batchContext.status === batchRunState.preCommitRun || batchContext.status === batchRunState.postCommitRun) {
|
|
54
54
|
batchExecutor.processPrePostCommitRun(app.request, app.response, batchContext, app.context, function (err) {
|
|
55
|
-
return resultDone(batchContext.inChangeSet ? err : null, app);
|
|
56
|
-
});
|
|
57
|
-
} else if (batchContext.status === batchRunState.postCommitRun) {
|
|
58
|
-
batchExecutor.processPrePostCommitRun(app.request, app.response, batchContext, app.context, function (err) {
|
|
59
|
-
|
|
60
55
|
return resultDone(batchContext.inChangeSet ? err : null, app);
|
|
61
56
|
});
|
|
62
57
|
}
|
|
63
58
|
}
|
|
64
59
|
|
|
65
60
|
function processParts(batchContext, asyncDone) {
|
|
66
|
-
|
|
61
|
+
const parts = batchContext.processedPart.parts;
|
|
67
62
|
|
|
68
63
|
async.mapSeries(
|
|
69
64
|
parts,
|
|
@@ -86,13 +81,13 @@ function processParts(batchContext, asyncDone) {
|
|
|
86
81
|
|
|
87
82
|
|
|
88
83
|
function collectContentIds(batchContext, asyncDone) {
|
|
89
|
-
|
|
84
|
+
const part = batchContext.processedPart;
|
|
90
85
|
|
|
91
|
-
|
|
86
|
+
const contentIds = part.contentIds = {list: [], map: {}};
|
|
92
87
|
part.parts.forEach(function (app) {
|
|
93
|
-
|
|
88
|
+
const id = app.rawData.headers['content-id'];
|
|
94
89
|
if (id) {
|
|
95
|
-
|
|
90
|
+
const idTriple = {id: id, app: app, value: null, key_nv : {}};
|
|
96
91
|
app.contentId = idTriple;
|
|
97
92
|
contentIds.list.push(idTriple);
|
|
98
93
|
contentIds.map[id] = idTriple;
|
|
@@ -120,8 +115,8 @@ function processChangeSetPartsPreCommit(batchContext, asyncDone) {
|
|
|
120
115
|
}
|
|
121
116
|
|
|
122
117
|
function processChangeSetPartsCommit(batchContext, asyncDone) {
|
|
123
|
-
|
|
124
|
-
|
|
118
|
+
const parentContext = batchContext.parentContext;
|
|
119
|
+
const client = parentContext.db.client;
|
|
125
120
|
batchContext.logger.debug('processChangeSetPartsCommit', 'commit changeset operations');
|
|
126
121
|
client.commit(function (err) {
|
|
127
122
|
if (err) {
|
|
@@ -168,7 +163,7 @@ function processChangeSet(batchContext, part, asyncDone) {
|
|
|
168
163
|
return asyncDone(null, batchContext);
|
|
169
164
|
} else {
|
|
170
165
|
|
|
171
|
-
|
|
166
|
+
const dbClient = batchContext.parentContext.db.client;
|
|
172
167
|
if (dbClient) {
|
|
173
168
|
//ROLLBack the changes
|
|
174
169
|
return connect.dbRollback(batchContext.parentContext, dbClient, function (errDB) {
|
|
@@ -179,12 +174,6 @@ function processChangeSet(batchContext, part, asyncDone) {
|
|
|
179
174
|
|
|
180
175
|
//inside one of the changeset part an error occured
|
|
181
176
|
updateBatchContext(batchContext, part, err);
|
|
182
|
-
//batchContext.status = batchRunState.executedWithError;
|
|
183
|
-
//batchContext.inChangeSet = false;
|
|
184
|
-
//part.changeSetError = err;
|
|
185
|
-
//part.changeSetErrorResponse = err._changeSetErrorResponse;
|
|
186
|
-
//batchContext.processedPart = null;
|
|
187
|
-
|
|
188
177
|
|
|
189
178
|
//Error is set back with changeSetErrorResponse, proceed with further batch parts
|
|
190
179
|
return asyncDone(null, batchContext);
|
|
@@ -245,7 +234,7 @@ function processPart(batchContext, part, asyncDone) {
|
|
|
245
234
|
function processBatch(batchContext, asyncDone) {
|
|
246
235
|
batchContext.logger.silly('batchProcessor', 'processBatch');
|
|
247
236
|
|
|
248
|
-
|
|
237
|
+
const batchParts = batchContext.batchParsed.parts;
|
|
249
238
|
|
|
250
239
|
async.mapSeries(
|
|
251
240
|
batchParts,
|
|
@@ -264,7 +253,7 @@ function processBatch(batchContext, asyncDone) {
|
|
|
264
253
|
|
|
265
254
|
|
|
266
255
|
function sendBatchResponse(batchContext, asyncDone) {
|
|
267
|
-
|
|
256
|
+
const context = batchContext.parentContext;
|
|
268
257
|
|
|
269
258
|
batchContext.batchParsed.write(context, context.response);
|
|
270
259
|
|
|
@@ -287,7 +276,7 @@ function sendBatchResponse(batchContext, asyncDone) {
|
|
|
287
276
|
exports.process = function (context, asyncDone) {
|
|
288
277
|
context.logger.silly('batchProcessor', 'started');
|
|
289
278
|
|
|
290
|
-
|
|
279
|
+
const batchContext = {
|
|
291
280
|
parentContext: context,
|
|
292
281
|
logger: context.logger,
|
|
293
282
|
callRegisteredStep : context.callRegisteredStep, // pass to inner context
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
//Include
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const json = require('./../serializer/jsonSerializer');
|
|
5
|
+
const HttpError = require('./../utils/errors/httpError');
|
|
6
|
+
const configuration = require('./../configuration');
|
|
7
7
|
|
|
8
8
|
//Code
|
|
9
9
|
//
|
|
10
10
|
exports.process = function (context, error) {
|
|
11
|
-
|
|
11
|
+
let content, serializer;
|
|
12
12
|
|
|
13
13
|
context.logger.silly('error processor', 'process');
|
|
14
14
|
context.payloadType = 'application/json';
|
|
@@ -5,7 +5,7 @@ const HttpError = require('./../utils/errors/httpError');
|
|
|
5
5
|
const SqlError = require('../utils/errors/sqlError');
|
|
6
6
|
const dataCollector2 = require('./../sql/dataCollector2');
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const EXIT_REGEXP = /([\w\.\/\-]+)(:((\w+)\.(js|xsjslib)))?::(\w+)/;
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
11
|
ExitSpec: ExitSpec,
|
|
@@ -14,7 +14,7 @@ module.exports = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
function ExitSpec(sExitSpec) {
|
|
17
|
-
|
|
17
|
+
const aMatch = EXIT_REGEXP.exec(sExitSpec);
|
|
18
18
|
|
|
19
19
|
function throwMalformedSpec() {
|
|
20
20
|
throw new Error('Invalid exit specification ' + sExitSpec +
|
|
@@ -42,10 +42,10 @@ function ExitSpec(sExitSpec) {
|
|
|
42
42
|
*/
|
|
43
43
|
function eventHandler(sEventType, sOperation) {
|
|
44
44
|
return function callEventHandler(context, asyncDone) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
let modifications; // The defined modifications (custom exits) of the given odata service entry (association | entityType)
|
|
46
|
+
let association, entityType;
|
|
47
|
+
let operation, modelExitSpec;
|
|
48
|
+
let foundEvent;
|
|
49
49
|
|
|
50
50
|
// if links, e.g. /Employees('1')/$links/ne_Team, modifications are given in the in-xsodata-defined association (TeamEmployees)
|
|
51
51
|
if (context.oData.dbSegment && context.oData.dbSegment.isLinks) {
|
|
@@ -112,17 +112,17 @@ function logErrorSave(context, preFix, logText) {
|
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
function _executeExit(sExitSpec, sEventType, sOperation, context, asyncDone) {
|
|
115
|
-
|
|
115
|
+
const exitSpec = new ExitSpec(sExitSpec);
|
|
116
116
|
|
|
117
117
|
exitSpec._dbClient = context.db ? context.db.client : null;
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
let dbSegment = context.oData.dbSegmentLast;
|
|
120
|
+
let attribute1name; // afterTableName | (if links) principalTableName
|
|
121
|
+
let table1name; // the corresponding table name for attrib.1
|
|
122
|
+
let attribute2name; // beforeTableName | (if links) dependentTableName
|
|
123
|
+
let table2name; // the corresponding table name for attrib.2
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
let param = {}, aParams = [];
|
|
126
126
|
|
|
127
127
|
if (context.oData.dbSegment && context.oData.dbSegment.isLinks) {
|
|
128
128
|
dbSegment = context.oData.links.toBeUpdated;
|
|
@@ -195,9 +195,9 @@ function _executeExit(sExitSpec, sEventType, sOperation, context, asyncDone) {
|
|
|
195
195
|
aParams.push('?'); // for the error out parameter of the stored procedure
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
|
|
198
|
+
const sParams = aParams.join(',');
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
const sql = 'call "' + sExitSpec + '"(' + sParams + ')';
|
|
201
201
|
|
|
202
202
|
logInfoSave(context, 'custom exit:SQL-procedure', sql);
|
|
203
203
|
|
|
@@ -207,10 +207,10 @@ function _executeExit(sExitSpec, sEventType, sOperation, context, asyncDone) {
|
|
|
207
207
|
return asyncDone(new SqlError(context, err), context);
|
|
208
208
|
} else {
|
|
209
209
|
if (outTable && isNaN(outTable) && outTable.length > 0) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
const appError = outTable[0];
|
|
211
|
+
const statusCode = appError.HTTP_STATUS_CODE;
|
|
212
|
+
const errorMessage = appError.ERROR_MESSAGE;
|
|
213
|
+
const innerError = JSON.stringify(appError);
|
|
214
214
|
err = new HttpError(errorMessage, context, null, statusCode, innerError);
|
|
215
215
|
}
|
|
216
216
|
logInfoSave(context, 'custom exit', '... execution done');
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const odataUri = require('./../uri/oDataUriParser');
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const serviceProcessor = require('./../serializer/serviceSerializer');
|
|
6
|
+
const metadataProcessor = require('./../serializer/metadataSerializer');
|
|
7
|
+
const batchProcessor = require('./../processor/batchProcessor');
|
|
8
|
+
const resourceProcessor = require('./resourceProcessor');
|
|
9
|
+
const batchRunState = require('./../utils/batch/batchConst').runState;
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const Measurement = require('./../utils/measurement');
|
|
12
12
|
|
|
13
13
|
exports.processRequest = function (context, asyncDone) {
|
|
14
14
|
try {
|
|
15
15
|
context.logger.silly("processor", "processRequest");
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const oData = context.oData;
|
|
18
18
|
|
|
19
19
|
if (oData.kind === odataUri.URI_KIND_Service) {
|
|
20
20
|
Measurement.measureWithCB(serviceProcessor.process, context, asyncDone, 'serviceProcessor.process');
|
|
@@ -28,7 +28,7 @@ exports.processRequest = function (context, asyncDone) {
|
|
|
28
28
|
// regular request processing
|
|
29
29
|
Measurement.measureWithCB(resourceProcessor.process, context, asyncDone, 'resourceProcessor.process');
|
|
30
30
|
} else {
|
|
31
|
-
|
|
31
|
+
const batchContext = context.batchContext; // $batch-request: operation processing (based on status)
|
|
32
32
|
if (batchContext.status === batchRunState.createTables) { // on batch changes: all temp. tables of all operations are generated at beginning batch
|
|
33
33
|
Measurement.measureWithCB(resourceProcessor.processInBatchCreateTables, context, asyncDone, 'processInBatchCreateTables');
|
|
34
34
|
}else if (batchContext.status === batchRunState.execution) {
|