jxp 2.10.1 → 2.11.1

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/libs/docs.js CHANGED
@@ -46,29 +46,32 @@ class Docs {
46
46
  }
47
47
  }
48
48
 
49
- metaModel(req, res) {
49
+ metaModel(req, res, next) {
50
50
  try {
51
51
  if (!req.Model) {
52
52
  return res.send(404, { status: "error", error: "Model not found" })
53
53
  }
54
54
  res.send(req.Model.schema.paths);
55
+ next();
55
56
  } catch (err) {
56
57
  console.error(err);
57
58
  return res.send(500, { status: "error", error: err, message: err.toString() });
58
59
  }
59
60
  }
60
61
 
61
- dbDiagram(req, res) {
62
+ dbDiagram(req, res, next) {
62
63
  try {
63
64
  res.send(this.models);
65
+ next();
64
66
  } catch(err) {
65
67
  res.send(500, { status: "error", error: err, message: err.toString() });
66
68
  }
67
69
  }
68
70
 
69
- frontPage(req, res) {
71
+ frontPage(req, res, next) {
70
72
  try {
71
73
  this.renderTemplate(res, "index", {});
74
+ next();
72
75
  } catch(err) {
73
76
  res.send(500, { status: "error", error: err, message: err.toString() });
74
77
  }
@@ -84,7 +87,7 @@ class Docs {
84
87
  }
85
88
  }
86
89
 
87
- model(req, res) {
90
+ model(req, res, next) {
88
91
  try {
89
92
  const model = this.models[req.params.modelname];
90
93
  console.dir(model.schema.opts);
@@ -92,6 +95,7 @@ class Docs {
92
95
  fields.sort();
93
96
  const perms = model.schema.opts.perms;
94
97
  this.renderTemplate(res, "model", { model, fields, perms });
98
+ next();
95
99
  } catch(err) {
96
100
  res.send(500, { status: "error", error: err, message: err.toString() });
97
101
  }
package/libs/jxp.js CHANGED
@@ -49,12 +49,13 @@ const middlewareCheckAdmin = (req, res, next) => {
49
49
  };
50
50
 
51
51
  // Outputs whatever is in res.result as JSON
52
- const outputJSON = (req, res) => {
52
+ const outputJSON = (req, res, next) => {
53
53
  res.send(res.result);
54
+ next();
54
55
  }
55
56
 
56
57
  // Outputs whatever is in res.result as CSV
57
- const outputCSV = (req, res) => {
58
+ const outputCSV = (req, res, next) => {
58
59
  const json2csv = require('json2csv').parse;
59
60
  const opts = { "flatten": true };
60
61
  if (!res.result.data) {
@@ -71,6 +72,7 @@ const outputCSV = (req, res) => {
71
72
  });
72
73
  const csv = json2csv(data, opts);
73
74
  res.end(csv);
75
+ next();
74
76
  } catch (err) {
75
77
  console.error(err);
76
78
  res.send(500, { status: "error", error: err, message: err.toString() });
@@ -78,9 +80,16 @@ const outputCSV = (req, res) => {
78
80
  }
79
81
 
80
82
  // Actions (verbs)
81
- const actionGet = async (req, res, next) => {
83
+ const actionGet = async (req, res) => {
82
84
  const opname = `get ${req.modelname} ${ops++}`;
83
85
  console.time(opname);
86
+ try {
87
+ if (res.user) {
88
+ req.Model.__user = res.user;
89
+ }
90
+ } catch(err) {
91
+ console.error(err);
92
+ }
84
93
  const parseSearch = function(search) {
85
94
  let result = {};
86
95
  for (let i in search) {
@@ -177,7 +186,6 @@ const actionGet = async (req, res, next) => {
177
186
  result.data = await q.exec();
178
187
  res.result = result;
179
188
  if (debug) console.timeEnd(opname);
180
- next();
181
189
  } catch(err) {
182
190
  console.error(new Date(), err);
183
191
  if (debug) console.timeEnd(opname);
@@ -189,6 +197,9 @@ const actionGetOne = async (req, res) => {
189
197
  const opname = `getOne ${req.modelname}/${req.params.item_id} ${ops++}`;
190
198
  console.time(opname);
191
199
  try {
200
+ if (res.user) {
201
+ req.Model.__user = res.user;
202
+ }
192
203
  const data = await getOne(req.Model, req.params.item_id, req.query);
193
204
  res.send({ data });
194
205
  if (debug) console.timeEnd(opname);
@@ -203,7 +214,7 @@ const actionGetOne = async (req, res) => {
203
214
  }
204
215
  };
205
216
 
206
- const actionPost = async (req, res, next) => {
217
+ const actionPost = async (req, res) => {
207
218
  const opname = `post ${req.modelname} ${ops++}`;
208
219
  console.time(opname);
209
220
  try {
@@ -226,7 +237,6 @@ const actionPost = async (req, res, next) => {
226
237
  data: item
227
238
  });
228
239
  if (debug) console.timeEnd(opname);
229
- next();
230
240
  } catch (err) {
231
241
  console.error(new Date(), err);
232
242
  if (debug) console.timeEnd(opname);
@@ -234,7 +244,7 @@ const actionPost = async (req, res, next) => {
234
244
  }
235
245
  };
236
246
 
237
- const actionPut = async (req, res, next) => {
247
+ const actionPut = async (req, res) => {
238
248
  const opname = `put ${req.modelname}/${req.params.item_id} ${ops++}`;
239
249
  console.time(opname);
240
250
  try {
@@ -263,7 +273,6 @@ const actionPut = async (req, res, next) => {
263
273
  data: data
264
274
  });
265
275
  if (debug) console.timeEnd(opname);
266
- next();
267
276
  } catch (err) {
268
277
  console.error(new Date(), err);
269
278
  if (debug) console.timeEnd(opname);
@@ -272,24 +281,10 @@ const actionPut = async (req, res, next) => {
272
281
  }
273
282
  };
274
283
 
275
- const actionUpdate = async (req, res, next) => {
284
+ const actionUpdate = async (req, res) => {
276
285
  const opname = `update ${req.modelname}/${req.params.item_id} ${ops++}`;
277
286
  console.time(opname);
278
287
  try {
279
- // let item = await req.Model.findById(req.params.item_id);
280
- // if (!item) {
281
- // console.error(new Date(), "Document not found");
282
- // res.send(404, { status: "error", message: "Document not found" });
283
- // return;
284
- // }
285
- // _populateItem(item, datamunging.deserialize(req.body));
286
- // _versionItem(item);
287
- // if (res.user) {
288
- // item.__user = res.user;
289
- // item._updated_by_id = res.user._id;
290
- // }
291
- // const data = await item.save();
292
- console.log({ body: req.body });
293
288
  let body_data = datamunging.deserialize(req.body);
294
289
  const data = await req.Model.update({ _id: req.params.item_id }, body_data);
295
290
  let silence = req.params._silence;
@@ -304,7 +299,6 @@ const actionUpdate = async (req, res, next) => {
304
299
  data
305
300
  });
306
301
  if (debug) console.timeEnd(opname);
307
- next();
308
302
  } catch (err) {
309
303
  console.error(new Date(), err);
310
304
  if (debug) console.timeEnd(opname);
@@ -313,7 +307,7 @@ const actionUpdate = async (req, res, next) => {
313
307
  }
314
308
  };
315
309
 
316
- const actionDelete = async (req, res, next) => {
310
+ const actionDelete = async (req, res) => {
317
311
  const permaDelete = req.query._permaDelete;
318
312
  const cascade = req.query._cascade;
319
313
  let silence = req.query._silence || (req.body && req.body._silence);
@@ -384,7 +378,6 @@ const actionDelete = async (req, res, next) => {
384
378
  message: `${req.modelname}/${ req.params.item_id } deleted`
385
379
  });
386
380
  if (debug) console.timeEnd(opname);
387
- next();
388
381
  } catch(err) {
389
382
  console.error(new Date(), err);
390
383
  if (debug) console.timeEnd(opname);
@@ -393,7 +386,7 @@ const actionDelete = async (req, res, next) => {
393
386
  }
394
387
  };
395
388
 
396
- const actionCount = async (req, res, next) => {
389
+ const actionCount = async (req, res) => {
397
390
  const opname = `count ${req.modelname} ${ops++}`;
398
391
  console.time(opname);
399
392
  const parseSearch = function(search) {
@@ -422,7 +415,6 @@ const actionCount = async (req, res, next) => {
422
415
  const count = await req.Model.countDocuments(filters).exec();
423
416
  res.result = { count };
424
417
  if (debug) console.timeEnd(opname);
425
- next();
426
418
  } catch(err) {
427
419
  console.error(new Date(), err);
428
420
  if (debug) console.timeEnd(opname);
@@ -443,29 +435,21 @@ const actionCall = async (req, res) => {
443
435
  }
444
436
  };
445
437
 
446
- const actionCallItem = (req, res) => {
447
- req.Model.findById(req.params.item_id, function(err, item) {
438
+ const actionCallItem = async (req, res) => {
439
+ try {
440
+ const item = req.Model.findById(req.params.item_id);
448
441
  if (!item) {
449
442
  res.send(404, "Document not found for " + req.params.method_name);
450
443
  return;
451
444
  }
452
- if (err) {
453
- console.trace(err);
454
- res.send(500, { status: "error", message: err.toString() });
455
- return;
456
- }
457
445
  req.params.__user = res.user || null;
458
- req.Model[req.params.method_name](item).then(
459
- function(item) {
460
- // console.log({ action_id: 7, action: "Method called", type: req.modelname, id: item._id, method: req.params.method_name, user: filterLogUser(res.user) });
461
- res.json(item);
462
- },
463
- function(err) {
464
- console.trace(err);
465
- res.send(500, { status: "error", message: err.toString() });
466
- }
467
- );
468
- });
446
+ const result = await req.Model[req.params.method_name](item);
447
+ res.json(result);
448
+
449
+ } catch(err) {
450
+ console.trace(err);
451
+ res.send(500, { status: "error", message: err.toString() });
452
+ }
469
453
  };
470
454
 
471
455
  // Actions (verbs)
@@ -573,7 +557,7 @@ const actionAggregate = async (req, res) => {
573
557
  };
574
558
 
575
559
  // Actions (verbs)
576
- const actionBulkWrite = async (req, res, next) => {
560
+ const actionBulkWrite = async (req, res) => {
577
561
  if (!req.body || !Array.isArray(req.body)) {
578
562
  console.error("query missing or not of type array")
579
563
  return res.send(500, { status: "error", message: "query missing or not of type array" });
@@ -588,7 +572,6 @@ const actionBulkWrite = async (req, res, next) => {
588
572
  res.result = result;
589
573
  if (debug) console.timeEnd(opname);
590
574
  res.json(result);
591
- next();
592
575
  } catch (err) {
593
576
  console.error(new Date(), err);
594
577
  if (debug) console.timeEnd(opname);
@@ -828,8 +811,7 @@ const JXP = function(options) {
828
811
  }
829
812
  },
830
813
  post_hooks: {
831
- login: async (req, res, next) => {
832
- next();
814
+ login: async () => {
833
815
  },
834
816
  },
835
817
  cache_timeout: "5 minutes",
package/libs/login.js CHANGED
@@ -83,7 +83,7 @@ const oauth = (req, res, next) => { // Log in through an OAuth2 provider, define
83
83
  res.redirect(uri, next);
84
84
  }
85
85
 
86
- const oauth_callback = async (req, res, next) => {
86
+ const oauth_callback = async (req, res) => {
87
87
  const provider = req.params.provider;
88
88
  const provider_config = req.config.oauth[provider];
89
89
  const code = req.query.code;
@@ -126,19 +126,19 @@ const oauth_callback = async (req, res, next) => {
126
126
  var jwt_token = jwt.sign({ apikey: apikey.apikey, user: user }, req.config.shared_secret, {
127
127
  expiresIn: "1m"
128
128
  });
129
- res.redirect(`${req.config.oauth.success_uri}?token=${jwt_token}`, next);
129
+ res.redirect(`${req.config.oauth.success_uri}?token=${jwt_token}`);
130
130
  } catch (err) {
131
131
  console.error(err);
132
132
  if (typeof err === 'string' || err instanceof String) {
133
- res.redirect(`${req.config.oauth.fail_uri}?error=${err}&provider=${provider}`, next);
133
+ res.redirect(`${req.config.oauth.fail_uri}?error=${err}&provider=${provider}`);
134
134
  } else {
135
- res.redirect(`${req.config.oauth.fail_uri}?error=unknown&provider=${provider}`, next);
135
+ res.redirect(`${req.config.oauth.fail_uri}?error=unknown&provider=${provider}`);
136
136
  }
137
137
  return;
138
138
  }
139
139
  }
140
140
 
141
- const login = async (req, res, next) => {
141
+ const login = async (req, res) => {
142
142
  const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
143
143
  let email = req.params.email || req.body.email;
144
144
  let password = req.params.password || req.body.password;
@@ -170,7 +170,6 @@ const login = async (req, res, next) => {
170
170
  refresh_token_expires: security.tokenExpires(refreshtoken),
171
171
  provider: token.provider,
172
172
  });
173
- next();
174
173
  } catch (err) {
175
174
  res.send(401, { status: "fail", message: "Authentication failed", err });
176
175
  console.error(new Date(), `Authentication failed`, ip, err);
@@ -178,7 +177,7 @@ const login = async (req, res, next) => {
178
177
  }
179
178
  }
180
179
 
181
- const getJWT = (req, res) => {
180
+ const getJWT = async (req, res) => {
182
181
  var user = null;
183
182
  if (!res.user.admin) {
184
183
  res.send(403, { status: "fail", message: "Unauthorized" });
@@ -189,27 +188,26 @@ const getJWT = (req, res) => {
189
188
  res.send(400, { status: "fail", message: "Email required" });
190
189
  return;
191
190
  }
192
- User.findOne({ email: email }, function (err, result) {
193
- if (err) {
194
- res.send(500, { status: "error", error: err });
195
- return;
196
- }
191
+ try {
192
+ const result = await User.findOne({ email: email });
197
193
  if (!result || !result._id) {
198
194
  res.send(404, { status: "fail", message: "User not found" });
199
195
  return;
200
196
  }
201
197
  user = result;
202
- security.generateApiKey(user._id)
203
- .then(function (result) {
204
- var token = jwt.sign({ apikey: result.apikey, email: user.email, id: user._id }, req.config.shared_secret, {
205
- expiresIn: "2d"
206
- });
207
- res.send({ email: user.email, token: token });
208
- }, function () {
209
- res.send(403, { status: "fail", message: "Unauthorized" });
198
+ try {
199
+ const apikey = await security.generateApiKey(user._id)
200
+ var token = jwt.sign({ apikey: apikey.apikey, email: user.email, id: user._id }, req.config.shared_secret, {
201
+ expiresIn: "2d"
210
202
  });
211
- });
212
- return;
203
+ res.send({ email: user.email, token: token });
204
+ } catch (err) {
205
+ res.send(403, { status: "fail", message: "Unauthorized" });
206
+ return;
207
+ }
208
+ } catch (err) {
209
+ res.send(500, { status: "error", error: err });
210
+ }
213
211
  }
214
212
 
215
213
  const Login = {
package/libs/security.js CHANGED
@@ -204,7 +204,7 @@ const revokeRefreshToken = async user_id => {
204
204
  return true;
205
205
  }
206
206
 
207
- const refresh = async (req, res, next) => {
207
+ const refresh = async (req, res) => {
208
208
  try {
209
209
  if(req.headers.authorization && req.headers.authorization.trim().toLowerCase().indexOf("bearer") === 0) {
210
210
  const refresh_token = await RefreshToken.findOne({ refresh_token: bearerAuthData(req) }).exec();
@@ -221,27 +221,24 @@ const refresh = async (req, res, next) => {
221
221
  refresh_token: new_refresh_token.refresh_token,
222
222
  refresh_token_expires: tokenExpires(new_refresh_token)
223
223
  });
224
- next();
225
224
  } else {
226
225
  throw("Missing refresh token")
227
226
  }
228
- next();
229
227
  } catch (err) {
230
228
  console.error(err);
231
229
  return fail(res, 403, err);
232
230
  }
233
231
  }
234
232
 
235
- const login = async (req, res, next) => {
233
+ const login = async (req, res) => {
236
234
  try {
237
235
  const authenticate_result = await authenticate(req);
238
236
  if (!authenticate_result) {
239
237
  res.user = null;
240
238
  res.groups = [];
241
- return next();
239
+ return;
242
240
  }
243
241
  res = Object.assign(res, authenticate_result);
244
- next();
245
242
  } catch(err) {
246
243
  console.error(err);
247
244
  return fail(res, 403, err);
@@ -282,7 +279,7 @@ const authenticate = async req => {
282
279
  }
283
280
  }
284
281
 
285
- const auth = async (req, res, next) => {
282
+ const auth = async (req, res) => {
286
283
  // Check against model as to whether we're allowed to edit this model
287
284
  if (!req.Model) {
288
285
  console.error("Model missing");
@@ -304,7 +301,6 @@ const auth = async (req, res, next) => {
304
301
  return fail(res, 500, "Unsupported operation: " + req.method);
305
302
  }
306
303
  await check_perms(res.user, res.groups, req.Model, method, req.params.item_id);
307
- next();
308
304
  } catch(err) {
309
305
  console.error(err);
310
306
  return fail(res, 403, { status: "Unauthorized", error: err });
@@ -312,13 +308,12 @@ const auth = async (req, res, next) => {
312
308
  };
313
309
 
314
310
  // Bulk auth requires all CRUD permissions
315
- const bulkAuth = async (req, res, next) => {
311
+ const bulkAuth = async (req, res,) => {
316
312
  try {
317
313
  await check_perms(res.user, res.groups, req.Model, "c");
318
314
  await check_perms(res.user, res.groups, req.Model, "r");
319
315
  await check_perms(res.user, res.groups, req.Model, "u");
320
316
  await check_perms(res.user, res.groups, req.Model, "d");
321
- next();
322
317
  } catch (err) {
323
318
  console.error(err);
324
319
  return fail(res, 403, { status: "Unauthorized", error: err });
package/libs/setup.js CHANGED
@@ -9,14 +9,12 @@ const init = config => {
9
9
  User = require(path.join(config.model_dir, "user_model"));
10
10
  }
11
11
 
12
- const checkUserDoesNotExist = async (req, res, next) => {
12
+ const checkUserDoesNotExist = async (req, res) => {
13
13
  try {
14
14
  const count = await User.countDocuments();
15
15
  if (count) {
16
- const users = await User.find();
17
16
  return res.send(403, { status: "failed", error: "Cannot setup if user exists" });
18
17
  }
19
- return next();
20
18
  } catch(err) {
21
19
  console.error(err);
22
20
  res.send(500, { status: "error", error: err.message });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jxp",
3
3
  "description:": "An opinionated RESTful API library based on Mongoose and Restify. Make an API by just writing Mongoose models.",
4
- "version": "2.10.1",
4
+ "version": "2.11.1",
5
5
  "private": false,
6
6
  "main": "libs/jxp.js",
7
7
  "scripts": {
@@ -27,38 +27,39 @@
27
27
  "url": "https://github.com/j-norwood-young/jexpress-2/issues"
28
28
  },
29
29
  "dependencies": {
30
- "axios": "^0.24.0",
30
+ "axios": "^1.2.0",
31
31
  "bcryptjs": "^2.4.3",
32
- "commander": "^8.3.0",
33
- "config": "^3.3.6",
34
- "dotenv": "^10.0.0",
35
- "glob": "7.2.0",
32
+ "commander": "^9.4.1",
33
+ "config": "^3.3.8",
34
+ "dotenv": "^16.0.3",
35
+ "glob": "8.0.3",
36
36
  "js-yaml": "4.1.0",
37
- "json2csv": "^5.0.6",
37
+ "json2csv": "^5.0.7",
38
38
  "jsonwebtoken": "^8.5.1",
39
- "jstransformer-markdown-it": "^2.1.0",
40
- "jxp-helper": "^1.3.14",
39
+ "jstransformer-markdown-it": "^3.0.0",
40
+ "jxp-helper": "^1.4.0",
41
41
  "mkdirp": "^1.0.4",
42
- "mongoose": "6.0.13",
42
+ "mongoose": "6.7.3",
43
43
  "mongoose-friendly": "^0.1.4",
44
44
  "morgan": "^1.10.0",
45
- "nodemailer": "^6.7.1",
45
+ "nodemailer": "^6.8.0",
46
46
  "nodemailer-smtp-transport": "^2.7.4",
47
47
  "path": "^0.12.7",
48
48
  "pug": "^3.0.2",
49
49
  "querystring": "^0.2.1",
50
50
  "rand-token": "^1.0.1",
51
51
  "readline-sync": "^1.4.10",
52
- "restify": "^8.6.0",
52
+ "restify": "^9.0.0",
53
53
  "restify-cors-middleware": "^1.1.1",
54
- "traverse": "^0.6.6",
55
- "underscore": "^1.13.1",
56
- "ws": "^8.2.3"
54
+ "traverse": "^0.6.7",
55
+ "underscore": "^1.13.6",
56
+ "ws": "^8.11.0"
57
57
  },
58
58
  "devDependencies": {
59
- "chai": "^4.3.4",
59
+ "chai": "^4.3.7",
60
60
  "chai-http": "^4.3.0",
61
- "mocha": "^9.1.3",
62
- "should": "^13.2.3"
61
+ "mocha": "^10.1.0",
62
+ "should": "^13.2.3",
63
+ "moment": "^2.29.4"
63
64
  }
64
65
  }