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
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Harness
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
*
|
|
6
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
////////// Code can go here for easy debugging //////////
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
const tmpApplicationSettings = (
|
|
15
|
+
{
|
|
16
|
+
Product: 'MockEndpointServer',
|
|
17
|
+
ProductVersion: '0.0.0',
|
|
18
|
+
|
|
19
|
+
"UnauthorizedRequestDelay": 100,
|
|
20
|
+
|
|
21
|
+
APIServerPort: 8086,
|
|
22
|
+
|
|
23
|
+
MySQL:
|
|
24
|
+
{
|
|
25
|
+
// This is queued up for Travis defaults.
|
|
26
|
+
Server: "localhost",
|
|
27
|
+
Port: 3306,
|
|
28
|
+
User: "root",
|
|
29
|
+
Password: "123456789",
|
|
30
|
+
// Password: "",
|
|
31
|
+
Database: "FableTest",
|
|
32
|
+
ConnectionPoolLimit: 20
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Construct a fable.
|
|
37
|
+
const _Fable = new libFable(tmpApplicationSettings);
|
|
38
|
+
// Connect to SQL, put the connection in the magic location
|
|
39
|
+
_Fable.MeadowMySQLConnectionPool = libMySQL.createPool
|
|
40
|
+
(
|
|
41
|
+
{
|
|
42
|
+
connectionLimit: _Fable.settings.MySQL.ConnectionPoolLimit,
|
|
43
|
+
host: _Fable.settings.MySQL.Server,
|
|
44
|
+
port: _Fable.settings.MySQL.Port,
|
|
45
|
+
user: _Fable.settings.MySQL.User,
|
|
46
|
+
password: _Fable.settings.MySQL.Password,
|
|
47
|
+
database: _Fable.settings.MySQL.Database,
|
|
48
|
+
namedPlaceholders: true
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
// Load up a Meadow (pointing at the Animal database)
|
|
53
|
+
const _AnimalSchema = require('../test/Animal.json');
|
|
54
|
+
const _Meadow = libMeadow.new(_Fable, 'FableTest')
|
|
55
|
+
.setProvider('MySQL')
|
|
56
|
+
.setSchema(_AnimalSchema.Schema)
|
|
57
|
+
.setJsonSchema(_AnimalSchema.JsonSchema)
|
|
58
|
+
.setDefaultIdentifier(_AnimalSchema.DefaultIdentifier)
|
|
59
|
+
.setDefault(_AnimalSchema.DefaultObject);
|
|
60
|
+
|
|
61
|
+
// Instantiate the meadow endpoints with the DAL object constructed above
|
|
62
|
+
const _MeadowEndpoints = new libMeadowEndpoints(_Meadow);
|
|
63
|
+
|
|
64
|
+
// Instantiate the service server, using restify
|
|
65
|
+
const _Orator = new libOrator(_Fable, libOratorServiceServerRestify);
|
|
66
|
+
// Prepare the service server for mapping endpoints
|
|
67
|
+
_Orator.initializeServiceServer();
|
|
68
|
+
|
|
69
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Schema-PreOperation',
|
|
70
|
+
function (pRequest, pRequestState, fCallback)
|
|
71
|
+
{
|
|
72
|
+
this.log.info('I have access to state!', pRequestState);
|
|
73
|
+
return fCallback();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Schema-PostOperation',
|
|
77
|
+
function (pRequest, pRequestState, fCallback)
|
|
78
|
+
{
|
|
79
|
+
pRequestState.JSONSchema.PLOT = `GODZILLA WILL EAT YOUR SOUL!`;
|
|
80
|
+
this.log.info('I can also mutate state before sending!', pRequestState);
|
|
81
|
+
return fCallback();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Wire the endpoints up
|
|
85
|
+
_MeadowEndpoints.connectRoutes(_Orator.serviceServer);
|
|
86
|
+
|
|
87
|
+
// Now start the web server.
|
|
88
|
+
_Orator.startWebServer(_HarnessBehavior);
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Check that a user is logged in, if enabled
|
|
3
|
-
*
|
|
4
|
-
* @method getAuthenticator
|
|
5
|
-
*/
|
|
6
|
-
const getAuthenticator = (pAuthenticatorMode) =>
|
|
7
|
-
{
|
|
8
|
-
if (pAuthenticatorMode === 'Disabled')
|
|
9
|
-
{
|
|
10
|
-
return (pRequest, pResponse, fNext) =>
|
|
11
|
-
{
|
|
12
|
-
pRequest.EndpointAuthenticated = true;
|
|
13
|
-
fNext();
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
return (pRequest, pResponse, fNext) =>
|
|
17
|
-
{
|
|
18
|
-
if (!pRequest.UserSession.LoggedIn)
|
|
19
|
-
{
|
|
20
|
-
pRequest.EndpointAuthenticated = false;
|
|
21
|
-
}
|
|
22
|
-
else
|
|
23
|
-
{
|
|
24
|
-
pRequest.EndpointAuthenticated = true;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
fNext();
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
module.exports = getAuthenticator;
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Meadow Security Authorizor Collection
|
|
3
|
-
*
|
|
4
|
-
* Provide a set of security authorizers, and give the API consumer the ability to add to or modify them.
|
|
5
|
-
*
|
|
6
|
-
* @class MeadowAuthorizers
|
|
7
|
-
* @constructor
|
|
8
|
-
*/
|
|
9
|
-
var libUnderscore = require('underscore');
|
|
10
|
-
var libAsync = require('async');
|
|
11
|
-
|
|
12
|
-
var MeadowAuthorizers = function()
|
|
13
|
-
{
|
|
14
|
-
function createNew(pMeadow)
|
|
15
|
-
{
|
|
16
|
-
// If a valid fable object isn't passed in, return a constructor
|
|
17
|
-
if ((typeof(pMeadow) !== 'object') || !('fable' in pMeadow))
|
|
18
|
-
{
|
|
19
|
-
return {new: createNew};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const _AuthorizationMode = pMeadow.fable.settings.MeadowAuthorizationMode || 'Disabled';
|
|
23
|
-
|
|
24
|
-
// An object to hold modifications to specific authorizers.
|
|
25
|
-
var _AuthorizerFunctions = {};
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Set a specific authorizer.
|
|
30
|
-
*
|
|
31
|
-
* The anatomy of a authorizer function is as follows:
|
|
32
|
-
*
|
|
33
|
-
* var someAuthorizer = function(pRequest, fComplete)
|
|
34
|
-
* {
|
|
35
|
-
* // Do some stuff with pRequest...
|
|
36
|
-
* if (pRequest.UserSession.UserRoleIndex < 5)
|
|
37
|
-
* pRequest.MeadowAuthorization = pRequest.MeadowAuthorization && false;
|
|
38
|
-
*
|
|
39
|
-
* return fComplete(false);
|
|
40
|
-
* }
|
|
41
|
-
*
|
|
42
|
-
* It is important to note that the fComplete function expects false if no error, or a string message if there is one.
|
|
43
|
-
*/
|
|
44
|
-
var setAuthorizer = function(pAuthorizerHash, fAuthorizer)
|
|
45
|
-
{
|
|
46
|
-
_AuthorizerFunctions[pAuthorizerHash] = fAuthorizer;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Get a specific authorizer.
|
|
51
|
-
*/
|
|
52
|
-
var getAuthorizer = function(pAuthorizerHash)
|
|
53
|
-
{
|
|
54
|
-
return _AuthorizerFunctions[pAuthorizerHash];
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
if (_AuthorizationMode === 'SimpleOwnership')
|
|
58
|
-
{
|
|
59
|
-
// Map in the authorizers for simple ownership mode
|
|
60
|
-
setAuthorizer('Allow', require(__dirname+'/authorizers/Meadow-Authorizer-Allow.js'));
|
|
61
|
-
setAuthorizer('Deny', require(__dirname+'/authorizers/Meadow-Authorizer-Deny.js'));
|
|
62
|
-
setAuthorizer('Mine', require(__dirname+'/authorizers/Meadow-Authorizer-Mine.js'));
|
|
63
|
-
setAuthorizer('MyCustomer', require(__dirname+'/authorizers/Meadow-Authorizer-MyCustomer.js'));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* This method runs a authorizer at a specific hash, and returns true.
|
|
68
|
-
* Or it returns false if there was no authorizer there.
|
|
69
|
-
* Authorizers should expect their state to be in the pRequest object, per the example in setAuthorizer
|
|
70
|
-
*/
|
|
71
|
-
var authorize = function(pAuthorizerHash, pRequest, fComplete)
|
|
72
|
-
{
|
|
73
|
-
// Add the authorization value to the request object if it doesn't exist yet
|
|
74
|
-
if (!pRequest.hasOwnProperty('MeadowAuthorization'))
|
|
75
|
-
{
|
|
76
|
-
pRequest.MeadowAuthorization = true;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// authorize all behaviors if authorization is disabled
|
|
80
|
-
if (_AuthorizationMode === 'Disabled')
|
|
81
|
-
{
|
|
82
|
-
return fComplete();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
//FIXME: Get rid of this...
|
|
86
|
-
if (pRequest.Satchel &&
|
|
87
|
-
pRequest.Satchel.AuthorizeOverride)
|
|
88
|
-
return fComplete(false);
|
|
89
|
-
|
|
90
|
-
// Run an injected authorizer (if it exists)
|
|
91
|
-
if (_AuthorizerFunctions.hasOwnProperty(pAuthorizerHash))
|
|
92
|
-
{
|
|
93
|
-
if (!pRequest.Record &&
|
|
94
|
-
pRequest.Records)
|
|
95
|
-
{
|
|
96
|
-
// Run the authorizer for multiple records
|
|
97
|
-
|
|
98
|
-
libAsync.eachSeries(pRequest.Records, function(pRecord, fNext)
|
|
99
|
-
{
|
|
100
|
-
pRequest.Record = pRecord;
|
|
101
|
-
|
|
102
|
-
_AuthorizerFunctions[pAuthorizerHash](pRequest, function(err)
|
|
103
|
-
{
|
|
104
|
-
if (err)
|
|
105
|
-
return fNext({Error: err});
|
|
106
|
-
|
|
107
|
-
// If MeadowAuthorization fails, keep the state and pass it on
|
|
108
|
-
return fNext(!pRequest.MeadowAuthorization);
|
|
109
|
-
});
|
|
110
|
-
},
|
|
111
|
-
function(pCancelled)
|
|
112
|
-
{
|
|
113
|
-
delete pRequest['Record']; //remove this property as it should only contains 'Records'
|
|
114
|
-
|
|
115
|
-
if (pCancelled &&
|
|
116
|
-
pCancelled.Error)
|
|
117
|
-
{
|
|
118
|
-
return fComplete(pCancelled.Error);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return fComplete(false);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
else
|
|
125
|
-
{
|
|
126
|
-
// Run the authorizer for one record
|
|
127
|
-
return _AuthorizerFunctions[pAuthorizerHash](pRequest, fComplete);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
else
|
|
131
|
-
{
|
|
132
|
-
return fComplete(false);
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
// Try to execute any defined authorizers on the proper endpoint
|
|
138
|
-
var authorizeRequest = function(pRequestHash, pRequest, fComplete)
|
|
139
|
-
{
|
|
140
|
-
// Add the authorization value to the request object if it doesn't exist yet
|
|
141
|
-
if (!pRequest.hasOwnProperty('MeadowAuthorization'))
|
|
142
|
-
{
|
|
143
|
-
pRequest.MeadowAuthorization = true;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// authorize all behaviors if authorization is disabled
|
|
147
|
-
if (_AuthorizationMode === 'Disabled')
|
|
148
|
-
{
|
|
149
|
-
return fComplete();
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Attach authorizer hash in case the invoked authorizer needs the endpoint context
|
|
153
|
-
pRequest.EndpointHash = pRequestHash;
|
|
154
|
-
|
|
155
|
-
// See if there is an authorizer collection for the role of the user
|
|
156
|
-
var tmpRoleAuthorizer = pRequest.DAL.schemaFull.authorizer[pRequest.DAL.getRoleName(pRequest.UserSession.UserRoleIndex)];
|
|
157
|
-
if (!tmpRoleAuthorizer)
|
|
158
|
-
{
|
|
159
|
-
// Fallback to default definition, if present
|
|
160
|
-
tmpRoleAuthorizer = pRequest.DAL.schemaFull.authorizer['__DefaultAPISecurity'];
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Authorizing Endpoint
|
|
164
|
-
//console.log(pRequestHash + ' >>> '+pRequest.DAL.getRoleName(pRequest.UserSession.UserRoleIndex)+' - '+pRequest.UserSession.UserRoleIndex+' Authorization Configuration: '+JSON.stringify(tmpRoleAuthorizer));
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if ((typeof(tmpRoleAuthorizer) === 'object') && tmpRoleAuthorizer.hasOwnProperty(pRequestHash))
|
|
168
|
-
{
|
|
169
|
-
// Authorizing Endpoint
|
|
170
|
-
//console.log(' >>> Authorizing Endpoint: '+JSON.stringify(tmpRoleAuthorizer));
|
|
171
|
-
// If there is an authorizer collection in the DAL and it has this request hash as a property in it, execute the authorizer(s)
|
|
172
|
-
if (typeof(tmpRoleAuthorizer[pRequestHash]) === 'string')
|
|
173
|
-
{
|
|
174
|
-
// Execute the single authorizer
|
|
175
|
-
authorize(tmpRoleAuthorizer[pRequestHash], pRequest, fComplete);
|
|
176
|
-
}
|
|
177
|
-
else
|
|
178
|
-
{
|
|
179
|
-
// Execute every authorizer in the array
|
|
180
|
-
libAsync.eachSeries(tmpRoleAuthorizer[pRequestHash],
|
|
181
|
-
function(pAuthorizerHash, fCallback)
|
|
182
|
-
{
|
|
183
|
-
authorize(pAuthorizerHash, pRequest, fCallback);
|
|
184
|
-
},
|
|
185
|
-
fComplete);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
else
|
|
189
|
-
{
|
|
190
|
-
fComplete();
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Container Object for our Factory Pattern
|
|
197
|
-
*/
|
|
198
|
-
var tmpNewMeadowAuthorizer = (
|
|
199
|
-
{
|
|
200
|
-
setAuthorizer: setAuthorizer,
|
|
201
|
-
getAuthorizer: getAuthorizer,
|
|
202
|
-
authorize: authorize,
|
|
203
|
-
authorizeRequest: authorizeRequest,
|
|
204
|
-
|
|
205
|
-
new: createNew
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
return tmpNewMeadowAuthorizer;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return createNew();
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
module.exports = new MeadowAuthorizers();
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Meadow Behavior Modification Object
|
|
3
|
-
*
|
|
4
|
-
* Provide a sane mechanism for overloading or injecting behaviors into request endpoints.
|
|
5
|
-
*
|
|
6
|
-
* @class MeadowBehaviorModifications
|
|
7
|
-
* @constructor
|
|
8
|
-
*/
|
|
9
|
-
var libUnderscore = require('underscore');
|
|
10
|
-
|
|
11
|
-
var MeadowBehaviorModifications = function()
|
|
12
|
-
{
|
|
13
|
-
function createNew(pMeadow)
|
|
14
|
-
{
|
|
15
|
-
// If a valid fable object isn't passed in, return a constructor
|
|
16
|
-
if ((typeof(pMeadow) !== 'object') || !('fable' in pMeadow))
|
|
17
|
-
{
|
|
18
|
-
return {new: createNew};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
var libAsync = require('async');
|
|
22
|
-
|
|
23
|
-
// An object to hold modifications to specific behaviors.
|
|
24
|
-
var _BehaviorFunctions = {};
|
|
25
|
-
|
|
26
|
-
// A set of objects to hold the specific templates and their compiled functions
|
|
27
|
-
var _Templates = {};
|
|
28
|
-
var _TemplateFunctions = {};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Set a specific behavior.
|
|
33
|
-
*
|
|
34
|
-
* The anatomy of a behavior function is as follows:
|
|
35
|
-
*
|
|
36
|
-
* var someBehavior = function(pRequest, fComplete)
|
|
37
|
-
* {
|
|
38
|
-
* // Do some stuff with pRequest...
|
|
39
|
-
* if (pRequest.UserSession.UserRoleIndex < 5)
|
|
40
|
-
* pRequest.Query.addFilter('Customer', pRequest.UserSession.IDCustomer);
|
|
41
|
-
* return fComplete(false);
|
|
42
|
-
* }
|
|
43
|
-
*
|
|
44
|
-
* It is important to note that the fComplete function expects false if no error, or a string message if there is one.
|
|
45
|
-
*/
|
|
46
|
-
var setBehavior = function(pBehaviorHash, fBehavior)
|
|
47
|
-
{
|
|
48
|
-
_BehaviorFunctions[pBehaviorHash] = fBehavior;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* This method runs a behavior at a specific hash, and returns true.
|
|
53
|
-
* Or it returns false if there was no behavior there.
|
|
54
|
-
* Behaviors should expect their state to be in the pRequest object, per the example in setBehavior
|
|
55
|
-
*/
|
|
56
|
-
var runBehavior = function(pBehaviorHash, pRequest, fComplete)
|
|
57
|
-
{
|
|
58
|
-
// Run an injected behavior (if it exists)
|
|
59
|
-
if (_BehaviorFunctions.hasOwnProperty(pBehaviorHash) &&
|
|
60
|
-
_BehaviorFunctions[pBehaviorHash])
|
|
61
|
-
{
|
|
62
|
-
//Array of functions. Aborts on first error.
|
|
63
|
-
if (Array.isArray(_BehaviorFunctions[pBehaviorHash]))
|
|
64
|
-
{
|
|
65
|
-
libAsync.timesLimit(_BehaviorFunctions[pBehaviorHash].length, 1, function(idx, fNext)
|
|
66
|
-
{
|
|
67
|
-
_BehaviorFunctions[pBehaviorHash][idx](pRequest, fNext);
|
|
68
|
-
},
|
|
69
|
-
function complete(err)
|
|
70
|
-
{
|
|
71
|
-
return fComplete(err);
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
else
|
|
75
|
-
{
|
|
76
|
-
//Single function
|
|
77
|
-
return _BehaviorFunctions[pBehaviorHash](pRequest, fComplete);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
else
|
|
81
|
-
{
|
|
82
|
-
return fComplete(false);
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Set a template.
|
|
89
|
-
*/
|
|
90
|
-
var setTemplate = function(pTemplateHash, pTemplate)
|
|
91
|
-
{
|
|
92
|
-
// Store both the cached text as well as the function
|
|
93
|
-
_Templates[pTemplateHash] = pTemplate;
|
|
94
|
-
_TemplateFunctions[pTemplateHash] = libUnderscore.template(pTemplate);
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Get a template.
|
|
99
|
-
*/
|
|
100
|
-
var getTemplate = function(pTemplateHash)
|
|
101
|
-
{
|
|
102
|
-
if (_Templates.hasOwnProperty(pTemplateHash))
|
|
103
|
-
{
|
|
104
|
-
return _Templates[pTemplateHash];
|
|
105
|
-
}
|
|
106
|
-
else
|
|
107
|
-
{
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Get a template function.
|
|
114
|
-
*/
|
|
115
|
-
var getTemplateFunction = function(pTemplateHash)
|
|
116
|
-
{
|
|
117
|
-
if (_TemplateFunctions.hasOwnProperty(pTemplateHash))
|
|
118
|
-
{
|
|
119
|
-
return _TemplateFunctions[pTemplateHash];
|
|
120
|
-
}
|
|
121
|
-
else
|
|
122
|
-
{
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Process a template at a hash, and return the result.
|
|
129
|
-
*/
|
|
130
|
-
var processTemplate = function(pTemplateHash, pTemplateData, pDefaultTemplate)
|
|
131
|
-
{
|
|
132
|
-
var tmpTemplateFunction = getTemplateFunction(pTemplateHash);
|
|
133
|
-
var tmpTemplateData = (typeof(pTemplateData) === 'undefined') ? {} : pTemplateData;
|
|
134
|
-
|
|
135
|
-
// This makes the function fairly laziliy loading.
|
|
136
|
-
if (tmpTemplateFunction === false)
|
|
137
|
-
{
|
|
138
|
-
// If the template doesn't exist, try to use the passed-in default and set that as the template.
|
|
139
|
-
// Otherwise make it empty.
|
|
140
|
-
setTemplate(pTemplateHash, (typeof(pDefaultTemplate) === 'undefined') ? '' : pDefaultTemplate);
|
|
141
|
-
tmpTemplateFunction = getTemplateFunction(pTemplateHash);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Now process and return the underscore template.
|
|
145
|
-
return tmpTemplateFunction(tmpTemplateData);
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Container Object for our Factory Pattern
|
|
150
|
-
*/
|
|
151
|
-
var tmpNewMeadowBehaviorModifications = (
|
|
152
|
-
{
|
|
153
|
-
setBehavior: setBehavior,
|
|
154
|
-
runBehavior: runBehavior,
|
|
155
|
-
|
|
156
|
-
setTemplate: setTemplate,
|
|
157
|
-
getTemplate: getTemplate,
|
|
158
|
-
getTemplateFunction: getTemplateFunction,
|
|
159
|
-
processTemplate: processTemplate,
|
|
160
|
-
|
|
161
|
-
new: createNew
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
return tmpNewMeadowBehaviorModifications;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return createNew();
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
module.exports = new MeadowBehaviorModifications();
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Meadow Common Services Provider
|
|
3
|
-
*
|
|
4
|
-
* This class aims to provide anything that every request will need.
|
|
5
|
-
*
|
|
6
|
-
* @class MeadowCommonServices
|
|
7
|
-
* @constructor
|
|
8
|
-
*/
|
|
9
|
-
var MeadowCommonServices = function()
|
|
10
|
-
{
|
|
11
|
-
function createNew(pMeadow, pAuthenticationMode)
|
|
12
|
-
{
|
|
13
|
-
// If a valid fable object isn't passed in, return a constructor
|
|
14
|
-
if ((typeof(pMeadow) !== 'object') || !('fable' in pMeadow))
|
|
15
|
-
{
|
|
16
|
-
return {new: createNew};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
var _Meadow = pMeadow;
|
|
20
|
-
const _AuthenticationMode = pAuthenticationMode;
|
|
21
|
-
var _Log = _Meadow.fable.log;
|
|
22
|
-
|
|
23
|
-
var libRestify = require('restify');
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Send an Error Code and Error Message to the client, and log it as an error in the log files.
|
|
27
|
-
*
|
|
28
|
-
* @method sendCodedError
|
|
29
|
-
*/
|
|
30
|
-
var sendCodedError = function(pDefaultMessage, pError, pRequest, pResponse, fNext)
|
|
31
|
-
{
|
|
32
|
-
var tmpErrorMessage = pDefaultMessage;
|
|
33
|
-
var tmpErrorCode = 1;
|
|
34
|
-
var tmpScope = null;
|
|
35
|
-
var tmpParams = null;
|
|
36
|
-
var tmpSessionID = null;
|
|
37
|
-
|
|
38
|
-
if (typeof(pError) === 'object')
|
|
39
|
-
{
|
|
40
|
-
tmpErrorMessage = pError.Message;
|
|
41
|
-
if (pError.Code)
|
|
42
|
-
tmpErrorCode = pError.Code;
|
|
43
|
-
}
|
|
44
|
-
else if (typeof(pError) === 'string')
|
|
45
|
-
{
|
|
46
|
-
tmpErrorMessage += ' ' + pError;
|
|
47
|
-
}
|
|
48
|
-
if (pRequest.DAL)
|
|
49
|
-
{
|
|
50
|
-
tmpScope = pRequest.DAL.scope;
|
|
51
|
-
}
|
|
52
|
-
if (pRequest.params)
|
|
53
|
-
{
|
|
54
|
-
tmpParams = pRequest.params;
|
|
55
|
-
}
|
|
56
|
-
if (pRequest.UserSession)
|
|
57
|
-
{
|
|
58
|
-
tmpSessionID = pRequest.UserSession.SessionID;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
_Log.warn('API Error: '+tmpErrorMessage, {SessionID: tmpSessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Scope: tmpScope, Parameters: tmpParams, Action:'APIError'}, pRequest);
|
|
62
|
-
pResponse.send({Error:tmpErrorMessage, ErrorCode: tmpErrorCode});
|
|
63
|
-
|
|
64
|
-
return fNext();
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Send an Error to the client, and log it as an error in the log files.
|
|
70
|
-
*
|
|
71
|
-
* @method sendError
|
|
72
|
-
*/
|
|
73
|
-
var sendError = function(pMessage, pRequest, pResponse, fNext)
|
|
74
|
-
{
|
|
75
|
-
var tmpSessionID = null;
|
|
76
|
-
if (pRequest.UserSession)
|
|
77
|
-
{
|
|
78
|
-
tmpSessionID = pRequest.UserSession.SessionID;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
_Log.warn('API Error: '+pMessage, {SessionID: tmpSessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:'APIError'}, pRequest);
|
|
82
|
-
pResponse.send({Error:pMessage});
|
|
83
|
-
|
|
84
|
-
return fNext();
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Check that the user has an appropriate user level to use the current endpoint
|
|
90
|
-
*
|
|
91
|
-
* @method authorizeEndpoint
|
|
92
|
-
*/
|
|
93
|
-
var authorizeEndpoint = function(pRequest, pResponse, fNext)
|
|
94
|
-
{
|
|
95
|
-
if (!pRequest.EndpointAuthenticated)
|
|
96
|
-
{
|
|
97
|
-
pRequest.CommonServices.log.warn('Unauthenticated user attempting to get a secured resource.', {RequestID:pRequest.RequestUUID}, pRequest);
|
|
98
|
-
sendNotAuthorized('You must be authenticated to access this resource.', pRequest, pResponse, fNext);
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
//Check if endpoint is being invoked programmatically, in which case
|
|
103
|
-
// we bypass session authentication checks
|
|
104
|
-
if (pRequest.EndpointInvoked)
|
|
105
|
-
{
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Check that the user has a valid ID.
|
|
110
|
-
if (_AuthenticationMode !== 'Disabled')
|
|
111
|
-
{
|
|
112
|
-
//TODO: do we need this code anymore?
|
|
113
|
-
const tmpIDUser = pRequest.UserSession.UserID;
|
|
114
|
-
if (tmpIDUser < 1)
|
|
115
|
-
{
|
|
116
|
-
_Log.warn('Invalid session when attempting to get a secured resource - IDUser is not valid.', {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:'APISecurity'}, pRequest);
|
|
117
|
-
sendNotAuthorized('You must be authenticated to access this resource.', pRequest, pResponse, fNext);
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Check that the authentication level is valid.
|
|
122
|
-
if (pRequest.UserSession.UserRoleIndex < pRequest.EndpointAuthorizationRequirement)
|
|
123
|
-
{
|
|
124
|
-
_Log.warn('Invalid permission level when attempting to get a secured resource.', {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:'APISecurity', RequiredUserLevel:pRequest.EndpointAuthorizationRequirement, ActualUserLevel:pRequest.UserSession.UserRoleIndex}, pRequest);
|
|
125
|
-
// TODO: Send the proper http status code
|
|
126
|
-
sendNotAuthorized('You must be appropriately authenticated to access this resource.', pRequest, pResponse, fNext);
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return true;
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Send a not authorized response to the client, and log it in the log files.
|
|
137
|
-
*
|
|
138
|
-
* @method sendNotAuthorized
|
|
139
|
-
*/
|
|
140
|
-
var sendNotAuthorized = function(pMessage, pRequest, pResponse, fNext)
|
|
141
|
-
{
|
|
142
|
-
// TODO: Use the proper http code
|
|
143
|
-
_Log.trace('API Unauthorized Attempt: '+pMessage, {SessionID:pRequest.UserSession.SessionID, RequestID:pRequest.RequestUUID, RequestURL:pRequest.url, Action:'APIUnauthorized'}, pRequest);
|
|
144
|
-
|
|
145
|
-
//cause a delay to mitigate DoS type attacks against endpoints
|
|
146
|
-
setTimeout(function()
|
|
147
|
-
{
|
|
148
|
-
pResponse.send({Error:pMessage});
|
|
149
|
-
|
|
150
|
-
return fNext();
|
|
151
|
-
}, (_Meadow.fable.settings.UnauthorizedRequestDelay ? _Meadow.fable.settings.UnauthorizedRequestDelay : 15000));
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Container Object for our Factory Pattern
|
|
157
|
-
*/
|
|
158
|
-
var tmpNewMeadowCommonServices = (
|
|
159
|
-
{
|
|
160
|
-
authorizeEndpoint: authorizeEndpoint,
|
|
161
|
-
|
|
162
|
-
sendCodedError: sendCodedError,
|
|
163
|
-
sendError: sendError,
|
|
164
|
-
sendNotAuthorized: sendNotAuthorized,
|
|
165
|
-
|
|
166
|
-
// Restify body parser passed through, for any POST and PUT requests
|
|
167
|
-
bodyParser: libRestify.plugins.bodyParser,
|
|
168
|
-
|
|
169
|
-
new: createNew
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// Turn the common services object into a first-class Fable object
|
|
173
|
-
// addServices removed in fable 2.x
|
|
174
|
-
if (typeof(_Meadow.fable.addServices) === 'function')
|
|
175
|
-
{
|
|
176
|
-
_Meadow.fable.addServices(tmpNewMeadowCommonServices);
|
|
177
|
-
}
|
|
178
|
-
else
|
|
179
|
-
{
|
|
180
|
-
// bring over addServices implementation from Fable 1.x for backward compatibility
|
|
181
|
-
Object.defineProperty(tmpNewMeadowCommonServices, 'fable',
|
|
182
|
-
{
|
|
183
|
-
get: function() { return _Meadow.fable; },
|
|
184
|
-
enumerable: false,
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
Object.defineProperty(tmpNewMeadowCommonServices, 'settings',
|
|
188
|
-
{
|
|
189
|
-
get: function() { return _Meadow.fable.settings; },
|
|
190
|
-
enumerable: false,
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
Object.defineProperty(tmpNewMeadowCommonServices, 'log',
|
|
194
|
-
{
|
|
195
|
-
get: function() { return _Meadow.fable.log; },
|
|
196
|
-
enumerable: false,
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return tmpNewMeadowCommonServices;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return createNew();
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
module.exports = new MeadowCommonServices();
|