meadow-endpoints 3.0.7 → 4.0.3
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_LUXURYCode +1 -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 +27 -15
- 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/Meadow-Endpoints-Browser-Shim.js +14 -0
- package/source/Meadow-Endpoints.js +176 -565
- 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 +53 -0
- package/source/endpoints/upsert/Meadow-Endpoint-Upsert.js +58 -0
- package/source/endpoints/upsert/Meadow-Operation-Upsert.js +132 -0
- package/test/MeadowEndpoints_basic_tests.js +50 -2408
- 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-Undelete.js +0 -161
- 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,161 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - Undelete a Record
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Undelete a record using the Meadow DAL object
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
var libAsync = require('async');
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
var doAPIUndeleteEndpoint = function(pRequest, pResponse, fNext)
|
|
17
|
-
{
|
|
18
|
-
// This state is the requirement for the UserRoleIndex value in the UserSession object... processed by default as >=
|
|
19
|
-
// The default here is that any authenticated user can use this endpoint.
|
|
20
|
-
pRequest.EndpointAuthorizationRequirement = pRequest.EndpointAuthorizationLevels.Undelete;
|
|
21
|
-
|
|
22
|
-
// INJECT: Pre authorization (for instance to change the authorization level)
|
|
23
|
-
|
|
24
|
-
if (pRequest.CommonServices.authorizeEndpoint(pRequest, pResponse, fNext) === false)
|
|
25
|
-
{
|
|
26
|
-
// If this endpoint fails, it's sent an error automatically.
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// INJECT: Pre endpoint operation
|
|
31
|
-
|
|
32
|
-
var tmpIDRecord = 0;
|
|
33
|
-
if (typeof(pRequest.params.IDRecord) === 'string')
|
|
34
|
-
{
|
|
35
|
-
tmpIDRecord = pRequest.params.IDRecord;
|
|
36
|
-
}
|
|
37
|
-
else if (typeof(pRequest.body[pRequest.DAL.defaultIdentifier]) === 'number')
|
|
38
|
-
{
|
|
39
|
-
tmpIDRecord = pRequest.body[pRequest.DAL.defaultIdentifier];
|
|
40
|
-
}
|
|
41
|
-
else if (typeof(pRequest.body[pRequest.DAL.defaultIdentifier]) === 'string')
|
|
42
|
-
{
|
|
43
|
-
tmpIDRecord = pRequest.body[pRequest.DAL.defaultIdentifier];
|
|
44
|
-
}
|
|
45
|
-
// Although the undelete request does allow multiple undeletes, we require an identifier.
|
|
46
|
-
// TODO: Decide if we want to keep this pattern similar to Delete, or, if we want to change it to allow bulk undeletes.
|
|
47
|
-
if (tmpIDRecord < 1)
|
|
48
|
-
{
|
|
49
|
-
return pRequest.CommonServices.sendError('Record undelete failure - a valid record ID is required in the passed-in record.', pRequest, pResponse, fNext);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
var tmpRecordCount = {};
|
|
53
|
-
var tmpQuery;
|
|
54
|
-
|
|
55
|
-
libAsync.waterfall(
|
|
56
|
-
[
|
|
57
|
-
function(fStageComplete)
|
|
58
|
-
{
|
|
59
|
-
tmpQuery = pRequest.DAL.query;
|
|
60
|
-
|
|
61
|
-
// INJECT: Query configuration and population
|
|
62
|
-
var tmpSchema = pRequest.DAL.schema;
|
|
63
|
-
var tmpHasDeletedBit = false;
|
|
64
|
-
for (let i = 0; i < tmpSchema.length; i++)
|
|
65
|
-
{
|
|
66
|
-
if (tmpSchema[i].Type == 'Deleted')
|
|
67
|
-
{
|
|
68
|
-
// There is a deleted bit on the record!
|
|
69
|
-
tmpHasDeletedBit = true;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (!tmpHasDeletedBit)
|
|
74
|
-
{
|
|
75
|
-
return fStageComplete("NO_DELETED_BIT");
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return fStageComplete();
|
|
80
|
-
},
|
|
81
|
-
function(fStageComplete)
|
|
82
|
-
{
|
|
83
|
-
// Now see if the record, with this identifier, for this user, has the deleted bit set to 1
|
|
84
|
-
tmpQuery.addFilter(pRequest.DAL.defaultIdentifier, tmpIDRecord);
|
|
85
|
-
tmpQuery.addFilter('Deleted', 1);
|
|
86
|
-
tmpQuery.setIDUser(pRequest.UserSession.UserID);
|
|
87
|
-
|
|
88
|
-
return fStageComplete();
|
|
89
|
-
},
|
|
90
|
-
function(fStageComplete)
|
|
91
|
-
{
|
|
92
|
-
// Load the record so we can do security checks on it
|
|
93
|
-
pRequest.DAL.doRead(tmpQuery,
|
|
94
|
-
function(pError, pQuery, pRecord)
|
|
95
|
-
{
|
|
96
|
-
if (!pRecord)
|
|
97
|
-
{
|
|
98
|
-
tmpRecordCount = {Count:0};
|
|
99
|
-
return fStageComplete("NO_UNDELETABLE_RECORD_FOUND");
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
pRequest.Record = pRecord;
|
|
103
|
-
|
|
104
|
-
return fStageComplete();
|
|
105
|
-
});
|
|
106
|
-
},
|
|
107
|
-
function(fStageComplete)
|
|
108
|
-
{
|
|
109
|
-
pRequest.Authorizers.authorizeRequest('Undelete', pRequest, fStageComplete);
|
|
110
|
-
},
|
|
111
|
-
function(fStageComplete)
|
|
112
|
-
{
|
|
113
|
-
// INJECT: Once we've check the authorizer and are ready to Undelete, invoke an injected behavior before we execute the actuall delete operation
|
|
114
|
-
return pRequest.BehaviorModifications.runBehavior('Undelete-PreOperation', pRequest, fStageComplete);
|
|
115
|
-
},
|
|
116
|
-
function(fStageComplete)
|
|
117
|
-
{
|
|
118
|
-
// INJECT: Record modification before delete
|
|
119
|
-
|
|
120
|
-
if (pRequest.MeadowAuthorization)
|
|
121
|
-
{
|
|
122
|
-
return fStageComplete(false);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// It looks like this record was not authorized. Send an error.
|
|
126
|
-
return fStageComplete({Code:405,Message:'UNAUTHORIZED ACCESS IS NOT ALLOWED'});
|
|
127
|
-
},
|
|
128
|
-
function(fStageComplete)
|
|
129
|
-
{
|
|
130
|
-
// Do the delete
|
|
131
|
-
pRequest.DAL.doUndelete(tmpQuery,
|
|
132
|
-
function(pError, pQuery, pCount)
|
|
133
|
-
{
|
|
134
|
-
// It returns the number of rows deleted
|
|
135
|
-
tmpRecordCount = {Count:pCount};
|
|
136
|
-
|
|
137
|
-
return fStageComplete(pError);
|
|
138
|
-
});
|
|
139
|
-
},
|
|
140
|
-
function(fStageComplete)
|
|
141
|
-
{
|
|
142
|
-
// INJECT: After the delete count is grabbed, let the user alter the response content
|
|
143
|
-
return pRequest.BehaviorModifications.runBehavior('Undelete-PostOperation', pRequest, fStageComplete);
|
|
144
|
-
}
|
|
145
|
-
], function(pError)
|
|
146
|
-
{
|
|
147
|
-
if (pError &&
|
|
148
|
-
pError !== "NO_RECORD_FOUND")
|
|
149
|
-
{
|
|
150
|
-
return pRequest.CommonServices.sendCodedError('Error undeleting a record.', pError, pRequest, pResponse, fNext);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
pRequest.CommonServices.log.info('Undeleted '+tmpRecordCount.Count+' records with ID '+tmpIDRecord+'.', {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-Undelete'}, pRequest);
|
|
154
|
-
pResponse.send(tmpRecordCount);
|
|
155
|
-
|
|
156
|
-
return fNext();
|
|
157
|
-
}
|
|
158
|
-
);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
module.exports = doAPIUndeleteEndpoint;
|
|
@@ -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;
|