meadow-endpoints 2.0.14 → 3.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 ADDED
@@ -0,0 +1,48 @@
1
+ # Use the codercom/code-server image
2
+ FROM codercom/code-server:latest
3
+ MAINTAINER steven velozo
4
+
5
+ VOLUME /home/coder/.config
6
+ VOLUME /home/coder/.vscode
7
+
8
+ RUN echo "...installing debian dependencies..."
9
+ RUN sudo apt update
10
+ RUN sudo apt install vim curl tmux -y
11
+ RUN sudo apt install default-mysql-server default-mysql-client -y
12
+
13
+
14
+ RUN echo "Building RETOLD development image..."
15
+
16
+ RUN echo "...configuring mariadb (mysql) server..."
17
+ RUN sudo sed -i "s|bind-address|#bind-address|g" /etc/mysql/mariadb.conf.d/50-server.cnf
18
+ ADD ./.config/luxury-extras/MySQL/MySQL-Security.sql /home/coder/MySQL-Configure-Security.sql
19
+ ADD ./.config/luxury-extras/MySQL/MySQL-Laden-Entry.sh /usr/bin/MySQL-Laden-Entry.sh
20
+ RUN ( sudo mysqld_safe --skip-grant-tables --skip-networking & ) && sleep 5 && mysql -u root < /home/coder/MySQL-Configure-Security.sql
21
+
22
+ # Import the initial database
23
+ COPY ./.config/luxury-extras/model/sql_create/BookStore-CreateDatabase.mysql.sql /home/coder/MySQL-Create-Databases.sql
24
+ RUN sudo service mariadb restart && sleep 5 && mysql -u root -p"123456789" -e "CREATE DATABASE bookstore;"
25
+ RUN sudo service mariadb restart && sleep 5 && mysql -u root -p"123456789" bookstore < /home/coder/MySQL-Create-Databases.sql
26
+ RUN sudo service mariadb restart && sleep 5 && mysql -u root -p"123456789" -e "CREATE DATABASE FableTest;"
27
+
28
+
29
+ RUN echo "...mapping library specific volumes..."
30
+ # Volume mappings for RETOLD:Meadow Endpoints library
31
+ VOLUME /home/coder/meadow-endpoints
32
+ # VOLUME /home/coder/meadow-endpoints/node_modules
33
+
34
+ SHELL ["/bin/bash", "-c"]
35
+ USER coder
36
+
37
+ RUN echo "...installing node version manager..."
38
+ # Because there is a .bashrc chicken/egg problem, we will create one here to simulate logging in. This is not great.
39
+ RUN touch ~/.bashrc && chmod +x ~/.bashrc
40
+ RUN curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
41
+
42
+ RUN echo "...installing node version 14 as the default..."
43
+ RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm install 14
44
+ RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm alias default 14
45
+
46
+ WORKDIR /home/coder/meadow-endpoints
47
+
48
+ ENTRYPOINT ["/usr/bin/MySQL-Laden-Entry.sh"]
package/README.md CHANGED
@@ -16,4 +16,33 @@ The design philosophy is not to cover every possible use case, but to cover the
16
16
 
17
17
  To best use this library, it should be in conjunction with [stricture](https://github.com/stevenvelozo/stricture) and [orator](https://github.com/stevenvelozo/orator).
18
18
 
19
- Multiple organizations have been using these libraries in medium to high load production environments for over a year.
19
+
20
+ ### Docker Development Environment
21
+
22
+ 1. Run this command to build this image:
23
+ ```
24
+ docker build ./ -t retold/meadow-endpoints:local
25
+ ```
26
+
27
+ alternatively you can use npm to run this
28
+
29
+ ```
30
+ npm run docker-dev-build-image
31
+ ```
32
+
33
+ 2. Run this command to build the local container:
34
+ ```
35
+ docker run -it --name meadow-endpoints-dev -p 127.0.0.1:12343:8080 -v "$PWD/.config:/home/coder/.config" -v "$PWD:/home/coder/meadow-endpoints" -u "$(id -u):$(id -g)" -e "DOCKER_USER=$USER" retold/meadow-endpoints:local
36
+ ```
37
+
38
+ alternatively you can use npm to run this
39
+
40
+ ```
41
+ npm run docker-dev-run
42
+ ```
43
+
44
+ 3. Go to http://localhost:12343/ in a web browser
45
+
46
+ 4. The password is "retold"
47
+
48
+ 5. Right now you (may) need to delete the `node_modules` folders and regenerate it for Linux.
File without changes
package/package.json CHANGED
@@ -1,12 +1,32 @@
1
1
  {
2
2
  "name": "meadow-endpoints",
3
- "version": "2.0.14",
3
+ "version": "3.0.2",
4
4
  "description": "Automatic API endpoints for Meadow data.",
5
5
  "main": "source/Meadow-Endpoints.js",
6
6
  "scripts": {
7
7
  "start": "node source/Meadow-Endpoints.js",
8
8
  "coverage": "nyc npm run test && nyc report --reporter=lcov",
9
- "test": "./node_modules/.bin/mocha --exit -u tdd -R spec"
9
+ "test": "./node_modules/.bin/mocha --exit -u tdd -R spec",
10
+ "docker-dev-build-image": "docker build ./ -t retold/meadow-endpoints:local",
11
+ "docker-dev-run": "docker run -it -d --name meadow-endpoints-dev -p 127.0.0.1:12343:8080 -p 12305:3306 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/meadow-endpoints\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" retold/meadow-endpoints:local"
12
+ },
13
+ "mocha": {
14
+ "diff": true,
15
+ "extension": [
16
+ "js"
17
+ ],
18
+ "package": "./package.json",
19
+ "reporter": "spec",
20
+ "slow": "75",
21
+ "timeout": "5000",
22
+ "ui": "tdd",
23
+ "watch-files": [
24
+ "source/**/*.js",
25
+ "test/**/*.js"
26
+ ],
27
+ "watch-ignore": [
28
+ "lib/vendor"
29
+ ]
10
30
  },
11
31
  "repository": {
12
32
  "type": "git",
@@ -24,20 +44,19 @@
24
44
  "homepage": "https://github.com/stevenvelozo/meadow-endpoints",
25
45
  "devDependencies": {
26
46
  "chai": "4.1.2",
27
- "codeclimate-test-reporter": "0.5.0",
28
- "coveralls": "3.0.2",
47
+ "chance": "^1.1.8",
29
48
  "fable": "^2.0.1",
30
- "mocha": "5.2.0",
49
+ "mocha": "9.2.2",
50
+ "mysql2": "1.6.1",
31
51
  "nyc": "^15.1.0",
32
52
  "supertest": "3.1.0"
33
53
  },
34
54
  "dependencies": {
35
55
  "async": "2.6.1",
36
56
  "JSONStream": "^1.3.5",
37
- "meadow": "~1.0.32",
57
+ "meadow": "~1.0.34",
38
58
  "meadow-filter": "^1.0.1",
39
- "mysql2": "1.6.1",
40
59
  "orator": "~2.0.2",
41
- "underscore": "1.9.1"
60
+ "underscore": "1.12.1"
42
61
  }
43
62
  }
@@ -1,21 +1,31 @@
1
1
  /**
2
- * Check that a user is logged in
2
+ * Check that a user is logged in, if enabled
3
3
  *
4
- * @method checkAuthentication
4
+ * @method getAuthenticator
5
5
  */
6
- var checkAuthentication = function(pRequest, pResponse, fNext)
6
+ const getAuthenticator = (pAuthenticatorMode) =>
7
7
  {
8
- if (!pRequest.UserSession.LoggedIn)
8
+ if (pAuthenticatorMode === 'Disabled')
9
9
  {
10
- pRequest.EndpointAuthenticated = false;
10
+ return (pRequest, pResponse, fNext) =>
11
+ {
12
+ pRequest.EndpointAuthenticated = true;
13
+ fNext();
14
+ };
11
15
  }
12
- else
16
+ return (pRequest, pResponse, fNext) =>
13
17
  {
14
- pRequest.EndpointAuthenticated = true;
15
- }
18
+ if (!pRequest.UserSession.LoggedIn)
19
+ {
20
+ pRequest.EndpointAuthenticated = false;
21
+ }
22
+ else
23
+ {
24
+ pRequest.EndpointAuthenticated = true;
25
+ }
16
26
 
17
- // This doesn't call next in chain because SendError does that for us.
18
- fNext();
27
+ fNext();
28
+ }
19
29
  };
20
30
 
21
- module.exports = checkAuthentication;
31
+ module.exports = getAuthenticator;
@@ -19,6 +19,8 @@ var MeadowAuthorizers = function()
19
19
  return {new: createNew};
20
20
  }
21
21
 
22
+ const _AuthorizationMode = pMeadow.fable.settings.MeadowAuthorizationMode || 'Disabled';
23
+
22
24
  // An object to hold modifications to specific authorizers.
23
25
  var _AuthorizerFunctions = {};
24
26
 
@@ -44,12 +46,14 @@ var MeadowAuthorizers = function()
44
46
  _AuthorizerFunctions[pAuthorizerHash] = fAuthorizer;
45
47
  };
46
48
 
47
-
48
- // Map in the default authorizers
49
- setAuthorizer('Allow', require(__dirname+'/authorizers/Meadow-Authorizer-Allow.js'));
50
- setAuthorizer('Deny', require(__dirname+'/authorizers/Meadow-Authorizer-Deny.js'));
51
- setAuthorizer('Mine', require(__dirname+'/authorizers/Meadow-Authorizer-Mine.js'));
52
- setAuthorizer('MyCustomer', require(__dirname+'/authorizers/Meadow-Authorizer-MyCustomer.js'));
49
+ if (_AuthorizationMode === 'SimpleOwnership')
50
+ {
51
+ // Map in the authorizers for simple ownership mode
52
+ setAuthorizer('Allow', require(__dirname+'/authorizers/Meadow-Authorizer-Allow.js'));
53
+ setAuthorizer('Deny', require(__dirname+'/authorizers/Meadow-Authorizer-Deny.js'));
54
+ setAuthorizer('Mine', require(__dirname+'/authorizers/Meadow-Authorizer-Mine.js'));
55
+ setAuthorizer('MyCustomer', require(__dirname+'/authorizers/Meadow-Authorizer-MyCustomer.js'));
56
+ }
53
57
 
54
58
 
55
59
  /**
@@ -65,6 +69,13 @@ var MeadowAuthorizers = function()
65
69
  pRequest.MeadowAuthorization = true;
66
70
  }
67
71
 
72
+ // authorize all behaviors if authorization is disabled
73
+ if (_AuthorizationMode === 'Disabled')
74
+ {
75
+ return fComplete();
76
+ }
77
+
78
+ //FIXME: Get rid of this...
68
79
  if (pRequest.Satchel &&
69
80
  pRequest.Satchel.AuthorizeOverride)
70
81
  return fComplete(false);
@@ -125,10 +136,15 @@ var MeadowAuthorizers = function()
125
136
  pRequest.MeadowAuthorization = true;
126
137
  }
127
138
 
139
+ // authorize all behaviors if authorization is disabled
140
+ if (_AuthorizationMode === 'Disabled')
141
+ {
142
+ return fComplete();
143
+ }
144
+
128
145
  // Attach authorizer hash in case the invoked authorizer needs the endpoint context
129
146
  pRequest.EndpointHash = pRequestHash;
130
147
 
131
-
132
148
  // See if there is an authorizer collection for the role of the user
133
149
  var tmpRoleAuthorizer = pRequest.DAL.schemaFull.authorizer[pRequest.DAL.getRoleName(pRequest.UserSession.UserRoleIndex)];
134
150
  if (!tmpRoleAuthorizer)
@@ -8,7 +8,7 @@
8
8
  */
9
9
  var MeadowCommonServices = function()
10
10
  {
11
- function createNew(pMeadow)
11
+ function createNew(pMeadow, pAuthenticationMode)
12
12
  {
13
13
  // If a valid fable object isn't passed in, return a constructor
14
14
  if ((typeof(pMeadow) !== 'object') || !('fable' in pMeadow))
@@ -17,6 +17,7 @@ var MeadowCommonServices = function()
17
17
  }
18
18
 
19
19
  var _Meadow = pMeadow;
20
+ const _AuthenticationMode = pAuthenticationMode;
20
21
  var _Log = _Meadow.fable.log;
21
22
 
22
23
  var libRestify = require('restify');
@@ -106,21 +107,25 @@ var MeadowCommonServices = function()
106
107
  }
107
108
 
108
109
  // Check that the user has a valid ID.
109
- var tmpIDUser = pRequest.UserSession.UserID;
110
- if (tmpIDUser < 1)
110
+ if (_AuthenticationMode !== 'Disabled')
111
111
  {
112
- _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);
113
- sendNotAuthorized('You must be authenticated to access this resource.', pRequest, pResponse, fNext);
114
- return false;
115
- }
116
-
117
- // Check that the authentication level is valid.
118
- if (pRequest.UserSession.UserRoleIndex < pRequest.EndpointAuthorizationRequirement)
119
- {
120
- _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);
121
- // TODO: Send the proper http status code
122
- sendNotAuthorized('You must be appropriately authenticated to access this resource.', pRequest, pResponse, fNext);
123
- return false;
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
+ }
124
129
  }
125
130
 
126
131
  return true;
@@ -7,9 +7,6 @@
7
7
  * @module Meadow
8
8
  */
9
9
 
10
- //Meadow needs to connect some general route handlers, this ensures it is done lazily, and only once.
11
- var _AttachedRequestHandlers = false;
12
-
13
10
  /**
14
11
  * Meadow Data Broker Library
15
12
  *
@@ -31,7 +28,9 @@ var MeadowEndpoints = function()
31
28
  var libAsync = require('async');
32
29
  var libRestRouteParse = require('./Restify-RouteParser.js');
33
30
 
34
- var _CommonServices = require('./Meadow-CommonServices.js').new(pMeadow);
31
+ const _AuthenticationMode = _Fable.settings.MeadowAuthenticationMode || 'Disabled';
32
+
33
+ var _CommonServices = require('./Meadow-CommonServices.js').new(pMeadow, _AuthenticationMode);
35
34
 
36
35
  // This holds any changed behaviors.
37
36
  var _BehaviorModifications = require('./Meadow-BehaviorModifications.js').new(pMeadow);
@@ -40,7 +39,7 @@ var MeadowEndpoints = function()
40
39
  var _Authorizers = require('./Meadow-Authorizers.js').new(pMeadow);
41
40
 
42
41
  // This checks that the user is authenticated. In the future, it will be overloadable.
43
- var _Authenticator = require('./Meadow-Authenticator.js');
42
+ var _Authenticator = require('./Meadow-Authenticator.js')(_AuthenticationMode);
44
43
 
45
44
  // The default endpoints
46
45
  var _Endpoints = (
@@ -303,14 +302,17 @@ var MeadowEndpoints = function()
303
302
 
304
303
  const tmpEndpointPrefix = `/${tmpEndpointVersion}/${tmpEndpointName}`;
305
304
 
306
- if (!_AttachedRequestHandlers)
305
+ if (!pRestServer._AttachedMeadowEndpointsRequestHandlers)
307
306
  {
308
- _AttachedRequestHandlers = true;
307
+ pRestServer._AttachedMeadowEndpointsRequestHandlers = true;
309
308
  // Connect the common services to the route
310
309
  pRestServer.use(wireCommonServices);
311
310
 
312
311
  // Build formattedParams route parameters
313
312
  pRestServer.use(formatRouteParams);
313
+
314
+ // Marshall session data in, if needed / configured
315
+ pRestServer.use(require('./Meadow-MarshallSessionData')(_Fable));
314
316
  }
315
317
 
316
318
  // These special schema services must come in the route table before the READ because they
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Meadow Session Marshaller - Extract session data based on configuration.
3
+ *
4
+ * @license MIT
5
+ *
6
+ * @author Alex Decker <alex.decker@headlight.com>
7
+ * @module Meadow
8
+ */
9
+
10
+ module.exports = (pFable) =>
11
+ {
12
+ const _Fable = pFable;
13
+ const _SessionDataSource = _Fable.settings.MeadowEndpointsSessionDataSource || 'Request';
14
+
15
+ return (pRequest, pResponse, fNext) =>
16
+ {
17
+ let session;
18
+
19
+ switch (_SessionDataSource)
20
+ {
21
+ default:
22
+ _Fable.log.warn(`Unknown session source configured: ${_SessionDataSource} - defaulting to Request for backward compatibility`);
23
+ case 'Request':
24
+ // noop - already set by orator-session
25
+ session = pRequest.UserSession;
26
+ break;
27
+ case 'None':
28
+ break;
29
+ case 'Header':
30
+ try
31
+ {
32
+ const sessionStr = pRequest.headers['x-trusted-session'];
33
+ if (!sessionStr)
34
+ {
35
+ break;
36
+ }
37
+ session = JSON.parse(sessionStr);
38
+ }
39
+ catch (pError)
40
+ {
41
+ _Fable.log.error('Error marshalling session data from header.', { Error: pError.message, Stack: pError.stack });
42
+ }
43
+ break;
44
+ }
45
+
46
+ if (!session)
47
+ {
48
+ // blank session so things don't break, for now
49
+ session =
50
+ {
51
+ SessionID: '',
52
+ UserID: 0,
53
+ UserRole: '',
54
+ UserRoleIndex: 0,
55
+ LoggedIn: false,
56
+ DeviceID: '',
57
+ CustomerID: 0,
58
+ };
59
+ }
60
+
61
+ pRequest.UserSession = session;
62
+ fNext();
63
+ }
64
+ };
@@ -22,6 +22,9 @@ var tmpFableSettings = (
22
22
 
23
23
  "UnauthorizedRequestDelay": 10,
24
24
 
25
+ MeadowAuthenticationMode: 'LoggedIn',
26
+ MeadowAuthorizationMode: 'SimpleOwnership',
27
+
25
28
  APIServerPort: 9080,
26
29
 
27
30
  MySQL:
@@ -30,7 +33,7 @@ var tmpFableSettings = (
30
33
  Server: "localhost",
31
34
  Port: 3306,
32
35
  User: process.env.DEV_MYSQL_USER || "root",
33
- Password: process.env.DEV_MYSQL_PASS || "",
36
+ Password: process.env.DEV_MYSQL_PASS || "123456789",
34
37
  Database: "FableTest",
35
38
  ConnectionPoolLimit: 20
36
39
  },
@@ -40,7 +43,6 @@ var tmpFableSettings = (
40
43
  var libFable = require('fable').new(tmpFableSettings);
41
44
  tmpFableSettings = libFable.settings;
42
45
 
43
- var libMySQL = require('mysql2');
44
46
  libFable.MeadowMySQLConnectionPool = libMySQL.createPool
45
47
  (
46
48
  {