@vulkano/core 1.24.2 → 1.25.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.
@@ -11,6 +11,14 @@ const AllControllers = require('include-all')({
11
11
 
12
12
  const scaffoldController = require('./ScaffoldController');
13
13
 
14
+ // PascalCase controller name -> kebab-case URL segment (MyAccount -> my-account)
15
+ function toKebabCase(str) {
16
+ return str
17
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
18
+ .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
19
+ .toLowerCase();
20
+ }
21
+
14
22
  module.exports = function loadControllersApplication() {
15
23
 
16
24
  const routes = {};
@@ -48,7 +56,7 @@ module.exports = function loadControllersApplication() {
48
56
 
49
57
  }
50
58
 
51
- let controllerName = controller.replace('Controller', '').toLowerCase();
59
+ let controllerName = toKebabCase(controller.replace('Controller', ''));
52
60
 
53
61
  let parts = [];
54
62
  let method = 'get';
@@ -65,7 +73,7 @@ module.exports = function loadControllersApplication() {
65
73
 
66
74
  Object.keys(submodules || []).forEach( (subcontroller) => {
67
75
 
68
- controllerName = subcontroller.replace('Controller', '').toLowerCase();
76
+ controllerName = toKebabCase(subcontroller.replace('Controller', ''));
69
77
  const subcurrent = submodules[subcontroller];
70
78
 
71
79
  const {
@@ -177,3 +185,5 @@ module.exports = function loadControllersApplication() {
177
185
  return routes;
178
186
 
179
187
  };
188
+
189
+ module.exports.toKebabCase = toKebabCase;
@@ -1,67 +1,5 @@
1
- // Field names that are never exposed through populate select, whatever the
2
- // caller asks for — a coarse, name-based backstop for common secret-shaped
3
- // fields (defense in depth on top of the schema's own `select: false`, in
4
- // case a referenced model forgets to mark a sensitive field itself).
5
- const SENSITIVE_FIELD_HINTS = [
6
- 'password', 'passwd', 'secret', 'token', 'apikey', 'api_key',
7
- 'privatekey', 'private_key', 'hash', 'salt', 'ssn', 'creditcard',
8
- 'credit_card', 'cvv', 'pin'
9
- ];
10
-
11
- function isSensitiveByName(field) {
12
- const lower = field.toLowerCase();
13
- return SENSITIVE_FIELD_HINTS.some((hint) => lower.includes(hint));
14
- }
15
-
16
1
  module.exports = {
17
2
 
18
- /**
19
- * Look up the referenced model on the same connection this model was
20
- * compiled on (models here are registered via `db.model(...)`, not the
21
- * global `mongoose.model(...)` registry — see database/mongodb.js — so
22
- * resolving by connection is required for this to ever find it).
23
- *
24
- * @param {String} refModelName mongoose ref (the "ref" schema option)
25
- * @returns {Object|null}
26
- */
27
- _resolveRefModel(refModelName) {
28
-
29
- try {
30
- return (this.db && this.db.model(refModelName)) || mongoose.model(refModelName);
31
- } catch {
32
- return null;
33
- }
34
-
35
- },
36
-
37
- /**
38
- * A field is safe to expose through populate select when it's neither
39
- * name-flagged as sensitive (SENSITIVE_FIELD_HINTS) nor marked
40
- * `select: false` on the REFERENCED model's own schema. If the referenced
41
- * model can't be resolved (e.g. in isolated unit tests), only the
42
- * name-based check applies.
43
- *
44
- * @param {String} refModelName mongoose ref (the "ref" schema option)
45
- * @param {String} field
46
- * @returns {Boolean}
47
- */
48
- _isFieldSafeToExpose(refModelName, field) {
49
-
50
- if (isSensitiveByName(field)) {
51
- return false;
52
- }
53
-
54
- const RefModel = this._resolveRefModel(refModelName);
55
- const refPath = RefModel && RefModel.schema.paths[field];
56
-
57
- if (refPath && refPath.options && refPath.options.select === false) {
58
- return false;
59
- }
60
-
61
- return true;
62
-
63
- },
64
-
65
3
  /**
66
4
  * Parse the populate param into one entry per relation: `name` (trimmed,
67
5
  * lowercased) plus an optional `fields` list. Syntax: relations are
@@ -165,28 +103,7 @@ module.exports = {
165
103
  const populateProps = { path: field };
166
104
 
167
105
  if (entry.fields && entry.fields.length > 0) {
168
-
169
- // Explicit field list: keep only what's safe, as a pure inclusion
170
- // select. If everything requested turns out sensitive, fall back
171
- // to "_id" only — never to the unfiltered full document.
172
- const safeFields = entry.fields.filter((f) => this._isFieldSafeToExpose(ref, f));
173
- populateProps.select = safeFields.length > 0 ? safeFields.join(' ') : '_id';
174
-
175
- } else {
176
-
177
- // Full-doc populate: still must not leak sensitive fields, so
178
- // build an exclusion select for whatever the ref schema/name-hints
179
- // flag on that model — skipped only if nothing needs excluding.
180
- const RefModel = this._resolveRefModel(ref);
181
-
182
- const toExclude = RefModel
183
- ? Object.keys(RefModel.schema.paths).filter((f) => !this._isFieldSafeToExpose(ref, f))
184
- : [];
185
-
186
- if (toExclude.length > 0) {
187
- populateProps.select = toExclude.map((f) => `-${f}`).join(' ');
188
- }
189
-
106
+ populateProps.select = entry.fields.join(' ');
190
107
  }
191
108
 
192
109
  return populateProps;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vulkano/core",
3
- "version": "1.24.2",
3
+ "version": "1.25.0",
4
4
  "description": "A MVC framework using Express 4",
5
5
  "license": "MIT",
6
6
  "author": "Vulkano Team",