meadow-endpoints 3.0.6 → 3.0.7
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.
|
@@ -13,6 +13,48 @@ RUN sudo apt install default-mysql-server default-mysql-client -y
|
|
|
13
13
|
|
|
14
14
|
RUN echo "Building RETOLD development image..."
|
|
15
15
|
|
|
16
|
+
RUN echo "...installing vscode extensions..."
|
|
17
|
+
|
|
18
|
+
# Mocha unit testing in the sidebar
|
|
19
|
+
RUN code-server --install-extension hbenl.vscode-mocha-test-adapter
|
|
20
|
+
RUN code-server --install-extension hbenl.test-adapter-converter
|
|
21
|
+
RUN code-server --install-extension hbenl.vscode-test-explorer
|
|
22
|
+
|
|
23
|
+
# Magic indentation rainbow
|
|
24
|
+
RUN code-server --install-extension oderwat.indent-rainbow
|
|
25
|
+
RUN code-server --install-extension dbaeumer.vscode-eslint
|
|
26
|
+
|
|
27
|
+
# Contextual git
|
|
28
|
+
RUN code-server --install-extension eamodio.gitlens
|
|
29
|
+
|
|
30
|
+
# Other extensions (uncomment them to have them automagic, or run this from a terminal to install in the container):
|
|
31
|
+
|
|
32
|
+
# SQL Tools
|
|
33
|
+
RUN code-server --install-extension mtxr.sqltools
|
|
34
|
+
RUN code-server --install-extension mtxr.sqltools-driver-mysql
|
|
35
|
+
|
|
36
|
+
# Microsoft's AI code completion
|
|
37
|
+
# RUN code-server --install-extension VisualStudioExptTeam.vscodeintellicode
|
|
38
|
+
|
|
39
|
+
# Live server -- make sure to open up the port on the docker image
|
|
40
|
+
# RUN code-server --install-extension ritwickdey.LiveServer
|
|
41
|
+
|
|
42
|
+
# Quick link to required modules' documentation
|
|
43
|
+
RUN code-server --install-extension bengreenier.vscode-node-readme
|
|
44
|
+
|
|
45
|
+
# Switch up fonts
|
|
46
|
+
# RUN code-server --install-extension evan-buss.font-switcher
|
|
47
|
+
|
|
48
|
+
# Icons
|
|
49
|
+
# RUN code-server --install-extension vscode-icons-team.vscode-icons
|
|
50
|
+
# RUN code-server --install-extension PKief.material-icon-theme
|
|
51
|
+
|
|
52
|
+
# Hover over CSS colors to see them previewed
|
|
53
|
+
# RUN code-server --install-extension bierner.color-info
|
|
54
|
+
|
|
55
|
+
# An easy on the eyes color theme
|
|
56
|
+
# RUN code-server --install-extension daylerees.rainglow
|
|
57
|
+
|
|
16
58
|
RUN echo "...configuring mariadb (mysql) server..."
|
|
17
59
|
RUN sudo sed -i "s|bind-address|#bind-address|g" /etc/mysql/mariadb.conf.d/50-server.cnf
|
|
18
60
|
ADD ./.config/luxury-extras/MySQL/MySQL-Security.sql /home/coder/MySQL-Configure-Security.sql
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meadow-endpoints",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.7",
|
|
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
9
|
"test": "./node_modules/.bin/mocha --exit -u tdd -R spec",
|
|
10
|
-
"
|
|
10
|
+
"build": "./node_modules/.bin/gulp build",
|
|
11
|
+
"docker-dev-build-image": "docker build ./ -f Dockerfile_LUXURYCode -t retold/meadow-endpoints:local",
|
|
11
12
|
"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
|
},
|
|
13
14
|
"mocha": {
|
|
@@ -64,6 +64,7 @@ var MeadowEndpoints = function()
|
|
|
64
64
|
Upserts: require('./crud/Meadow-Endpoint-BulkUpsert.js'),
|
|
65
65
|
|
|
66
66
|
Delete: require('./crud/Meadow-Endpoint-Delete.js'),
|
|
67
|
+
Undelete: require('./crud/Meadow-Endpoint-Undelete.js'),
|
|
67
68
|
|
|
68
69
|
Count: require('./crud/Meadow-Endpoint-Count.js'),
|
|
69
70
|
CountBy: require('./crud/Meadow-Endpoint-CountBy.js'),
|
|
@@ -184,6 +185,7 @@ var MeadowEndpoints = function()
|
|
|
184
185
|
Delete: true,
|
|
185
186
|
// DEL [/1.0/SomeEndpoint]
|
|
186
187
|
// DEL [/1.0/SomeEndpoint/:IDRecord]
|
|
188
|
+
// GET [/1.0/SomeEndpoint/Undelete/:IDRecord]
|
|
187
189
|
|
|
188
190
|
Count: true,
|
|
189
191
|
// GET [/1.0/SomeEndpoints/Count]
|
|
@@ -379,6 +381,7 @@ var MeadowEndpoints = function()
|
|
|
379
381
|
{
|
|
380
382
|
pRestServer.del(`${tmpEndpointPrefix}`, _CommonServices.bodyParser(), _EndpointAuthenticators.Delete, wireState, _Endpoints.Delete);
|
|
381
383
|
pRestServer.del(`${tmpEndpointPrefix}/:IDRecord`, _EndpointAuthenticators.Delete, wireState, _Endpoints.Delete);
|
|
384
|
+
pRestServer.get(`${tmpEndpointPrefix}/Undelete/:IDRecord`, _EndpointAuthenticators.Delete, wireState, _Endpoints.Undelete);
|
|
382
385
|
}
|
|
383
386
|
if (_EnabledBehaviors.Count)
|
|
384
387
|
{
|
|
@@ -0,0 +1,161 @@
|
|
|
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;
|
|
@@ -1007,6 +1007,39 @@ suite
|
|
|
1007
1007
|
}
|
|
1008
1008
|
);
|
|
1009
1009
|
test
|
|
1010
|
+
(
|
|
1011
|
+
'delete: undelete a record after deleting it',
|
|
1012
|
+
function(fDone)
|
|
1013
|
+
{
|
|
1014
|
+
// Delete animal 4
|
|
1015
|
+
var tmpRecord = {IDAnimal:4};
|
|
1016
|
+
libSuperTest('http://localhost:9080/')
|
|
1017
|
+
.del('1.0/FableTest')
|
|
1018
|
+
.send(tmpRecord)
|
|
1019
|
+
.end(
|
|
1020
|
+
function(pError, pResponse)
|
|
1021
|
+
{
|
|
1022
|
+
// Expect response to be the count of deleted records.
|
|
1023
|
+
var tmpResult = JSON.parse(pResponse.text);
|
|
1024
|
+
Expect(tmpResult.Count).to.equal(1);
|
|
1025
|
+
|
|
1026
|
+
// Now undelete the record
|
|
1027
|
+
libSuperTest('http://localhost:9080/')
|
|
1028
|
+
.get('1.0/FableTest/Undelete/4')
|
|
1029
|
+
.end(
|
|
1030
|
+
function(pError, pResponse)
|
|
1031
|
+
{
|
|
1032
|
+
// Expect response to be the count of deleted records.
|
|
1033
|
+
var tmpResult = JSON.parse(pResponse.text);
|
|
1034
|
+
Expect(tmpResult.Count).to.equal(1);
|
|
1035
|
+
return fDone();
|
|
1036
|
+
}
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
);
|
|
1040
|
+
}
|
|
1041
|
+
);
|
|
1042
|
+
test
|
|
1010
1043
|
(
|
|
1011
1044
|
'delete: delete a record with a bad parameter',
|
|
1012
1045
|
function(fDone)
|