meadow-endpoints 3.0.6 → 4.0.2
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/{Dockerfile → Dockerfile_LUXURYCode} +43 -1
- package/README.md +48 -14
- package/debug/Animal.json +62 -0
- package/debug/Harness-Configuration.json +31 -0
- package/debug/Harness.js +7 -108
- package/debug/KillHarness.sh +10 -0
- package/dist/meadowendpoints.js +4402 -0
- package/dist/meadowendpoints.min.js +92 -0
- package/dist/meadowendpoints.min.js.map +1 -0
- package/gulpfile.js +83 -0
- package/package.json +29 -16
- package/source/Meadow-Endpoints-Browser-Shim.js +14 -0
- package/source/Meadow-Endpoints.js +176 -562
- package/source/controller/Meadow-Endpoints-Controller-Base.js +161 -0
- package/source/controller/components/Meadow-Endpoints-Controller-BehaviorInjection.js +125 -0
- package/source/controller/components/Meadow-Endpoints-Controller-Error-StatusCodes.txt +189 -0
- package/source/controller/components/Meadow-Endpoints-Controller-Error.js +118 -0
- package/source/controller/components/Meadow-Endpoints-Controller-Log.js +103 -0
- package/source/controller/utility/Meadow-Endpoints-Filter-Parser.js +225 -0
- package/source/controller/utility/Meadow-Endpoints-Session-Marshaler.js +48 -0
- package/source/controller/utility/Meadow-Endpoints-Stream-RecordArray.js +66 -0
- package/source/endpoints/count/Meadow-Endpoint-Count.js +49 -0
- package/source/endpoints/count/Meadow-Endpoint-CountBy.js +40 -0
- package/source/endpoints/create/Meadow-Endpoint-BulkCreate.js +53 -0
- package/source/endpoints/create/Meadow-Endpoint-Create.js +58 -0
- package/source/endpoints/create/Meadow-Operation-Create.js +83 -0
- package/source/endpoints/delete/Meadow-Endpoint-Delete.js +93 -0
- package/source/endpoints/delete/Meadow-Endpoint-Undelete.js +108 -0
- package/source/endpoints/read/Meadow-Endpoint-Read.js +72 -0
- package/source/endpoints/read/Meadow-Endpoint-ReadDistinctList.js +92 -0
- package/source/endpoints/read/Meadow-Endpoint-ReadLiteList.js +85 -0
- package/source/endpoints/read/Meadow-Endpoint-ReadMax.js +55 -0
- package/source/endpoints/read/Meadow-Endpoint-ReadSelectList.js +89 -0
- package/source/endpoints/read/Meadow-Endpoint-Reads.js +75 -0
- package/source/endpoints/read/Meadow-Endpoint-ReadsBy.js +100 -0
- package/source/{crud → endpoints/read}/Meadow-Marshal-DistinctList.js +4 -13
- package/source/{crud → endpoints/read}/Meadow-Marshal-LiteList.js +5 -14
- package/source/endpoints/schema/Meadow-Endpoint-New.js +36 -0
- package/source/endpoints/schema/Meadow-Endpoint-Schema.js +36 -0
- package/source/endpoints/schema/Meadow-Endpoint-Validate.js +41 -0
- package/source/endpoints/update/Meadow-Endpoint-BulkUpdate.js +50 -0
- package/source/endpoints/update/Meadow-Endpoint-Update.js +58 -0
- package/source/endpoints/update/Meadow-Operation-Update.js +115 -0
- package/source/endpoints/upsert/Meadow-Endpoint-BulkUpsert.js +52 -0
- package/source/endpoints/upsert/Meadow-Endpoint-Upsert.js +57 -0
- package/source/endpoints/upsert/Meadow-Operation-Upsert.js +137 -0
- package/test/MeadowEndpoints_basic_tests.js +50 -2375
- package/test_support/bookstore-api-endpoint-exercises.paw +0 -0
- package/test_support/bookstore-configuration.json +28 -0
- package/test_support/bookstore-import-books-run.js +1 -0
- package/test_support/bookstore-import-books.js +215 -0
- package/test_support/bookstore-serve-meadow-endpoint-apis-IPC.js +138 -0
- package/test_support/bookstore-serve-meadow-endpoint-apis-run.js +6 -0
- package/test_support/bookstore-serve-meadow-endpoint-apis.js +129 -0
- package/test_support/data/books.csv +10001 -0
- package/test_support/model/ddl/BookStore.ddl +66 -0
- package/test_support/model/generated_diagram/README.md +1 -0
- package/test_support/model/generated_diagram/Stricture_Output.dot +13 -0
- package/test_support/model/generated_diagram/Stricture_Output.png +0 -0
- package/test_support/model/generated_documentation/Dictionary.md +18 -0
- package/test_support/model/generated_documentation/Model-Author.md +20 -0
- package/test_support/model/generated_documentation/Model-Book.md +26 -0
- package/test_support/model/generated_documentation/Model-BookAuthorJoin.md +14 -0
- package/test_support/model/generated_documentation/Model-BookPrice.md +25 -0
- package/test_support/model/generated_documentation/Model-Review.md +22 -0
- package/test_support/model/generated_documentation/ModelChangeTracking.md +17 -0
- package/test_support/model/generated_documentation/README.md +1 -0
- package/test_support/model/manual_scripts/DropTables.sql +5 -0
- package/test_support/model/manual_scripts/README.md +2 -0
- package/test_support/model/sql_create/BookStore-CreateDatabase.mysql.sql +116 -0
- package/test_support/model/sql_create/README.md +1 -0
- package/test_support/test_old/Tests.js +3243 -0
- package/test_support/test_old/untitled.js +88 -0
- package/source/Meadow-Authenticator.js +0 -31
- package/source/Meadow-Authorizers.js +0 -214
- package/source/Meadow-BehaviorModifications.js +0 -170
- package/source/Meadow-CommonServices.js +0 -206
- package/source/Meadow-MarshallSessionData.js +0 -64
- package/source/Restify-RouteParser.js +0 -114
- package/source/authorizers/Meadow-Authorizer-Allow.js +0 -17
- package/source/authorizers/Meadow-Authorizer-Deny.js +0 -17
- package/source/authorizers/Meadow-Authorizer-Mine.js +0 -47
- package/source/authorizers/Meadow-Authorizer-MyCustomer.js +0 -48
- package/source/crud/Meadow-Endpoint-BulkCreate.js +0 -67
- package/source/crud/Meadow-Endpoint-BulkUpdate.js +0 -74
- package/source/crud/Meadow-Endpoint-BulkUpsert.js +0 -76
- package/source/crud/Meadow-Endpoint-Count.js +0 -93
- package/source/crud/Meadow-Endpoint-CountBy.js +0 -101
- package/source/crud/Meadow-Endpoint-Create.js +0 -77
- package/source/crud/Meadow-Endpoint-Delete.js +0 -139
- package/source/crud/Meadow-Endpoint-Read.js +0 -109
- package/source/crud/Meadow-Endpoint-ReadDistinctList.js +0 -146
- package/source/crud/Meadow-Endpoint-ReadLiteList.js +0 -139
- package/source/crud/Meadow-Endpoint-ReadMax.js +0 -86
- package/source/crud/Meadow-Endpoint-ReadSelectList.js +0 -145
- package/source/crud/Meadow-Endpoint-Reads.js +0 -129
- package/source/crud/Meadow-Endpoint-ReadsBy.js +0 -155
- package/source/crud/Meadow-Endpoint-Update.js +0 -80
- package/source/crud/Meadow-Endpoint-Upsert.js +0 -78
- package/source/crud/Meadow-Operation-Create.js +0 -105
- package/source/crud/Meadow-Operation-Update.js +0 -145
- package/source/crud/Meadow-Operation-Upsert.js +0 -106
- package/source/crud/Meadow-StreamRecordArray.js +0 -45
- package/source/schema/Meadow-Endpoint-New.js +0 -37
- package/source/schema/Meadow-Endpoint-Schema.js +0 -37
- package/source/schema/Meadow-Endpoint-Validate.js +0 -43
- package/test/Animal.json +0 -140
- package/test/MeadowEndpoints_disabledAuth_tests.js +0 -1325
- package/test/MeadowEndpoints_trustedSession_tests.js +0 -1731
- package/test/load/artillery-low.yml +0 -10
- package/test/load/cloud9setup.sh +0 -25
- package/test/load/package.json +0 -19
- package/test/load/test-schema-initializedatabase.sql +0 -29
- package/test/load/test-schema.json +0 -119
- package/test/load/test-server.js +0 -157
- package/test/scripts/InitializeDatabase-C9.sql +0 -7
- /package/{test/schemas → test_support/model}/json_schema/BookStore-Extended.json +0 -0
- /package/{test/schemas → test_support/model}/json_schema/BookStore-PICT.json +0 -0
- /package/{test/schemas → test_support/model}/json_schema/BookStore.json +0 -0
- /package/{test/schemas → test_support/model}/json_schema/README.md +0 -0
- /package/{test/schemas → test_support/model}/meadow_schema/BookStore-MeadowSchema-Author.json +0 -0
- /package/{test/schemas → test_support/model}/meadow_schema/BookStore-MeadowSchema-Book.json +0 -0
- /package/{test/schemas → test_support/model}/meadow_schema/BookStore-MeadowSchema-BookAuthorJoin.json +0 -0
- /package/{test/schemas → test_support/model}/meadow_schema/BookStore-MeadowSchema-BookPrice.json +0 -0
- /package/{test/schemas → test_support/model}/meadow_schema/BookStore-MeadowSchema-Review.json +0 -0
- /package/{test/schemas → test_support/model}/meadow_schema/README.md +0 -0
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - Update a Record
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Update a record using the Meadow DAL object
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
var libAsync = require('async');
|
|
14
|
-
|
|
15
|
-
var doUpdate = require('./Meadow-Operation-Update.js');
|
|
16
|
-
|
|
17
|
-
var doAPIUpdateEndpoint = function(pRequest, pResponse, fNext)
|
|
18
|
-
{
|
|
19
|
-
// This state is the requirement for the UserRoleIndex value in the UserSession object... processed by default as >=
|
|
20
|
-
// The default here is that any authenticated user can use this endpoint.
|
|
21
|
-
pRequest.EndpointAuthorizationRequirement = pRequest.EndpointAuthorizationLevels.Update;
|
|
22
|
-
|
|
23
|
-
// INJECT: Pre authorization (for instance to change the authorization level)
|
|
24
|
-
|
|
25
|
-
if (pRequest.CommonServices.authorizeEndpoint(pRequest, pResponse, fNext) === false)
|
|
26
|
-
{
|
|
27
|
-
// If this endpoint fails, it's sent an error automatically.
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Configure the request for the generic update operation
|
|
32
|
-
pRequest.UpdatedRecords = [];
|
|
33
|
-
pRequest.MeadowOperation = 'Update';
|
|
34
|
-
|
|
35
|
-
libAsync.waterfall(
|
|
36
|
-
[
|
|
37
|
-
function(fStageComplete)
|
|
38
|
-
{
|
|
39
|
-
//1. Validate request body to ensure it is a valid record
|
|
40
|
-
if (typeof(pRequest.body) !== 'object')
|
|
41
|
-
{
|
|
42
|
-
return pRequest.CommonServices.sendError('Record update failure - a valid record is required.', pRequest, pResponse, fNext);
|
|
43
|
-
}
|
|
44
|
-
if (pRequest.body[pRequest.DAL.defaultIdentifier] < 1)
|
|
45
|
-
{
|
|
46
|
-
return pRequest.CommonServices.sendError('Record update failure - a valid record ID is required in the passed-in record.', pRequest, pResponse, fNext);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
pRequest.Record = pRequest.body;
|
|
50
|
-
|
|
51
|
-
return fStageComplete(null);
|
|
52
|
-
},
|
|
53
|
-
function(fStageComplete)
|
|
54
|
-
{
|
|
55
|
-
//4. Do the update operation
|
|
56
|
-
doUpdate(pRequest.body, pRequest, pResponse, fStageComplete);
|
|
57
|
-
},
|
|
58
|
-
function(fStageComplete)
|
|
59
|
-
{
|
|
60
|
-
//5. Respond with the new record
|
|
61
|
-
|
|
62
|
-
// If there was an error, respond with that instead
|
|
63
|
-
if (pRequest.RecordUpdateError)
|
|
64
|
-
return fStageComplete(pRequest.RecordUpdateErrorMessage);
|
|
65
|
-
|
|
66
|
-
pResponse.send(pRequest.Record);
|
|
67
|
-
return fStageComplete(null);
|
|
68
|
-
}
|
|
69
|
-
], function(pError)
|
|
70
|
-
{
|
|
71
|
-
if (pError)
|
|
72
|
-
{
|
|
73
|
-
return pRequest.CommonServices.sendCodedError('Error updating a record.', pError, pRequest, pResponse, fNext);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return fNext();
|
|
77
|
-
});
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
module.exports = doAPIUpdateEndpoint;
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - Upsert (Insert OR Update) a Record
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Upsert a record using the Meadow DAL object
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
var libAsync = require('async');
|
|
14
|
-
|
|
15
|
-
var doUpsert = require('./Meadow-Operation-Upsert.js');
|
|
16
|
-
|
|
17
|
-
var doAPIUpsertEndpoint = function(pRequest, pResponse, fNext)
|
|
18
|
-
{
|
|
19
|
-
// This state is the requirement for the UserRoleIndex value in the UserSession object... processed by default as >=
|
|
20
|
-
// The default here is that any authenticated user can use this endpoint.
|
|
21
|
-
pRequest.EndpointAuthorizationRequirement = pRequest.EndpointAuthorizationLevels.Update;
|
|
22
|
-
|
|
23
|
-
// INJECT: Pre authorization (for instance to change the authorization level)
|
|
24
|
-
|
|
25
|
-
if (pRequest.CommonServices.authorizeEndpoint(pRequest, pResponse, fNext) === false)
|
|
26
|
-
{
|
|
27
|
-
// If this endpoint fails, it's sent an error automatically.
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Configure the request for the generic create & update operations
|
|
32
|
-
pRequest.CreatedRecords = [];
|
|
33
|
-
pRequest.UpdatedRecords = [];
|
|
34
|
-
pRequest.UpsertedRecords = [];
|
|
35
|
-
pRequest.MeadowOperation = 'Upsert';
|
|
36
|
-
|
|
37
|
-
libAsync.waterfall(
|
|
38
|
-
[
|
|
39
|
-
function(fStageComplete)
|
|
40
|
-
{
|
|
41
|
-
//1. Validate request body to ensure it is a valid record
|
|
42
|
-
if (typeof(pRequest.body) !== 'object')
|
|
43
|
-
{
|
|
44
|
-
return pRequest.CommonServices.sendError('Record upsert failure - a valid record is required.', pRequest, pResponse, fNext);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
pRequest.Record = pRequest.body;
|
|
48
|
-
|
|
49
|
-
return fStageComplete(null);
|
|
50
|
-
},
|
|
51
|
-
function(fStageComplete)
|
|
52
|
-
{
|
|
53
|
-
//4. Do the upsert operation
|
|
54
|
-
doUpsert(pRequest.body, pRequest, pResponse, fStageComplete);
|
|
55
|
-
},
|
|
56
|
-
function(fStageComplete)
|
|
57
|
-
{
|
|
58
|
-
//5. Respond with the new record
|
|
59
|
-
|
|
60
|
-
// If there was an error, respond with that instead
|
|
61
|
-
if (pRequest.RecordUpsertError)
|
|
62
|
-
return fStageComplete(pRequest.RecordUpsertErrorMessage);
|
|
63
|
-
|
|
64
|
-
pResponse.send(pRequest.Record);
|
|
65
|
-
return fStageComplete(null);
|
|
66
|
-
}
|
|
67
|
-
], function(pError)
|
|
68
|
-
{
|
|
69
|
-
if (pError)
|
|
70
|
-
{
|
|
71
|
-
return pRequest.CommonServices.sendCodedError('Error upserting a record.', pError, pRequest, pResponse, fNext);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return fNext();
|
|
75
|
-
});
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
module.exports = doAPIUpsertEndpoint;
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Operation - Create a record function
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Shared record create code
|
|
11
|
-
*/
|
|
12
|
-
var libAsync = require('async');
|
|
13
|
-
|
|
14
|
-
var doCreate = function(pRecord, pRequest, pResponse, fCallback)
|
|
15
|
-
{
|
|
16
|
-
pRequest.MeadowOperation = (typeof(pRequest.MeadowOperation) === 'string') ? pRequest.MeadowOperation : 'Create';
|
|
17
|
-
|
|
18
|
-
libAsync.waterfall(
|
|
19
|
-
[
|
|
20
|
-
function(fStageComplete)
|
|
21
|
-
{
|
|
22
|
-
// Do this for compatibility with injected behaviors
|
|
23
|
-
pRequest.Record = pRecord;
|
|
24
|
-
|
|
25
|
-
//Make sure record gets created with a customerID
|
|
26
|
-
if (!pRequest.Record.hasOwnProperty('IDCustomer') &&
|
|
27
|
-
pRequest.DAL.jsonSchema.properties.hasOwnProperty('IDCustomer'))
|
|
28
|
-
{
|
|
29
|
-
pRequest.Record.IDCustomer = pRequest.UserSession.CustomerID || 0;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
pRequest.BehaviorModifications.runBehavior('Create-PreOperation', pRequest, fStageComplete);
|
|
33
|
-
},
|
|
34
|
-
function(fStageComplete)
|
|
35
|
-
{
|
|
36
|
-
pRequest.Authorizers.authorizeRequest('Create', pRequest, fStageComplete);
|
|
37
|
-
},
|
|
38
|
-
function (fStageComplete)
|
|
39
|
-
{
|
|
40
|
-
if (pRequest.MeadowAuthorization)
|
|
41
|
-
{
|
|
42
|
-
return fStageComplete(false);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// It looks like this record was not authorized. Send an error.
|
|
46
|
-
return fStageComplete({Code:405,Message:'UNAUTHORIZED ACCESS IS NOT ALLOWED'});
|
|
47
|
-
},
|
|
48
|
-
function(fStageComplete)
|
|
49
|
-
{
|
|
50
|
-
//3. Prepare create query
|
|
51
|
-
var tmpQuery = pRequest.DAL.query;
|
|
52
|
-
|
|
53
|
-
tmpQuery.setIDUser(pRequest.UserSession.UserID);
|
|
54
|
-
tmpQuery.addRecord(pRecord);
|
|
55
|
-
|
|
56
|
-
return fStageComplete(null, tmpQuery);
|
|
57
|
-
},
|
|
58
|
-
// 3. INJECT: Query configuration
|
|
59
|
-
function (tmpQuery, fStageComplete)
|
|
60
|
-
{
|
|
61
|
-
pRequest.Query = tmpQuery;
|
|
62
|
-
pRequest.BehaviorModifications.runBehavior('Create-QueryConfiguration', pRequest, fStageComplete);
|
|
63
|
-
},
|
|
64
|
-
function(fStageComplete)
|
|
65
|
-
{
|
|
66
|
-
//4. Do the create operation
|
|
67
|
-
pRequest.DAL.doCreate(pRequest.Query,
|
|
68
|
-
function(pError, pQuery, pReadQuery, pNewRecord)
|
|
69
|
-
{
|
|
70
|
-
if (!pNewRecord)
|
|
71
|
-
{
|
|
72
|
-
return fStageComplete('Error in DAL create: '+pError);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
pRequest.Record = pNewRecord;
|
|
76
|
-
|
|
77
|
-
pRequest.CreatedRecords.push(pNewRecord);
|
|
78
|
-
|
|
79
|
-
//pRequest.CommonServices.log.info('Created a record with ID '+pNewRecord[pRequest.DAL.defaultIdentifier]+'.', {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-CreateBulk'}, pRequest);
|
|
80
|
-
|
|
81
|
-
return fStageComplete(null);
|
|
82
|
-
});
|
|
83
|
-
},
|
|
84
|
-
function(fStageComplete)
|
|
85
|
-
{
|
|
86
|
-
return pRequest.BehaviorModifications.runBehavior('Create-PostOperation', pRequest, fStageComplete);
|
|
87
|
-
}
|
|
88
|
-
], function(pError)
|
|
89
|
-
{
|
|
90
|
-
if (pError)
|
|
91
|
-
{
|
|
92
|
-
pRecord.Error = 'Error creating record:'+pError;
|
|
93
|
-
// Added for singleton operations
|
|
94
|
-
pRequest.RecordCreateError = true;
|
|
95
|
-
pRequest.RecordCreateErrorMessage = pError;
|
|
96
|
-
// Also push the record to the created record stack with an error message
|
|
97
|
-
pRequest.CreatedRecords.push(pRecord);
|
|
98
|
-
pRequest.CommonServices.log.error('Error creating record:'+pError, {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-'+pRequest.MeadowOperation, Stack: pError.stack }, pRequest);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return fCallback();
|
|
102
|
-
});
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
module.exports = doCreate;
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Operation - Update a record
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Update a record using the Meadow DAL object.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
var libAsync = require('async');
|
|
14
|
-
|
|
15
|
-
var doUpdate = function(pRecordToModify, pRequest, pResponse, fCallback, pOptionalCachedUpdatingRecord)
|
|
16
|
-
{
|
|
17
|
-
// pOptionalCachedUpdatingRecord allows the caller to pass in a record, so the initial read doesn't need to happen.
|
|
18
|
-
pRequest.MeadowOperation = (typeof(pRequest.MeadowOperation) === 'string') ? pRequest.MeadowOperation : 'Update';
|
|
19
|
-
|
|
20
|
-
// If there is not a default identifier or cached record, fail
|
|
21
|
-
if ((pRecordToModify[pRequest.DAL.defaultIdentifier] < 1) && (typeof(pOptionalCachedUpdatingRecord) === 'undefined'))
|
|
22
|
-
{
|
|
23
|
-
return fCallback('Record update failure - a valid record ID is required in the passed-in record.');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
libAsync.waterfall(
|
|
27
|
-
[
|
|
28
|
-
function(fStageComplete)
|
|
29
|
-
{
|
|
30
|
-
pRequest.Record = pRecordToModify;
|
|
31
|
-
|
|
32
|
-
if (typeof(pOptionalCachedUpdatingRecord) !== 'undefined')
|
|
33
|
-
{
|
|
34
|
-
// Use the cached updating record instead of reading a record.
|
|
35
|
-
return fStageComplete(false, pOptionalCachedUpdatingRecord);
|
|
36
|
-
}
|
|
37
|
-
else
|
|
38
|
-
{
|
|
39
|
-
var tmpQuery = pRequest.DAL.query;
|
|
40
|
-
|
|
41
|
-
// This is not overloadable.
|
|
42
|
-
tmpQuery.addFilter(pRequest.DAL.defaultIdentifier, pRecordToModify[pRequest.DAL.defaultIdentifier]);
|
|
43
|
-
|
|
44
|
-
// Load the record so we can do security checks on it
|
|
45
|
-
pRequest.DAL.doRead(tmpQuery,
|
|
46
|
-
function(pError, pQuery, pRecord)
|
|
47
|
-
{
|
|
48
|
-
if (!pError && !pRecord)
|
|
49
|
-
{
|
|
50
|
-
//short-circuit: Can't update a record that doesn't exist!
|
|
51
|
-
pError = 'Record not found.';
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return fStageComplete(pError, pRecord);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
function(pOriginalRecord, fStageComplete)
|
|
59
|
-
{
|
|
60
|
-
//send the original record to the Authorizer so it can verify ownership/etc
|
|
61
|
-
// TODO: Because the authorizer looks in the request for the record, we need to fix this somehow to work asynchronously.
|
|
62
|
-
pRequest.UpdatingRecord = pRecordToModify;
|
|
63
|
-
pRequest.Record = pOriginalRecord;
|
|
64
|
-
|
|
65
|
-
pRequest.Authorizers.authorizeRequest('Update', pRequest, function(err)
|
|
66
|
-
{
|
|
67
|
-
pRequest.Record = pRequest.UpdatingRecord;
|
|
68
|
-
return fStageComplete(err);
|
|
69
|
-
});
|
|
70
|
-
},
|
|
71
|
-
function(fStageComplete)
|
|
72
|
-
{
|
|
73
|
-
//2. INJECT: Record modification before update
|
|
74
|
-
pRequest.BehaviorModifications.runBehavior('Update-PreOperation', pRequest, fStageComplete);
|
|
75
|
-
},
|
|
76
|
-
function (fStageComplete)
|
|
77
|
-
{
|
|
78
|
-
if (pRequest.MeadowAuthorization)
|
|
79
|
-
{
|
|
80
|
-
return fStageComplete(false);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// It looks like this record was not authorized. Send an error.
|
|
84
|
-
var tmpError = {Code:405,Message:'UNAUTHORIZED ACCESS IS NOT ALLOWED'};
|
|
85
|
-
tmpError.Scope = pRequest.DAL.scope;
|
|
86
|
-
tmpError[pRequest.DAL.defaultIdentifier] = pRequest.Record[pRequest.DAL.defaultIdentifier];
|
|
87
|
-
return fStageComplete(tmpError);
|
|
88
|
-
},
|
|
89
|
-
// 3a. INJECT: Query configuration
|
|
90
|
-
function (fStageComplete)
|
|
91
|
-
{
|
|
92
|
-
pRequest.Query = pRequest.DAL.query;
|
|
93
|
-
pRequest.BehaviorModifications.runBehavior('Update-QueryConfiguration', pRequest, fStageComplete);
|
|
94
|
-
},
|
|
95
|
-
function(fStageComplete)
|
|
96
|
-
{
|
|
97
|
-
//3b. Prepare update query
|
|
98
|
-
var tmpQuery = pRequest.Query;
|
|
99
|
-
|
|
100
|
-
tmpQuery.setIDUser(pRequest.UserSession.UserID);
|
|
101
|
-
tmpQuery.addRecord(pRequest.Record);
|
|
102
|
-
|
|
103
|
-
return fStageComplete(null, tmpQuery);
|
|
104
|
-
},
|
|
105
|
-
function(pPreparedQuery, fStageComplete)
|
|
106
|
-
{
|
|
107
|
-
//4. Do the update operation
|
|
108
|
-
pRequest.DAL.doUpdate(pPreparedQuery,
|
|
109
|
-
function(pError, pQuery, pReadQuery, pRecord)
|
|
110
|
-
{
|
|
111
|
-
if (!pRecord)
|
|
112
|
-
{
|
|
113
|
-
return fStageComplete('Error updating a record.');
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
pRequest.Record = pRecord;
|
|
117
|
-
|
|
118
|
-
pRequest.UpdatedRecords.push(pRecord);
|
|
119
|
-
|
|
120
|
-
//pRequest.CommonServices.log.info('Updated a record with ID '+pRecord[pRequest.DAL.defaultIdentifier]+'.', {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-UpdateBulk'}, pRequest);
|
|
121
|
-
|
|
122
|
-
return fStageComplete(null);
|
|
123
|
-
});
|
|
124
|
-
},
|
|
125
|
-
function(fStageComplete)
|
|
126
|
-
{
|
|
127
|
-
// INJECT: Post modification with record
|
|
128
|
-
return pRequest.BehaviorModifications.runBehavior('Update-PostOperation', pRequest, fStageComplete);
|
|
129
|
-
}
|
|
130
|
-
], function(pError)
|
|
131
|
-
{
|
|
132
|
-
if (pError)
|
|
133
|
-
{
|
|
134
|
-
pRecordToModify.Error = 'Error updating record:'+pError;
|
|
135
|
-
pRequest.RecordUpdateError = true;
|
|
136
|
-
pRequest.RecordUpdateErrorMessage = pError;
|
|
137
|
-
pRequest.UpdatedRecords.push(pRecordToModify);
|
|
138
|
-
pRequest.CommonServices.log.error('Error updating record:'+pError, {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-'+pRequest.MeadowOperation, Stack: pError.stack }, pRequest);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return fCallback();
|
|
142
|
-
});
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
module.exports = doUpdate;
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Operation - Upsert a record
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Upsert a record using the Meadow DAL object.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
var libAsync = require('async');
|
|
14
|
-
|
|
15
|
-
var doCreate = require('./Meadow-Operation-Create.js');
|
|
16
|
-
var doUpdate = require('./Meadow-Operation-Update.js');
|
|
17
|
-
|
|
18
|
-
var doUpsert = function(pRecordToUpsert, pRequest, pResponse, fCallback)
|
|
19
|
-
{
|
|
20
|
-
pRequest.MeadowOperation = (typeof(pRequest.MeadowOperation) === 'string') ? pRequest.MeadowOperation : 'Upsert';
|
|
21
|
-
|
|
22
|
-
libAsync.waterfall(
|
|
23
|
-
[
|
|
24
|
-
function(fStageComplete)
|
|
25
|
-
{
|
|
26
|
-
// Prepare to gather requirements for upserting
|
|
27
|
-
pRequest.Record = pRecordToUpsert;
|
|
28
|
-
|
|
29
|
-
var tmpQuery = pRequest.DAL.query;
|
|
30
|
-
|
|
31
|
-
// This operation will be create only if there is no GUID or ID in the record bundle
|
|
32
|
-
pRequest.UpsertCreateOnly = true;
|
|
33
|
-
|
|
34
|
-
// See if there is a default identifier or default GUIdentifier
|
|
35
|
-
if ((typeof(pRecordToUpsert[pRequest.DAL.defaultGUIdentifier]) !== 'undefined') && pRecordToUpsert[pRequest.DAL.defaultGUIdentifier].length > 0)
|
|
36
|
-
{
|
|
37
|
-
tmpQuery.addFilter(pRequest.DAL.defaultGUIdentifier, pRecordToUpsert[pRequest.DAL.defaultGUIdentifier]);
|
|
38
|
-
pRequest.UpsertCreateOnly = false;
|
|
39
|
-
}
|
|
40
|
-
if ((typeof(pRecordToUpsert[pRequest.DAL.defaultIdentifier]) !== 'undefined') && (pRecordToUpsert[pRequest.DAL.defaultIdentifier] > 0))
|
|
41
|
-
{
|
|
42
|
-
tmpQuery.addFilter(pRequest.DAL.defaultIdentifier, pRecordToUpsert[pRequest.DAL.defaultIdentifier]);
|
|
43
|
-
pRequest.UpsertCreateOnly = false;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (pRequest.UpsertCreateOnly)
|
|
47
|
-
{
|
|
48
|
-
// Just create the record
|
|
49
|
-
doCreate(pRecordToUpsert, pRequest, pResponse, fStageComplete);
|
|
50
|
-
}
|
|
51
|
-
else
|
|
52
|
-
{
|
|
53
|
-
// Load the record to see if it exists
|
|
54
|
-
pRequest.DAL.doRead(tmpQuery,
|
|
55
|
-
function(pError, pQuery, pRecord)
|
|
56
|
-
{
|
|
57
|
-
if (pError)
|
|
58
|
-
{
|
|
59
|
-
// Return the error, because there was an error.
|
|
60
|
-
return fStageComplete(pError);
|
|
61
|
-
}
|
|
62
|
-
else if (!pError && !pRecord)
|
|
63
|
-
{
|
|
64
|
-
// Record not found -- do a create.
|
|
65
|
-
doCreate(pRecordToUpsert, pRequest, pResponse, fStageComplete);
|
|
66
|
-
}
|
|
67
|
-
else
|
|
68
|
-
{
|
|
69
|
-
// Set the default ID in the passed-in record if it doesn't exist..
|
|
70
|
-
if (!pRecordToUpsert.hasOwnProperty(pRequest.DAL.defaultIdentifier))
|
|
71
|
-
{
|
|
72
|
-
pRecordToUpsert[pRequest.DAL.defaultIdentifier] = pRecord[pRequest.DAL.defaultIdentifier];
|
|
73
|
-
}
|
|
74
|
-
// If the found record does not match the passed ID --- what the heck?!
|
|
75
|
-
if (pRecordToUpsert[pRequest.DAL.defaultIdentifier] != pRecord[pRequest.DAL.defaultIdentifier])
|
|
76
|
-
{
|
|
77
|
-
return fStageComplete('Default identifier does not match GUID record.');
|
|
78
|
-
}
|
|
79
|
-
// Record found -- do an update. Use the cached record, though.
|
|
80
|
-
doUpdate(pRecordToUpsert, pRequest, pResponse, fStageComplete, pRecord);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
function(fStageComplete)
|
|
86
|
-
{
|
|
87
|
-
// Now stuff the record into the upserted array
|
|
88
|
-
pRequest.UpsertedRecords.push(pRequest.Record);
|
|
89
|
-
fStageComplete(null);
|
|
90
|
-
}
|
|
91
|
-
], function(pError)
|
|
92
|
-
{
|
|
93
|
-
if (pError)
|
|
94
|
-
{
|
|
95
|
-
pRecordToUpsert.Error = 'Error upserting record:'+pError;
|
|
96
|
-
pRequest.RecordUpsertError = true;
|
|
97
|
-
pRequest.RecordUpsertErrorMessage = pError;
|
|
98
|
-
pRequest.UpsertedRecords.push(pRecordToUpsert);
|
|
99
|
-
pRequest.CommonServices.log.error('Error upserting record:'+pError, {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-'+pRequest.MeadowOperation, Stack: pError.stack }, pRequest);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return fCallback();
|
|
103
|
-
});
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
module.exports = doUpsert;
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint Marshaller - Stream an array of recods as JSON to an output stream.
|
|
3
|
-
*
|
|
4
|
-
* If the array is small enough, we just call send() for simplicity.
|
|
5
|
-
*
|
|
6
|
-
* @license MIT
|
|
7
|
-
*
|
|
8
|
-
* @author Alex Decker <alex.decker@headlight.com>
|
|
9
|
-
* @module Meadow
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const libAsync = require('async');
|
|
13
|
-
const JSONStream = require('JSONStream');
|
|
14
|
-
const libUnderscore = require('underscore');
|
|
15
|
-
|
|
16
|
-
module.exports = (pResponse, pRecords, fCallback) =>
|
|
17
|
-
{
|
|
18
|
-
// for meadow invoke, writeHead isn't provided, so just call send(), which is the shim it uses...
|
|
19
|
-
// also, for small arrays, don't bother with the async serialization; this threshold could use tuning
|
|
20
|
-
if (!pResponse.writeHead || !Array.isArray(pRecords) || pRecords.length < 2500)
|
|
21
|
-
{
|
|
22
|
-
pResponse.send(pRecords);
|
|
23
|
-
return fCallback();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
pResponse.writeHead(200,
|
|
27
|
-
{
|
|
28
|
-
'content-type': 'application/json',
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const recordJsonMarshaller = JSONStream.stringify();
|
|
32
|
-
recordJsonMarshaller.pipe(pResponse);
|
|
33
|
-
|
|
34
|
-
// we write the records in chunks; doing one per loop is very inefficient, doing all is the same as not doing this at all
|
|
35
|
-
libAsync.eachSeries(libUnderscore.chunk(pRecords, 1000), (pRecordChunk, fNext) =>
|
|
36
|
-
{
|
|
37
|
-
pRecordChunk.forEach(recordJsonMarshaller.write);
|
|
38
|
-
setImmediate(fNext);
|
|
39
|
-
},
|
|
40
|
-
(error) =>
|
|
41
|
-
{
|
|
42
|
-
recordJsonMarshaller.end();
|
|
43
|
-
fCallback(error);
|
|
44
|
-
});
|
|
45
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - New Record
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Create a new record using the Meadow DAL object
|
|
11
|
-
*/
|
|
12
|
-
var doAPINewEndpoint = function(pRequest, pResponse, fNext)
|
|
13
|
-
{
|
|
14
|
-
// This state is the requirement for the UserRoleIndex value in the UserSession object... processed by default as >=
|
|
15
|
-
// The default here is that any authenticated user can use this endpoint.
|
|
16
|
-
pRequest.EndpointAuthorizationRequirement = pRequest.EndpointAuthorizationLevels.New;
|
|
17
|
-
|
|
18
|
-
// INJECT: Pre authorization (for instance to change the authorization level)
|
|
19
|
-
|
|
20
|
-
if (pRequest.CommonServices.authorizeEndpoint(pRequest, pResponse, fNext) === false)
|
|
21
|
-
{
|
|
22
|
-
// If this endpoint fails, it's sent an error automatically.
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// INJECT: Pre endpoint operation
|
|
27
|
-
|
|
28
|
-
var tmpEmptyObject = pRequest.DAL.schemaFull.defaultObject;
|
|
29
|
-
|
|
30
|
-
// INJECT: After the empty object is grabbed, let the user alter it
|
|
31
|
-
|
|
32
|
-
pRequest.CommonServices.log.info('Delivered new '+pRequest.DAL.scope, {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-New'}, pRequest);
|
|
33
|
-
pResponse.send(tmpEmptyObject);
|
|
34
|
-
return fNext();
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
module.exports = doAPINewEndpoint;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - Get the Record Schema
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Get the JSONSchema for a particular scope
|
|
11
|
-
*/
|
|
12
|
-
var doAPISchemaEndpoint = function(pRequest, pResponse, fNext)
|
|
13
|
-
{
|
|
14
|
-
// This state is the requirement for the UserRoleIndex value in the UserSession object... processed by default as >=
|
|
15
|
-
// The default here is that any authenticated user can use this endpoint.
|
|
16
|
-
pRequest.EndpointAuthorizationRequirement = pRequest.EndpointAuthorizationLevels.Schema;
|
|
17
|
-
|
|
18
|
-
// INJECT: Pre authorization (for instance to change the authorization level)
|
|
19
|
-
|
|
20
|
-
if (pRequest.CommonServices.authorizeEndpoint(pRequest, pResponse, fNext) === false)
|
|
21
|
-
{
|
|
22
|
-
// If this endpoint fails, it's sent an error automatically.
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// INJECT: Pre endpoint operation
|
|
27
|
-
|
|
28
|
-
var tmpSchema = pRequest.DAL.jsonSchema;
|
|
29
|
-
|
|
30
|
-
// INJECT: After the schema is grabbed, let the user alter it
|
|
31
|
-
|
|
32
|
-
pRequest.CommonServices.log.info('Delivered a JSON schema for '+pRequest.DAL.scope, {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-Schema'}, pRequest);
|
|
33
|
-
pResponse.send(tmpSchema);
|
|
34
|
-
return fNext();
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
module.exports = doAPISchemaEndpoint;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - Validate a Record
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Validate a record using the Meadow DAL object
|
|
11
|
-
*/
|
|
12
|
-
var doAPIValidateEndpoint = function(pRequest, pResponse, fNext)
|
|
13
|
-
{
|
|
14
|
-
// This state is the requirement for the UserRoleIndex value in the UserSession object... processed by default as >=
|
|
15
|
-
// The default here is that any authenticated user can use this endpoint.
|
|
16
|
-
pRequest.EndpointAuthorizationRequirement = pRequest.EndpointAuthorizationLevels.New;
|
|
17
|
-
|
|
18
|
-
// INJECT: Pre authorization (for instance to change the authorization level)
|
|
19
|
-
|
|
20
|
-
if (pRequest.CommonServices.authorizeEndpoint(pRequest, pResponse, fNext) === false)
|
|
21
|
-
{
|
|
22
|
-
// If this endpoint fails, it's sent an error automatically.
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (typeof(pRequest.body) !== 'object')
|
|
27
|
-
{
|
|
28
|
-
return pRequest.CommonServices.sendError('Record validate failure - a valid JSON object is required.', pRequest, pResponse, fNext);
|
|
29
|
-
}
|
|
30
|
-
var tmpRecord = pRequest.body;
|
|
31
|
-
|
|
32
|
-
// INJECT: Pre endpoint operation
|
|
33
|
-
|
|
34
|
-
var tmpValid = pRequest.DAL.schemaFull.validateObject(tmpRecord);
|
|
35
|
-
|
|
36
|
-
// INJECT: After the record is validated, let the API user alter the resultant
|
|
37
|
-
|
|
38
|
-
pRequest.CommonServices.log.info('Delivered validation for '+pRequest.DAL.scope+': '+tmpValid, {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-Validate'}, pRequest);
|
|
39
|
-
pResponse.send(tmpValid);
|
|
40
|
-
return fNext();
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
module.exports = doAPIValidateEndpoint;
|