meadow-endpoints 3.0.7 → 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_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/Meadow-Endpoints-Browser-Shim.js +14 -0
- package/source/Meadow-Endpoints.js +176 -565
- 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 -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,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - Count a Record filtered by a single value
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
var libAsync = require('async');
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Count a record using the Meadow DAL object
|
|
14
|
-
*/
|
|
15
|
-
var doAPICountByEndpoint = function(pRequest, pResponse, fNext)
|
|
16
|
-
{
|
|
17
|
-
// This state is the requirement for the UserRoleIndex value in the UserSession object... processed by default as >=
|
|
18
|
-
// The default here is that any authenticated user can use this endpoint.
|
|
19
|
-
pRequest.EndpointAuthorizationRequirement = pRequest.EndpointAuthorizationLevels.Count;
|
|
20
|
-
|
|
21
|
-
// INJECT: Pre authorization (for instance to change the authorization level)
|
|
22
|
-
|
|
23
|
-
if (pRequest.CommonServices.authorizeEndpoint(pRequest, pResponse, fNext) === false)
|
|
24
|
-
{
|
|
25
|
-
// If this endpoint fails, it's sent an error automatically.
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
libAsync.waterfall(
|
|
30
|
-
[
|
|
31
|
-
// 1. Create the query
|
|
32
|
-
function (fStageComplete)
|
|
33
|
-
{
|
|
34
|
-
pRequest.Query = pRequest.DAL.query;
|
|
35
|
-
|
|
36
|
-
var tmpByField = pRequest.params.ByField;
|
|
37
|
-
var tmpByValue = pRequest.formattedParams.ByValue;
|
|
38
|
-
// TODO: Validate theat the ByField exists in the current database
|
|
39
|
-
|
|
40
|
-
if (tmpByValue.constructor === Array)
|
|
41
|
-
{
|
|
42
|
-
pRequest.Query.addFilter(tmpByField, tmpByValue, 'IN', 'AND', 'RequestByField');
|
|
43
|
-
}
|
|
44
|
-
else
|
|
45
|
-
{
|
|
46
|
-
// The count tries to match the Reads, since they are called together.
|
|
47
|
-
pRequest.Query.addFilter(tmpByField, tmpByValue, '=', 'AND', 'RequestByField');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return fStageComplete(false);
|
|
51
|
-
},
|
|
52
|
-
// 2: Check if there is an authorizer set for this endpoint and user role combination, and authorize based on that
|
|
53
|
-
function (fStageComplete)
|
|
54
|
-
{
|
|
55
|
-
pRequest.Authorizers.authorizeRequest('CountBy', pRequest, fStageComplete);
|
|
56
|
-
},
|
|
57
|
-
// 3. INJECT: Query configuration
|
|
58
|
-
function (fStageComplete)
|
|
59
|
-
{
|
|
60
|
-
pRequest.BehaviorModifications.runBehavior('Reads-QueryConfiguration', pRequest, fStageComplete);
|
|
61
|
-
},
|
|
62
|
-
// 4: Check if authorization denies security access to the record
|
|
63
|
-
function (fStageComplete)
|
|
64
|
-
{
|
|
65
|
-
if (pRequest.MeadowAuthorization)
|
|
66
|
-
{
|
|
67
|
-
// This will complete the waterfall operation
|
|
68
|
-
return fStageComplete(false);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// It looks like this record was not authorized. Send an error.
|
|
72
|
-
return fStageComplete({Code:405,Message:'UNAUTHORIZED ACCESS IS NOT ALLOWED'});
|
|
73
|
-
},
|
|
74
|
-
// 5: Do the count
|
|
75
|
-
function (fStageComplete)
|
|
76
|
-
{
|
|
77
|
-
pRequest.DAL.doCount(pRequest.Query,
|
|
78
|
-
function(pError, pQuery, pCount)
|
|
79
|
-
{
|
|
80
|
-
pRequest.Result = {Count:pCount};
|
|
81
|
-
|
|
82
|
-
return fStageComplete(pError);
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
],
|
|
86
|
-
function(pError)
|
|
87
|
-
{
|
|
88
|
-
if (pError)
|
|
89
|
-
{
|
|
90
|
-
return pRequest.CommonServices.sendCodedError('Error retreiving a count.', pError, pRequest, pResponse, fNext);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
pRequest.CommonServices.log.info('Delivered recordset count of '+pRequest.Result.Count+'.', {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-CountBy'}, pRequest);
|
|
94
|
-
pResponse.send(pRequest.Result);
|
|
95
|
-
|
|
96
|
-
return fNext();
|
|
97
|
-
}
|
|
98
|
-
);
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
module.exports = doAPICountByEndpoint;
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - Create a Record
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Create a record using the Meadow DAL object
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
var libAsync = require('async');
|
|
14
|
-
|
|
15
|
-
var doCreate = require('./Meadow-Operation-Create.js');
|
|
16
|
-
|
|
17
|
-
var doAPICreateEndpoint = 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.Create;
|
|
22
|
-
|
|
23
|
-
if (pRequest.CommonServices.authorizeEndpoint(pRequest, pResponse, fNext) === false)
|
|
24
|
-
{
|
|
25
|
-
// If this endpoint fails, it's sent an error automatically.
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Configure the request for the generic create operation
|
|
30
|
-
pRequest.CreatedRecords = [];
|
|
31
|
-
pRequest.MeadowOperation = 'Create';
|
|
32
|
-
|
|
33
|
-
libAsync.waterfall(
|
|
34
|
-
[
|
|
35
|
-
function(fStageComplete)
|
|
36
|
-
{
|
|
37
|
-
//1. Validate request body to ensure it is a valid record
|
|
38
|
-
if (typeof(pRequest.body) !== 'object')
|
|
39
|
-
{
|
|
40
|
-
return pRequest.CommonServices.sendError('Record create failure - a valid record is required.', pRequest, pResponse, fNext);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return fStageComplete();
|
|
44
|
-
},
|
|
45
|
-
function(fStageComplete)
|
|
46
|
-
{
|
|
47
|
-
pRequest.Response = pResponse;
|
|
48
|
-
pRequest.BehaviorModifications.runBehavior('Create-PreRequest', pRequest, fStageComplete);
|
|
49
|
-
},
|
|
50
|
-
function(fStageComplete)
|
|
51
|
-
{
|
|
52
|
-
//4. Do the create operation
|
|
53
|
-
doCreate(pRequest.body, pRequest, pResponse, fStageComplete);
|
|
54
|
-
},
|
|
55
|
-
function(fStageComplete)
|
|
56
|
-
{
|
|
57
|
-
//5. Respond with the new record
|
|
58
|
-
|
|
59
|
-
// If there was an error, respond with that instead
|
|
60
|
-
if (pRequest.RecordCreateError)
|
|
61
|
-
return fStageComplete(pRequest.RecordCreateErrorMessage);
|
|
62
|
-
|
|
63
|
-
pResponse.send(pRequest.Record);
|
|
64
|
-
return fStageComplete();
|
|
65
|
-
}
|
|
66
|
-
], function(pError)
|
|
67
|
-
{
|
|
68
|
-
if (pError && pError!='ABORT') //TODO: should have an abort token/const
|
|
69
|
-
{
|
|
70
|
-
return pRequest.CommonServices.sendCodedError('Error creating a record.', pError, pRequest, pResponse, fNext);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return fNext();
|
|
74
|
-
});
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
module.exports = doAPICreateEndpoint;
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - Delete a Record
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Delete a record using the Meadow DAL object
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
var libAsync = require('async');
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
var doAPIDeleteEndpoint = 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.Delete;
|
|
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 delete request does allow multiple deletes, we require an identifier.
|
|
46
|
-
if (tmpIDRecord < 1)
|
|
47
|
-
{
|
|
48
|
-
return pRequest.CommonServices.sendError('Record delete failure - a valid record ID is required in the passed-in record.', pRequest, pResponse, fNext);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
var tmpRecordCount = {};
|
|
52
|
-
var tmpQuery;
|
|
53
|
-
|
|
54
|
-
libAsync.waterfall(
|
|
55
|
-
[
|
|
56
|
-
function(fStageComplete)
|
|
57
|
-
{
|
|
58
|
-
tmpQuery = pRequest.DAL.query;
|
|
59
|
-
|
|
60
|
-
// INJECT: Query configuration and population
|
|
61
|
-
|
|
62
|
-
// This is not overloadable.`
|
|
63
|
-
tmpQuery.addFilter(pRequest.DAL.defaultIdentifier, tmpIDRecord);
|
|
64
|
-
tmpQuery.setIDUser(pRequest.UserSession.UserID);
|
|
65
|
-
|
|
66
|
-
return fStageComplete();
|
|
67
|
-
},
|
|
68
|
-
function(fStageComplete)
|
|
69
|
-
{
|
|
70
|
-
// Load the record so we can do security checks on it
|
|
71
|
-
pRequest.DAL.doRead(tmpQuery,
|
|
72
|
-
function(pError, pQuery, pRecord)
|
|
73
|
-
{
|
|
74
|
-
if (!pRecord)
|
|
75
|
-
{
|
|
76
|
-
tmpRecordCount = {Count:0};
|
|
77
|
-
return fStageComplete("NO_RECORD_FOUND");
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
pRequest.Record = pRecord;
|
|
81
|
-
|
|
82
|
-
return fStageComplete();
|
|
83
|
-
});
|
|
84
|
-
},
|
|
85
|
-
function(fStageComplete)
|
|
86
|
-
{
|
|
87
|
-
pRequest.Authorizers.authorizeRequest('Delete', pRequest, fStageComplete);
|
|
88
|
-
},
|
|
89
|
-
function(fStageComplete)
|
|
90
|
-
{
|
|
91
|
-
// INJECT: Once we've check the authorizer and are ready to Delete, invoke an injected behavior before we execute the actuall delete operation
|
|
92
|
-
return pRequest.BehaviorModifications.runBehavior('Delete-PreOperation', pRequest, fStageComplete);
|
|
93
|
-
},
|
|
94
|
-
function(fStageComplete)
|
|
95
|
-
{
|
|
96
|
-
// INJECT: Record modification before delete
|
|
97
|
-
|
|
98
|
-
if (pRequest.MeadowAuthorization)
|
|
99
|
-
{
|
|
100
|
-
return fStageComplete(false);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// It looks like this record was not authorized. Send an error.
|
|
104
|
-
return fStageComplete({Code:405,Message:'UNAUTHORIZED ACCESS IS NOT ALLOWED'});
|
|
105
|
-
},
|
|
106
|
-
function(fStageComplete)
|
|
107
|
-
{
|
|
108
|
-
// Do the delete
|
|
109
|
-
pRequest.DAL.doDelete(tmpQuery,
|
|
110
|
-
function(pError, pQuery, pCount)
|
|
111
|
-
{
|
|
112
|
-
// It returns the number of rows deleted
|
|
113
|
-
tmpRecordCount = {Count:pCount};
|
|
114
|
-
|
|
115
|
-
return fStageComplete(pError);
|
|
116
|
-
});
|
|
117
|
-
},
|
|
118
|
-
function(fStageComplete)
|
|
119
|
-
{
|
|
120
|
-
// INJECT: After the delete count is grabbed, let the user alter the response content
|
|
121
|
-
return pRequest.BehaviorModifications.runBehavior('Delete-PostOperation', pRequest, fStageComplete);
|
|
122
|
-
}
|
|
123
|
-
], function(pError)
|
|
124
|
-
{
|
|
125
|
-
if (pError &&
|
|
126
|
-
pError !== "NO_RECORD_FOUND")
|
|
127
|
-
{
|
|
128
|
-
return pRequest.CommonServices.sendCodedError('Error deleting a record.', pError, pRequest, pResponse, fNext);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
pRequest.CommonServices.log.info('Deleted '+tmpRecordCount.Count+' records with ID '+tmpIDRecord+'.', {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-Delete'}, pRequest);
|
|
132
|
-
pResponse.send(tmpRecordCount);
|
|
133
|
-
|
|
134
|
-
return fNext();
|
|
135
|
-
}
|
|
136
|
-
);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
module.exports = doAPIDeleteEndpoint;
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - Read a Record
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
var libAsync = require('async');
|
|
10
|
-
/**
|
|
11
|
-
* Get a specific record from a DAL.
|
|
12
|
-
*/
|
|
13
|
-
var doAPIReadEndpoint = function(pRequest, pResponse, fNext)
|
|
14
|
-
{
|
|
15
|
-
// This state is the requirement for the UserRoleIndex value in the UserSession object... processed by default as >=
|
|
16
|
-
// The default here is that any authenticated user can use this endpoint.
|
|
17
|
-
pRequest.EndpointAuthorizationRequirement = pRequest.EndpointAuthorizationLevels.Read;
|
|
18
|
-
|
|
19
|
-
if (pRequest.CommonServices.authorizeEndpoint(pRequest, pResponse, fNext) === false)
|
|
20
|
-
{
|
|
21
|
-
// If this endpoint fails, it's sent an error automatically.
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
libAsync.waterfall(
|
|
26
|
-
[
|
|
27
|
-
// 1. Create the query
|
|
28
|
-
function (fStageComplete)
|
|
29
|
-
{
|
|
30
|
-
pRequest.Query = pRequest.DAL.query;
|
|
31
|
-
fStageComplete(false);
|
|
32
|
-
},
|
|
33
|
-
// 2. Set the query up with the record ID
|
|
34
|
-
function (fStageComplete)
|
|
35
|
-
{
|
|
36
|
-
if (!pRequest.params.IDRecord &&
|
|
37
|
-
pRequest.params.GUIDRecord)
|
|
38
|
-
{
|
|
39
|
-
// We use a custon name for this (RequestDefaultIdentifier) in case there is a query with a dot in the default identifier.
|
|
40
|
-
pRequest.Query.addFilter(pRequest.DAL.defaultGUIdentifier, pRequest.params.GUIDRecord, '=', 'AND', 'RequestDefaultIdentifier');
|
|
41
|
-
}
|
|
42
|
-
else
|
|
43
|
-
{
|
|
44
|
-
var tmpIDRecord = pRequest.params.IDRecord;
|
|
45
|
-
// We use a custon name for this (RequestDefaultIdentifier) in case there is a query with a dot in the default identifier.
|
|
46
|
-
pRequest.Query.addFilter(pRequest.DAL.defaultIdentifier, tmpIDRecord, '=', 'AND', 'RequestDefaultIdentifier');
|
|
47
|
-
}
|
|
48
|
-
return fStageComplete(false);
|
|
49
|
-
},
|
|
50
|
-
// 3. INJECT: Query configuration
|
|
51
|
-
function (fStageComplete)
|
|
52
|
-
{
|
|
53
|
-
pRequest.BehaviorModifications.runBehavior('Read-QueryConfiguration', pRequest, fStageComplete);
|
|
54
|
-
},
|
|
55
|
-
// 4. Execute the query
|
|
56
|
-
function (fStageComplete)
|
|
57
|
-
{
|
|
58
|
-
pRequest.DAL.doRead(pRequest.Query, fStageComplete);
|
|
59
|
-
},
|
|
60
|
-
// 5. Post processing of the records
|
|
61
|
-
function (pQuery, pRecord, fStageComplete)
|
|
62
|
-
{
|
|
63
|
-
if (!pRecord)
|
|
64
|
-
{
|
|
65
|
-
pRequest.CommonServices.log.info('Record not found', {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-Read'}, pRequest);
|
|
66
|
-
return fStageComplete('Record not found');
|
|
67
|
-
}
|
|
68
|
-
pRequest.Record = pRecord;
|
|
69
|
-
fStageComplete(false);
|
|
70
|
-
},
|
|
71
|
-
// 5.5: Check if there is an authorizer set for this endpoint and user role combination, and authorize based on that
|
|
72
|
-
function (fStageComplete)
|
|
73
|
-
{
|
|
74
|
-
pRequest.Authorizers.authorizeRequest('Read', pRequest, fStageComplete);
|
|
75
|
-
},
|
|
76
|
-
// 6. INJECT: Post process the record, tacking on or altering anything we want to.
|
|
77
|
-
function (fStageComplete)
|
|
78
|
-
{
|
|
79
|
-
pRequest.BehaviorModifications.runBehavior('Read-PostOperation', pRequest, fStageComplete);
|
|
80
|
-
},
|
|
81
|
-
// 6.5: Check if authorization or post processing denied security access to the record
|
|
82
|
-
function (fStageComplete)
|
|
83
|
-
{
|
|
84
|
-
if (pRequest.MeadowAuthorization)
|
|
85
|
-
{
|
|
86
|
-
// This will complete the waterfall operation
|
|
87
|
-
return fStageComplete(false);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// It looks like this record was not authorized. Send an error.
|
|
91
|
-
return fStageComplete({Code:405,Message:'UNAUTHORIZED ACCESS IS NOT ALLOWED'});
|
|
92
|
-
},
|
|
93
|
-
],
|
|
94
|
-
// 3. Return the results to the user
|
|
95
|
-
function(pError)
|
|
96
|
-
{
|
|
97
|
-
if (pError)
|
|
98
|
-
{
|
|
99
|
-
return pRequest.CommonServices.sendCodedError('Error retreiving a record.', pError, pRequest, pResponse, fNext);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
pRequest.CommonServices.log.info('Read a record with ID '+pRequest.params.IDRecord+'.', {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-Read'}, pRequest);
|
|
103
|
-
pResponse.send(pRequest.Record);
|
|
104
|
-
return fNext();
|
|
105
|
-
}
|
|
106
|
-
);
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
module.exports = doAPIReadEndpoint;
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Meadow Endpoint - Read a list of Records with a specified set of columns, distinct by those columns.
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Alex Decker <alex.decker@headlight.com>
|
|
7
|
-
* @module Meadow
|
|
8
|
-
*/
|
|
9
|
-
const libAsync = require('async');
|
|
10
|
-
const meadowFilterParser = require('meadow-filter').parse;
|
|
11
|
-
const marshalDistinctList = require('./Meadow-Marshal-DistinctList.js');
|
|
12
|
-
const streamRecordsToResponse = require('./Meadow-StreamRecordArray');
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Get a set of records from a DAL.
|
|
16
|
-
*/
|
|
17
|
-
const doAPIReadDistinctEndpoint = 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.Reads;
|
|
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
|
-
let tmpDistinctColumns;
|
|
32
|
-
libAsync.waterfall(
|
|
33
|
-
[
|
|
34
|
-
// 1a. Get the records
|
|
35
|
-
function (fStageComplete)
|
|
36
|
-
{
|
|
37
|
-
pRequest.Query = pRequest.DAL.query.setDistinct(true);
|
|
38
|
-
// TODO: Limit the query to the columns we need for the templated expression
|
|
39
|
-
|
|
40
|
-
let tmpCap = false;
|
|
41
|
-
let tmpBegin = false;
|
|
42
|
-
if (typeof(pRequest.params.Begin) === 'string' ||
|
|
43
|
-
typeof(pRequest.params.Begin) === 'number')
|
|
44
|
-
{
|
|
45
|
-
tmpBegin = parseInt(pRequest.params.Begin, 10);
|
|
46
|
-
}
|
|
47
|
-
if (typeof(pRequest.params.Cap) === 'string' ||
|
|
48
|
-
typeof(pRequest.params.Cap) === 'number')
|
|
49
|
-
{
|
|
50
|
-
tmpCap = parseInt(pRequest.params.Cap, 10);
|
|
51
|
-
}
|
|
52
|
-
else
|
|
53
|
-
{
|
|
54
|
-
//maximum number of records to return by default on Read queries. Override via "MeadowDefaultMaxCap" fable setting.
|
|
55
|
-
tmpCap = pRequest.DEFAULT_MAX_CAP;
|
|
56
|
-
}
|
|
57
|
-
pRequest.Query.setCap(tmpCap).setBegin(tmpBegin);
|
|
58
|
-
if (typeof(pRequest.params.Filter) === 'string')
|
|
59
|
-
{
|
|
60
|
-
// If a filter has been passed in, parse it and add the values to the query.
|
|
61
|
-
meadowFilterParser(pRequest.params.Filter, pRequest.Query);
|
|
62
|
-
}
|
|
63
|
-
else if (pRequest.params.Filter)
|
|
64
|
-
{
|
|
65
|
-
pRequest.Query.setFilter(pRequest.params.Filter);
|
|
66
|
-
}
|
|
67
|
-
if (typeof(pRequest.params.Columns) === 'string')
|
|
68
|
-
{
|
|
69
|
-
tmpDistinctColumns = pRequest.params.Columns.split(',');
|
|
70
|
-
if (!tmpDistinctColumns)
|
|
71
|
-
{
|
|
72
|
-
return fStageComplete({Code:400,Message:'Columns to distinct on must be provided.'});
|
|
73
|
-
}
|
|
74
|
-
pRequest.Query.setDataElements(tmpDistinctColumns);
|
|
75
|
-
}
|
|
76
|
-
fStageComplete(false);
|
|
77
|
-
},
|
|
78
|
-
// 1b. INJECT: Query configuration
|
|
79
|
-
function (fStageComplete)
|
|
80
|
-
{
|
|
81
|
-
pRequest.BehaviorModifications.runBehavior('Reads-QueryConfiguration', pRequest, fStageComplete);
|
|
82
|
-
},
|
|
83
|
-
// 1b2. INJECT: Query pre-authorization behavior (ex. if authorizer needs fields to be included, it can add them)
|
|
84
|
-
function (fStageComplete)
|
|
85
|
-
{
|
|
86
|
-
pRequest.BehaviorModifications.runBehavior('Reads-PreAuth', pRequest, fStageComplete);
|
|
87
|
-
},
|
|
88
|
-
// 1c. Do the record read
|
|
89
|
-
function (fStageComplete)
|
|
90
|
-
{
|
|
91
|
-
pRequest.DAL.doReads(pRequest.Query, fStageComplete);
|
|
92
|
-
},
|
|
93
|
-
// 2. Post processing of the records
|
|
94
|
-
function (pQuery, pRecords, fStageComplete)
|
|
95
|
-
{
|
|
96
|
-
if (pRecords.length < 1)
|
|
97
|
-
{
|
|
98
|
-
pRecords = [];
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
pRequest.Records = pRecords;
|
|
102
|
-
|
|
103
|
-
// Complete the waterfall operation
|
|
104
|
-
fStageComplete(false);
|
|
105
|
-
},
|
|
106
|
-
// 2.5: Check if there is an authorizer set for this endpoint and user role combination, and authorize based on that
|
|
107
|
-
function (fStageComplete)
|
|
108
|
-
{
|
|
109
|
-
// shared permission with reads
|
|
110
|
-
pRequest.Authorizers.authorizeRequest('Reads', pRequest, fStageComplete);
|
|
111
|
-
},
|
|
112
|
-
// 2.6: Check if authorization or post processing denied security access to the record
|
|
113
|
-
function (fStageComplete)
|
|
114
|
-
{
|
|
115
|
-
if (pRequest.MeadowAuthorization)
|
|
116
|
-
{
|
|
117
|
-
return fStageComplete(false);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// It looks like this record was not authorized. Send an error.
|
|
121
|
-
return fStageComplete({Code:405,Message:'UNAUTHORIZED ACCESS IS NOT ALLOWED'});
|
|
122
|
-
},
|
|
123
|
-
// 3. Marshalling of records into the hash list, using underscore templates.
|
|
124
|
-
function (fStageComplete)
|
|
125
|
-
{
|
|
126
|
-
fStageComplete(false, marshalDistinctList(pRequest.Records, pRequest, tmpDistinctColumns));
|
|
127
|
-
}
|
|
128
|
-
],
|
|
129
|
-
// 3. Return the results to the user
|
|
130
|
-
function(pError, pResultRecords)
|
|
131
|
-
{
|
|
132
|
-
// Remove 'Records' object from pRequest, instead return template results (pResultRecords) for the records
|
|
133
|
-
delete pRequest['Records'];
|
|
134
|
-
|
|
135
|
-
if (pError)
|
|
136
|
-
{
|
|
137
|
-
return pRequest.CommonServices.sendCodedError('Error retreiving a recordset.', pError, pRequest, pResponse, fNext);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
pRequest.CommonServices.log.info('Read a recordset lite list with '+pResultRecords.length+' results.', {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:pRequest.DAL.scope+'-ReadDistinct'}, pRequest);
|
|
141
|
-
return streamRecordsToResponse(pResponse, pResultRecords, fNext);
|
|
142
|
-
}
|
|
143
|
-
);
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
module.exports = doAPIReadDistinctEndpoint;
|