@vulkano/core 1.20.1 → 1.22.0
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/README.md +380 -70
- package/controllers/controllers.js +36 -8
- package/database/mongodb.js +11 -4
- package/examples/config/express/cookies.js +15 -0
- package/examples/config/express/cors.js +23 -0
- package/examples/config/express/csp.js +74 -0
- package/examples/config/express/helmet.js +19 -0
- package/examples/config/express/json.js +14 -0
- package/examples/config/express/jwt.js +39 -0
- package/examples/config/express/permissionPolicy.js +24 -0
- package/examples/config/express/settings.js +25 -0
- package/examples/config/middlewares/auth.js +38 -0
- package/examples/config/sockets/adapters/mongodb.js +12 -0
- package/examples/config/sockets/adapters/redis.js +9 -0
- package/examples/config/sockets/config.js +50 -0
- package/examples/config/sockets/cors.js +32 -0
- package/examples/config/sockets/events.js +12 -0
- package/examples/config/sockets/middlewares/auth.js +20 -0
- package/examples/config/views/config.js +8 -0
- package/examples/config/views/filters/example.js +6 -0
- package/examples/config/views/helpers/strpad.js +51 -0
- package/examples/controllers/ExampleController.js +22 -0
- package/examples/controllers/RestExampleController.js +78 -0
- package/examples/controllers/RestScaffoldController.js +18 -0
- package/examples/models/Example.js +238 -0
- package/examples/models/ExampleWithScaffold.js +51 -0
- package/examples/routes.js +55 -0
- package/examples/views/_shared/templates/default.html +20 -0
- package/examples/views/index.html +7 -0
- package/package.json +1 -1
- package/pnpm-workspace.yaml +7 -1
package/database/mongodb.js
CHANGED
|
@@ -175,12 +175,17 @@ module.exports = async function loadDatabaseApplication() {
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
// Update
|
|
178
|
+
// Bound to "updateOne" (the Mongoose 8 document method) rather than the
|
|
179
|
+
// legacy "update" hook name: Mongoose no longer fires "update" middleware,
|
|
180
|
+
// and that name collides with the scaffold's own `Model.update()` static
|
|
181
|
+
// (schema.statics.update), which Mongoose auto-wraps with any hook whose
|
|
182
|
+
// name matches an existing static method.
|
|
178
183
|
if (current.beforeUpdate) {
|
|
179
|
-
schema.pre('
|
|
184
|
+
schema.pre('updateOne', { document: true, query: false }, current.beforeUpdate);
|
|
180
185
|
delete schema.statics.beforeUpdate;
|
|
181
186
|
}
|
|
182
187
|
if (current.afterUpdate) {
|
|
183
|
-
schema.post('
|
|
188
|
+
schema.post('updateOne', { document: true, query: false }, current.afterUpdate);
|
|
184
189
|
delete schema.statics.afterUpdate;
|
|
185
190
|
}
|
|
186
191
|
|
|
@@ -195,12 +200,14 @@ module.exports = async function loadDatabaseApplication() {
|
|
|
195
200
|
}
|
|
196
201
|
|
|
197
202
|
// Remove
|
|
203
|
+
// Bound to "deleteOne" (the Mongoose 8 document method): `doc.remove()`
|
|
204
|
+
// and the legacy "remove" hook name were both removed upstream.
|
|
198
205
|
if (current.beforeRemove) {
|
|
199
|
-
schema.pre('
|
|
206
|
+
schema.pre('deleteOne', { document: true, query: false }, current.beforeRemove);
|
|
200
207
|
delete schema.statics.beforeRemove;
|
|
201
208
|
}
|
|
202
209
|
if (current.afterRemove) {
|
|
203
|
-
schema.post('
|
|
210
|
+
schema.post('deleteOne', { document: true, query: false }, current.afterRemove);
|
|
204
211
|
delete schema.statics.afterRemove;
|
|
205
212
|
}
|
|
206
213
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookies Config
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
|
|
7
|
+
// Enable cookie parser middleware
|
|
8
|
+
// @type Boolean
|
|
9
|
+
enabled: false,
|
|
10
|
+
|
|
11
|
+
// Secret key used to sign cookies — use https://api.wordpress.org/secret-key/1.1/salt/
|
|
12
|
+
// @type String
|
|
13
|
+
secret: process.env.COOKIES_SECRET_KEY || ''
|
|
14
|
+
|
|
15
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CORS Config
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
|
|
7
|
+
// Enable CORS
|
|
8
|
+
// @type Boolean
|
|
9
|
+
enabled: false,
|
|
10
|
+
|
|
11
|
+
// Path where CORS headers are applied
|
|
12
|
+
// @type String
|
|
13
|
+
path: '/',
|
|
14
|
+
|
|
15
|
+
// Allowed origin
|
|
16
|
+
// @type String
|
|
17
|
+
origin: '*',
|
|
18
|
+
|
|
19
|
+
// Additional allowed request headers
|
|
20
|
+
// @type Array
|
|
21
|
+
headers: ['x-token-auth']
|
|
22
|
+
|
|
23
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Security Policy
|
|
3
|
+
*
|
|
4
|
+
* Requires an endpoint to receive CSP violation reports.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
|
|
9
|
+
// Enable CSP
|
|
10
|
+
enabled: false,
|
|
11
|
+
|
|
12
|
+
// Reporting endpoint
|
|
13
|
+
report: {
|
|
14
|
+
group: 'csp-endpoint',
|
|
15
|
+
max_age: '10886400',
|
|
16
|
+
endpoints: [
|
|
17
|
+
{
|
|
18
|
+
// Replace with your domain
|
|
19
|
+
url: 'https://yourdomain.com/__cspreport__'
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
// CSP rules
|
|
25
|
+
rules: {
|
|
26
|
+
|
|
27
|
+
'default-src': ["'self'"],
|
|
28
|
+
|
|
29
|
+
'form-action': ["'self'"],
|
|
30
|
+
|
|
31
|
+
'font-src': [
|
|
32
|
+
"'self'",
|
|
33
|
+
'data:',
|
|
34
|
+
// 'fonts.googleapis.com',
|
|
35
|
+
// 'fonts.gstatic.com',
|
|
36
|
+
],
|
|
37
|
+
|
|
38
|
+
'img-src': [
|
|
39
|
+
"'self'",
|
|
40
|
+
'data:',
|
|
41
|
+
// '*.google-analytics.com',
|
|
42
|
+
],
|
|
43
|
+
|
|
44
|
+
'script-src': [
|
|
45
|
+
"'self'",
|
|
46
|
+
// "'unsafe-inline'",
|
|
47
|
+
// "'unsafe-eval'",
|
|
48
|
+
],
|
|
49
|
+
|
|
50
|
+
'style-src': [
|
|
51
|
+
"'self'",
|
|
52
|
+
"'unsafe-inline'",
|
|
53
|
+
'cdnjs.cloudflare.com'
|
|
54
|
+
],
|
|
55
|
+
|
|
56
|
+
'style-src-elem': [
|
|
57
|
+
"'self'",
|
|
58
|
+
// 'fonts.googleapis.com',
|
|
59
|
+
],
|
|
60
|
+
|
|
61
|
+
'frame-src': ["'self'"],
|
|
62
|
+
|
|
63
|
+
'frame-ancestors': ["'self'"],
|
|
64
|
+
|
|
65
|
+
'connect-src': [
|
|
66
|
+
"'self'",
|
|
67
|
+
// '*.google-analytics.com',
|
|
68
|
+
],
|
|
69
|
+
|
|
70
|
+
'report-to': ['csp-endpoint']
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helmet Config
|
|
3
|
+
* See https://helmetjs.github.io/ for all available options
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
|
|
8
|
+
// Referrer policy header
|
|
9
|
+
referrerPolicy: {
|
|
10
|
+
policy: 'strict-origin-when-cross-origin'
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
// Disable built-in CSP — managed separately via csp.js
|
|
14
|
+
contentSecurityPolicy: false,
|
|
15
|
+
|
|
16
|
+
// Disable COEP to allow embedding cross-origin resources
|
|
17
|
+
crossOriginEmbedderPolicy: false
|
|
18
|
+
|
|
19
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT Config
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
|
|
7
|
+
// Enable JWT
|
|
8
|
+
// @type Boolean
|
|
9
|
+
enabled: false,
|
|
10
|
+
|
|
11
|
+
// Secret key — use https://api.wordpress.org/secret-key/1.1/salt/ to generate one
|
|
12
|
+
// @type String
|
|
13
|
+
key: process.env.JWT_SECRET_KEY || '',
|
|
14
|
+
|
|
15
|
+
// Header name used to send the token
|
|
16
|
+
// @type String
|
|
17
|
+
header: 'x-token-auth',
|
|
18
|
+
|
|
19
|
+
// Query parameter name used to send the token
|
|
20
|
+
// @type String
|
|
21
|
+
queryParameter: 'token',
|
|
22
|
+
|
|
23
|
+
// Cookie name used to send the token
|
|
24
|
+
// @type String
|
|
25
|
+
cookieName: 'token',
|
|
26
|
+
|
|
27
|
+
// Path where the token is required
|
|
28
|
+
// @type String
|
|
29
|
+
path: '/api/',
|
|
30
|
+
|
|
31
|
+
// Paths excluded from token verification
|
|
32
|
+
// See https://github.com/jfromaniello/express-unless for pattern examples
|
|
33
|
+
// @type Array
|
|
34
|
+
ignore: [
|
|
35
|
+
'/api/',
|
|
36
|
+
/^\/api\/auth(?!\/(current))/i
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission Policy Config
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
|
|
7
|
+
// Enable Permission Policy header
|
|
8
|
+
// @type Boolean
|
|
9
|
+
enabled: false,
|
|
10
|
+
|
|
11
|
+
// Browser features to restrict — empty list means blocked for all origins
|
|
12
|
+
// @type Array
|
|
13
|
+
permissions: [
|
|
14
|
+
'accelerometer=()',
|
|
15
|
+
'camera=()',
|
|
16
|
+
'geolocation=()',
|
|
17
|
+
'gyroscope=()',
|
|
18
|
+
'magnetometer=()',
|
|
19
|
+
'microphone=()',
|
|
20
|
+
'payment=()',
|
|
21
|
+
'usb=()'
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express server settings
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
|
|
7
|
+
// Show "X-Powered-By" header
|
|
8
|
+
// @type Boolean
|
|
9
|
+
poweredBy: false,
|
|
10
|
+
|
|
11
|
+
// Request timeout in milliseconds
|
|
12
|
+
// @type Number
|
|
13
|
+
timeout: 120000,
|
|
14
|
+
|
|
15
|
+
// Folder to upload files
|
|
16
|
+
// @type String
|
|
17
|
+
uploadPath: 'public/files',
|
|
18
|
+
|
|
19
|
+
// Number of proxy hops to trust for X-Forwarded-* headers.
|
|
20
|
+
// Use 1 when behind a single load balancer, true to trust all (less secure).
|
|
21
|
+
// See https://expressjs.com/en/guide/behind-proxies.html
|
|
22
|
+
// @type Number | Boolean
|
|
23
|
+
trustProxy: 1
|
|
24
|
+
|
|
25
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middleware.js
|
|
3
|
+
*
|
|
4
|
+
* This file intercept all requests to make validations before running a controller
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
module.exports = (req, res, next) => {
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
auth: authEncripted
|
|
11
|
+
} = req;
|
|
12
|
+
|
|
13
|
+
if (authEncripted) {
|
|
14
|
+
const decoded = Jwt.decrypt(authEncripted);
|
|
15
|
+
req.auth = (decoded) ? { ...decoded, token: Jwt.getToken(req) } : {};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Remove this line if you need make validations
|
|
19
|
+
next();
|
|
20
|
+
|
|
21
|
+
//
|
|
22
|
+
// You can make validations to check ACL or anything before to run a controller
|
|
23
|
+
// Example:
|
|
24
|
+
//
|
|
25
|
+
|
|
26
|
+
/*
|
|
27
|
+
if (req.auth && +req.auth.role !== 1) {
|
|
28
|
+
const data = {
|
|
29
|
+
success: false,
|
|
30
|
+
error: 'You don\'t have permissions to access this option.'
|
|
31
|
+
}
|
|
32
|
+
res.status(403).jsonp(data);
|
|
33
|
+
} else {
|
|
34
|
+
next();
|
|
35
|
+
}
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
|
|
3
|
+
//
|
|
4
|
+
// Connection: you can use the same connection
|
|
5
|
+
// set a custom Mongo URI connection to manage the sockets
|
|
6
|
+
//
|
|
7
|
+
connection: process.env.SOCKETS_MONGO_URI || null,
|
|
8
|
+
|
|
9
|
+
// Collection to save the records
|
|
10
|
+
collection: process.env.SOCKETS_MONGO_COLLECTION || 'socket.io-adapter-events'
|
|
11
|
+
|
|
12
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Sockets Config
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
|
|
9
|
+
// Enable sockets
|
|
10
|
+
enabled: true,
|
|
11
|
+
|
|
12
|
+
// Socket IO Adapter (redis|mongodb|memory)
|
|
13
|
+
adapter: 'memory',
|
|
14
|
+
|
|
15
|
+
// Socket configuration
|
|
16
|
+
config: {
|
|
17
|
+
|
|
18
|
+
// Transports
|
|
19
|
+
transports: ['websocket', 'polling'],
|
|
20
|
+
|
|
21
|
+
// Socket timeout
|
|
22
|
+
timeout: 4000,
|
|
23
|
+
|
|
24
|
+
// Interval
|
|
25
|
+
interval: 2000,
|
|
26
|
+
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
// Connections
|
|
30
|
+
connections: {
|
|
31
|
+
|
|
32
|
+
users: 0,
|
|
33
|
+
|
|
34
|
+
// Clients connected
|
|
35
|
+
clients: {}
|
|
36
|
+
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
// Event handlers
|
|
40
|
+
// onConnect: (io, socket, clients, counter) => {
|
|
41
|
+
// counter.users++;
|
|
42
|
+
// clients[socket.request.user._id] = socket.id;
|
|
43
|
+
// io.emit('users:counter', counter.users);
|
|
44
|
+
// },
|
|
45
|
+
// onDisconnect: (io, socket, clients, counter) => {
|
|
46
|
+
// counter.users--;
|
|
47
|
+
// delete clients[socket.request.user._id];
|
|
48
|
+
// io.emit('users:counter', counter.users);
|
|
49
|
+
// }
|
|
50
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module.exports = (req, callback) => {
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
origin,
|
|
5
|
+
host,
|
|
6
|
+
} = req.headers || {};
|
|
7
|
+
|
|
8
|
+
const realOrigin = origin || host;
|
|
9
|
+
|
|
10
|
+
const allowedOrigin = [
|
|
11
|
+
'localhost',
|
|
12
|
+
'yourdomain.com'
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
let found = false;
|
|
16
|
+
|
|
17
|
+
allowedOrigin.forEach((o) => {
|
|
18
|
+
|
|
19
|
+
if ((realOrigin || '').indexOf(o) !== -1) {
|
|
20
|
+
found = true;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (found) {
|
|
26
|
+
callback(null, true);
|
|
27
|
+
} else {
|
|
28
|
+
console.log('Invalid origin', realOrigin || 'No Origin');
|
|
29
|
+
callback(new Error(`Invalid origin ${realOrigin} - Socket CORS`));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
|
|
3
|
+
// Examples Chat
|
|
4
|
+
// event:action: folder.YourController.method
|
|
5
|
+
//
|
|
6
|
+
// 'chat:signin': 'sockets.ChatController.signin',
|
|
7
|
+
// 'chat:message': 'sockets.ChatController.save',
|
|
8
|
+
// 'chat:history': 'sockets.ChatController.get'
|
|
9
|
+
|
|
10
|
+
'echo': 'sockets.EchoController.echo'
|
|
11
|
+
|
|
12
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module.exports = (socket, next) => {
|
|
2
|
+
|
|
3
|
+
// Security
|
|
4
|
+
const user = Jwt.socket(socket);
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
_id
|
|
8
|
+
} = user || {};
|
|
9
|
+
|
|
10
|
+
if (!_id) {
|
|
11
|
+
console.log('Sockets Middleware: Invalid ID');
|
|
12
|
+
next(new Error(`Invalid user ${_id || 'or token'}`));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line no-param-reassign
|
|
16
|
+
socket.request.user = user || {};
|
|
17
|
+
|
|
18
|
+
next();
|
|
19
|
+
|
|
20
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pads a string to a certain length with another string.
|
|
3
|
+
* The padding is applied from the left, right, or both sides of the string.
|
|
4
|
+
*
|
|
5
|
+
* Example: {{ strpad('hello world', 20, '*', 'left') }} => '*********hello world'
|
|
6
|
+
*
|
|
7
|
+
* @param {*} str
|
|
8
|
+
* @param {*} _len
|
|
9
|
+
* @param {*} _pad
|
|
10
|
+
* @param {*} _dir
|
|
11
|
+
* @returns String
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
module.exports = (str, _len, _pad, _dir) => {
|
|
15
|
+
|
|
16
|
+
const STR_PAD_LEFT = 1;
|
|
17
|
+
const STR_PAD_RIGHT = 2;
|
|
18
|
+
const STR_PAD_BOTH = 3;
|
|
19
|
+
|
|
20
|
+
const len = _len || 0;
|
|
21
|
+
const pad = _pad || ' ';
|
|
22
|
+
const dir = _dir || STR_PAD_RIGHT;
|
|
23
|
+
|
|
24
|
+
let newStr = '';
|
|
25
|
+
|
|
26
|
+
if (len + 1 >= str.length) {
|
|
27
|
+
|
|
28
|
+
const padlen = len - str.length;
|
|
29
|
+
const right = Math.ceil(padlen / 2);
|
|
30
|
+
const left = padlen - right;
|
|
31
|
+
|
|
32
|
+
switch (dir) {
|
|
33
|
+
case STR_PAD_LEFT:
|
|
34
|
+
newStr = Array(len + 1 - str.length).join(pad) + str;
|
|
35
|
+
break;
|
|
36
|
+
case 'left':
|
|
37
|
+
newStr = Array(len + 1 - str.length).join(pad) + str;
|
|
38
|
+
break;
|
|
39
|
+
case STR_PAD_BOTH:
|
|
40
|
+
newStr = Array(left + 1).join(pad) + str + Array(right + 1).join(pad);
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
newStr = str + Array(len + 1 - str.length).join(pad);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return newStr;
|
|
50
|
+
|
|
51
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// This is an example for a simple controller that renders a view.
|
|
2
|
+
// It is a good starting point for creating a simple web application.
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
|
|
6
|
+
// Method to render the home page
|
|
7
|
+
// Example: domain.com/example/
|
|
8
|
+
get(req, res) {
|
|
9
|
+
|
|
10
|
+
res.render('example/index.html', { title: 'This is an example home page' });
|
|
11
|
+
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
// Method to render the about page
|
|
15
|
+
// Example: domain.com/example/about/
|
|
16
|
+
about(req, res) {
|
|
17
|
+
|
|
18
|
+
res.render('example/about.html', { title: 'This is an example about page' });
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/* global Example */
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* This endpoint is protected by JWT, please disabled it to test
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// This is an example for Full API Rest controller that provides CRUD operations.
|
|
8
|
+
// It is a good starting point for creating a RESTful API.
|
|
9
|
+
// The business logic is implemented in the Example model, which is a good practice
|
|
10
|
+
// to keep the controller thin and focused on handling requests and responses.
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
|
|
14
|
+
// Method to get all records from the model
|
|
15
|
+
// Example: GET /projects/?page=1
|
|
16
|
+
get(req, res) {
|
|
17
|
+
|
|
18
|
+
// Status code: 200 (default)
|
|
19
|
+
res.vsr(Example.getAll(req.query || {}));
|
|
20
|
+
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
// Method to create a new record in the model
|
|
24
|
+
// Example: POST /projects/
|
|
25
|
+
post(req, res) {
|
|
26
|
+
|
|
27
|
+
const {
|
|
28
|
+
body
|
|
29
|
+
} = req || {};
|
|
30
|
+
|
|
31
|
+
// Status code: 201 (created)
|
|
32
|
+
res.vsr(Example.create(body), 201);
|
|
33
|
+
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
// Method to get a record by id from the model
|
|
37
|
+
// Example: GET /projects/:id
|
|
38
|
+
'get :id': (req, res) => {
|
|
39
|
+
|
|
40
|
+
const {
|
|
41
|
+
id
|
|
42
|
+
} = req.params;
|
|
43
|
+
|
|
44
|
+
// Status code: 200 (default)
|
|
45
|
+
res.vsr(Example.getExample(id));
|
|
46
|
+
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// Method to update a record by id in the model
|
|
50
|
+
// Example: PUT /projects/:id
|
|
51
|
+
'put :id': (req, res) => {
|
|
52
|
+
|
|
53
|
+
const {
|
|
54
|
+
id
|
|
55
|
+
} = req.params;
|
|
56
|
+
|
|
57
|
+
const {
|
|
58
|
+
body
|
|
59
|
+
} = req || {};
|
|
60
|
+
|
|
61
|
+
// Status code: 202 (accepted)
|
|
62
|
+
res.vsr(Example.update(id, body), 202);
|
|
63
|
+
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
// Method to delete a record by id from the model
|
|
67
|
+
// Example: DELETE /projects/:id
|
|
68
|
+
'delete :id': (req, res) => {
|
|
69
|
+
|
|
70
|
+
const {
|
|
71
|
+
id
|
|
72
|
+
} = req.params;
|
|
73
|
+
|
|
74
|
+
res.vsr(Example.remove(id), 204);
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This endpoint is protected by JWT, please disable it to test
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Scaffold Controller is a controller that provides CRUD operations for a model.
|
|
6
|
+
// It is a generic controller that can be used to create, read, update, and delete records
|
|
7
|
+
// from a model. It is a good starting point for creating a
|
|
8
|
+
// RESTful API.
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
|
|
12
|
+
// Model to CRUD (create, read, update, and delete) records — must exist as global.ExampleWithScaffold
|
|
13
|
+
scaffold: 'ExampleWithScaffold',
|
|
14
|
+
|
|
15
|
+
// Allowed methods
|
|
16
|
+
allowedMethods: ['get', 'post', 'put', 'delete']
|
|
17
|
+
|
|
18
|
+
};
|