@strapi/utils 5.56.0 → 5.58.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.
Files changed (149) hide show
  1. package/dist/async.js +2 -2
  2. package/dist/async.js.map +1 -1
  3. package/dist/async.mjs +1 -1
  4. package/dist/async.mjs.map +1 -1
  5. package/dist/content-types.d.ts.map +1 -1
  6. package/dist/content-types.js +8 -9
  7. package/dist/content-types.js.map +1 -1
  8. package/dist/content-types.mjs +6 -7
  9. package/dist/content-types.mjs.map +1 -1
  10. package/dist/convert-query-params.d.ts.map +1 -1
  11. package/dist/convert-query-params.js +33 -34
  12. package/dist/convert-query-params.js.map +1 -1
  13. package/dist/convert-query-params.mjs +23 -24
  14. package/dist/convert-query-params.mjs.map +1 -1
  15. package/dist/format-yup-error.js +3 -3
  16. package/dist/format-yup-error.js.map +1 -1
  17. package/dist/format-yup-error.mjs +1 -1
  18. package/dist/format-yup-error.mjs.map +1 -1
  19. package/dist/hooks.js +3 -3
  20. package/dist/hooks.js.map +1 -1
  21. package/dist/hooks.mjs +2 -2
  22. package/dist/hooks.mjs.map +1 -1
  23. package/dist/pagination.d.ts.map +1 -1
  24. package/dist/pagination.js +15 -18
  25. package/dist/pagination.js.map +1 -1
  26. package/dist/pagination.mjs +15 -18
  27. package/dist/pagination.mjs.map +1 -1
  28. package/dist/policy.d.ts +1 -1
  29. package/dist/policy.d.ts.map +1 -1
  30. package/dist/policy.js +1 -3
  31. package/dist/policy.js.map +1 -1
  32. package/dist/policy.mjs +1 -3
  33. package/dist/policy.mjs.map +1 -1
  34. package/dist/primitives/objects.d.ts +7 -1
  35. package/dist/primitives/objects.d.ts.map +1 -1
  36. package/dist/primitives/objects.js +5 -0
  37. package/dist/primitives/objects.js.map +1 -1
  38. package/dist/primitives/objects.mjs +5 -1
  39. package/dist/primitives/objects.mjs.map +1 -1
  40. package/dist/primitives/strings.d.ts.map +1 -1
  41. package/dist/primitives/strings.js +3 -7
  42. package/dist/primitives/strings.js.map +1 -1
  43. package/dist/primitives/strings.mjs +3 -7
  44. package/dist/primitives/strings.mjs.map +1 -1
  45. package/dist/provider-factory.js +4 -4
  46. package/dist/provider-factory.js.map +1 -1
  47. package/dist/provider-factory.mjs +1 -1
  48. package/dist/provider-factory.mjs.map +1 -1
  49. package/dist/relations.js +2 -2
  50. package/dist/relations.js.map +1 -1
  51. package/dist/relations.mjs +1 -1
  52. package/dist/relations.mjs.map +1 -1
  53. package/dist/sanitize/index.d.ts.map +1 -1
  54. package/dist/sanitize/index.js +8 -8
  55. package/dist/sanitize/index.js.map +1 -1
  56. package/dist/sanitize/index.mjs +7 -7
  57. package/dist/sanitize/index.mjs.map +1 -1
  58. package/dist/sanitize/sanitizers.js +10 -10
  59. package/dist/sanitize/sanitizers.js.map +1 -1
  60. package/dist/sanitize/sanitizers.mjs +4 -4
  61. package/dist/sanitize/sanitizers.mjs.map +1 -1
  62. package/dist/sanitize/visitors/remove-disallowed-fields.js +4 -4
  63. package/dist/sanitize/visitors/remove-disallowed-fields.js.map +1 -1
  64. package/dist/sanitize/visitors/remove-disallowed-fields.mjs +3 -3
  65. package/dist/sanitize/visitors/remove-disallowed-fields.mjs.map +1 -1
  66. package/dist/sanitize/visitors/remove-restricted-fields.js +2 -2
  67. package/dist/sanitize/visitors/remove-restricted-fields.js.map +1 -1
  68. package/dist/sanitize/visitors/remove-restricted-fields.mjs +2 -2
  69. package/dist/sanitize/visitors/remove-restricted-fields.mjs.map +1 -1
  70. package/dist/sanitize/visitors/remove-restricted-relations.js +9 -9
  71. package/dist/sanitize/visitors/remove-restricted-relations.js.map +1 -1
  72. package/dist/sanitize/visitors/remove-restricted-relations.mjs +4 -4
  73. package/dist/sanitize/visitors/remove-restricted-relations.mjs.map +1 -1
  74. package/dist/security.d.ts.map +1 -1
  75. package/dist/security.js +3 -3
  76. package/dist/security.js.map +1 -1
  77. package/dist/security.mjs +3 -3
  78. package/dist/security.mjs.map +1 -1
  79. package/dist/set-creator-fields.d.ts +4 -1
  80. package/dist/set-creator-fields.d.ts.map +1 -1
  81. package/dist/set-creator-fields.js +7 -4
  82. package/dist/set-creator-fields.js.map +1 -1
  83. package/dist/set-creator-fields.mjs +7 -4
  84. package/dist/set-creator-fields.mjs.map +1 -1
  85. package/dist/traverse/factory.js +8 -8
  86. package/dist/traverse/factory.js.map +1 -1
  87. package/dist/traverse/factory.mjs +8 -8
  88. package/dist/traverse/factory.mjs.map +1 -1
  89. package/dist/traverse/query-fields.js +7 -7
  90. package/dist/traverse/query-fields.js.map +1 -1
  91. package/dist/traverse/query-fields.mjs +3 -3
  92. package/dist/traverse/query-fields.mjs.map +1 -1
  93. package/dist/traverse/query-filters.js +12 -12
  94. package/dist/traverse/query-filters.js.map +1 -1
  95. package/dist/traverse/query-filters.mjs +7 -7
  96. package/dist/traverse/query-filters.mjs.map +1 -1
  97. package/dist/traverse/query-populate.d.ts.map +1 -1
  98. package/dist/traverse/query-populate.js +21 -21
  99. package/dist/traverse/query-populate.js.map +1 -1
  100. package/dist/traverse/query-populate.mjs +12 -12
  101. package/dist/traverse/query-populate.mjs.map +1 -1
  102. package/dist/traverse/query-sort.d.ts.map +1 -1
  103. package/dist/traverse/query-sort.js +16 -16
  104. package/dist/traverse/query-sort.js.map +1 -1
  105. package/dist/traverse/query-sort.mjs +6 -6
  106. package/dist/traverse/query-sort.mjs.map +1 -1
  107. package/dist/traverse-entity.d.ts.map +1 -1
  108. package/dist/traverse-entity.js +18 -18
  109. package/dist/traverse-entity.js.map +1 -1
  110. package/dist/traverse-entity.mjs +16 -16
  111. package/dist/traverse-entity.mjs.map +1 -1
  112. package/dist/validate/index.d.ts.map +1 -1
  113. package/dist/validate/index.js +5 -5
  114. package/dist/validate/index.js.map +1 -1
  115. package/dist/validate/index.mjs +3 -3
  116. package/dist/validate/index.mjs.map +1 -1
  117. package/dist/validate/utils.d.ts +2 -1
  118. package/dist/validate/utils.d.ts.map +1 -1
  119. package/dist/validate/utils.js +4 -4
  120. package/dist/validate/utils.js.map +1 -1
  121. package/dist/validate/utils.mjs +4 -4
  122. package/dist/validate/utils.mjs.map +1 -1
  123. package/dist/validate/validators.d.ts.map +1 -1
  124. package/dist/validate/validators.js +17 -9
  125. package/dist/validate/validators.js.map +1 -1
  126. package/dist/validate/validators.mjs +14 -6
  127. package/dist/validate/validators.mjs.map +1 -1
  128. package/dist/validate/visitors/throw-disallowed-fields.js +4 -4
  129. package/dist/validate/visitors/throw-disallowed-fields.js.map +1 -1
  130. package/dist/validate/visitors/throw-disallowed-fields.mjs +3 -3
  131. package/dist/validate/visitors/throw-disallowed-fields.mjs.map +1 -1
  132. package/dist/validate/visitors/throw-restricted-fields.js +2 -2
  133. package/dist/validate/visitors/throw-restricted-fields.js.map +1 -1
  134. package/dist/validate/visitors/throw-restricted-fields.mjs +2 -2
  135. package/dist/validate/visitors/throw-restricted-fields.mjs.map +1 -1
  136. package/dist/validate/visitors/throw-restricted-relations.js +6 -6
  137. package/dist/validate/visitors/throw-restricted-relations.js.map +1 -1
  138. package/dist/validate/visitors/throw-restricted-relations.mjs +2 -2
  139. package/dist/validate/visitors/throw-restricted-relations.mjs.map +1 -1
  140. package/dist/validators.js +3 -3
  141. package/dist/validators.js.map +1 -1
  142. package/dist/validators.mjs +3 -3
  143. package/dist/validators.mjs.map +1 -1
  144. package/dist/yup.d.ts.map +1 -1
  145. package/dist/yup.js +2 -3
  146. package/dist/yup.js.map +1 -1
  147. package/dist/yup.mjs +3 -4
  148. package/dist/yup.mjs.map +1 -1
  149. package/package.json +4 -4
@@ -1,4 +1,4 @@
1
- import { isArray, isString, isNil, toPath } from 'lodash/fp';
1
+ import { isString, toPath } from 'lodash';
2
2
 
3
3
  var removeDisallowedFields = ((allowedFields = null)=>({ key, path: { attribute: path } }, { remove })=>{
4
4
  // All fields are allowed
@@ -6,10 +6,10 @@ var removeDisallowedFields = ((allowedFields = null)=>({ key, path: { attribute:
6
6
  return;
7
7
  }
8
8
  // Throw on invalid formats
9
- if (!(isArray(allowedFields) && allowedFields.every(isString))) {
9
+ if (!(Array.isArray(allowedFields) && allowedFields.every(isString))) {
10
10
  throw new TypeError(`Expected array of strings for allowedFields but got "${typeof allowedFields}"`);
11
11
  }
12
- if (isNil(path)) {
12
+ if (path == null) {
13
13
  return;
14
14
  }
15
15
  const containedPaths = getContainedPaths(path);
@@ -1 +1 @@
1
- {"version":3,"file":"remove-disallowed-fields.mjs","sources":["../../../src/sanitize/visitors/remove-disallowed-fields.ts"],"sourcesContent":["import { isArray, isNil, isString, toPath } from 'lodash/fp';\nimport type { Visitor } from '../../traverse/factory';\n\nexport default (allowedFields: string[] | null = null): Visitor =>\n ({ key, path: { attribute: path } }, { remove }) => {\n // All fields are allowed\n if (allowedFields === null) {\n return;\n }\n\n // Throw on invalid formats\n if (!(isArray(allowedFields) && allowedFields.every(isString))) {\n throw new TypeError(\n `Expected array of strings for allowedFields but got \"${typeof allowedFields}\"`\n );\n }\n\n if (isNil(path)) {\n return;\n }\n\n const containedPaths = getContainedPaths(path);\n\n /**\n * Tells if the current path should be kept or not based\n * on the success of the check functions for any of the allowed paths.\n *\n * The check functions are defined as follow:\n *\n * `containedPaths.includes(p)`\n * @example\n * ```js\n * const path = 'foo.bar.field';\n * const p = 'foo.bar';\n * // it should match\n *\n * const path = 'foo.bar.field';\n * const p = 'bar.foo';\n * // it shouldn't match\n *\n * const path = 'foo.bar';\n * const p = 'foo.bar.field';\n * // it should match but isn't handled by this check\n * ```\n *\n * `p.startsWith(`${path}.`)`\n * @example\n * ```js\n * const path = 'foo.bar';\n * const p = 'foo.bar.field';\n * // it should match\n *\n * const path = 'foo.bar.field';\n * const p = 'bar.foo';\n * // it shouldn't match\n *\n * const path = 'foo.bar.field';\n * const p = 'foo.bar';\n * // it should match but isn't handled by this check\n * ```\n */\n const isPathAllowed = allowedFields.some(\n (p) => containedPaths.includes(p) || p.startsWith(`${path}.`)\n );\n\n if (isPathAllowed) {\n return;\n }\n\n // Remove otherwise\n remove(key);\n };\n\n/**\n * Retrieve the list of allowed paths based on the given path\n *\n * @example\n * ```js\n * const containedPaths = getContainedPaths('foo');\n * // ['foo']\n *\n * * const containedPaths = getContainedPaths('foo.bar');\n * // ['foo', 'foo.bar']\n *\n * * const containedPaths = getContainedPaths('foo.bar.field');\n * // ['foo', 'foo.bar', 'foo.bar.field']\n * ```\n */\nconst getContainedPaths = (path: string) => {\n const parts = toPath(path);\n\n return parts.reduce((acc, value, index, list) => {\n return [...acc, list.slice(0, index + 1).join('.')];\n }, [] as string[]);\n};\n"],"names":["allowedFields","key","path","attribute","remove","isArray","every","isString","TypeError","isNil","containedPaths","getContainedPaths","isPathAllowed","some","p","includes","startsWith","parts","toPath","reduce","acc","value","index","list","slice","join"],"mappings":";;AAGA,6BAAe,CAAA,CAACA,aAAAA,GAAiC,IAAI,GACnD,CAAC,EAAEC,GAAG,EAAEC,IAAAA,EAAM,EAAEC,WAAWD,IAAI,EAAE,EAAE,EAAE,EAAEE,MAAM,EAAE,GAAA;;AAE7C,QAAA,IAAIJ,kBAAkB,IAAA,EAAM;AAC1B,YAAA;AACF,QAAA;;QAGA,IAAI,EAAEK,OAAAA,CAAQL,aAAAA,CAAAA,IAAkBA,cAAcM,KAAK,CAACC,SAAQ,CAAA,EAAI;YAC9D,MAAM,IAAIC,UACR,CAAC,qDAAqD,EAAE,OAAOR,aAAAA,CAAc,CAAC,CAAC,CAAA;AAEnF,QAAA;AAEA,QAAA,IAAIS,MAAMP,IAAAA,CAAAA,EAAO;AACf,YAAA;AACF,QAAA;AAEA,QAAA,MAAMQ,iBAAiBC,iBAAAA,CAAkBT,IAAAA,CAAAA;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCC,QACD,MAAMU,aAAAA,GAAgBZ,aAAAA,CAAca,IAAI,CACtC,CAACC,CAAAA,GAAMJ,cAAAA,CAAeK,QAAQ,CAACD,MAAMA,CAAAA,CAAEE,UAAU,CAAC,CAAA,EAAGd,IAAAA,CAAK,CAAC,CAAC,CAAA,CAAA;AAG9D,QAAA,IAAIU,aAAAA,EAAe;AACjB,YAAA;AACF,QAAA;;QAGAR,MAAAA,CAAOH,GAAAA,CAAAA;AACT,IAAA,CAAA;AAEF;;;;;;;;;;;;;;IAeA,MAAMU,oBAAoB,CAACT,IAAAA,GAAAA;AACzB,IAAA,MAAMe,QAAQC,MAAAA,CAAOhB,IAAAA,CAAAA;AAErB,IAAA,OAAOe,MAAME,MAAM,CAAC,CAACC,GAAAA,EAAKC,OAAOC,KAAAA,EAAOC,IAAAA,GAAAA;QACtC,OAAO;AAAIH,YAAAA,GAAAA,GAAAA;AAAKG,YAAAA,IAAAA,CAAKC,KAAK,CAAC,CAAA,EAAGF,KAAAA,GAAQ,CAAA,CAAA,CAAGG,IAAI,CAAC,GAAA;AAAK,SAAA;AACrD,IAAA,CAAA,EAAG,EAAE,CAAA;AACP,CAAA;;;;"}
1
+ {"version":3,"file":"remove-disallowed-fields.mjs","sources":["../../../src/sanitize/visitors/remove-disallowed-fields.ts"],"sourcesContent":["import { isString, toPath } from 'lodash';\nimport type { Visitor } from '../../traverse/factory';\n\nexport default (allowedFields: string[] | null = null): Visitor =>\n ({ key, path: { attribute: path } }, { remove }) => {\n // All fields are allowed\n if (allowedFields === null) {\n return;\n }\n\n // Throw on invalid formats\n if (!(Array.isArray(allowedFields) && allowedFields.every(isString))) {\n throw new TypeError(\n `Expected array of strings for allowedFields but got \"${typeof allowedFields}\"`\n );\n }\n\n if (path == null) {\n return;\n }\n\n const containedPaths = getContainedPaths(path);\n\n /**\n * Tells if the current path should be kept or not based\n * on the success of the check functions for any of the allowed paths.\n *\n * The check functions are defined as follow:\n *\n * `containedPaths.includes(p)`\n * @example\n * ```js\n * const path = 'foo.bar.field';\n * const p = 'foo.bar';\n * // it should match\n *\n * const path = 'foo.bar.field';\n * const p = 'bar.foo';\n * // it shouldn't match\n *\n * const path = 'foo.bar';\n * const p = 'foo.bar.field';\n * // it should match but isn't handled by this check\n * ```\n *\n * `p.startsWith(`${path}.`)`\n * @example\n * ```js\n * const path = 'foo.bar';\n * const p = 'foo.bar.field';\n * // it should match\n *\n * const path = 'foo.bar.field';\n * const p = 'bar.foo';\n * // it shouldn't match\n *\n * const path = 'foo.bar.field';\n * const p = 'foo.bar';\n * // it should match but isn't handled by this check\n * ```\n */\n const isPathAllowed = allowedFields.some(\n (p) => containedPaths.includes(p) || p.startsWith(`${path}.`)\n );\n\n if (isPathAllowed) {\n return;\n }\n\n // Remove otherwise\n remove(key);\n };\n\n/**\n * Retrieve the list of allowed paths based on the given path\n *\n * @example\n * ```js\n * const containedPaths = getContainedPaths('foo');\n * // ['foo']\n *\n * * const containedPaths = getContainedPaths('foo.bar');\n * // ['foo', 'foo.bar']\n *\n * * const containedPaths = getContainedPaths('foo.bar.field');\n * // ['foo', 'foo.bar', 'foo.bar.field']\n * ```\n */\nconst getContainedPaths = (path: string) => {\n const parts = toPath(path);\n\n return parts.reduce((acc, value, index, list) => {\n return [...acc, list.slice(0, index + 1).join('.')];\n }, [] as string[]);\n};\n"],"names":["allowedFields","key","path","attribute","remove","Array","isArray","every","isString","TypeError","containedPaths","getContainedPaths","isPathAllowed","some","p","includes","startsWith","parts","toPath","reduce","acc","value","index","list","slice","join"],"mappings":";;AAGA,6BAAe,CAAA,CAACA,aAAAA,GAAiC,IAAI,GACnD,CAAC,EAAEC,GAAG,EAAEC,IAAAA,EAAM,EAAEC,WAAWD,IAAI,EAAE,EAAE,EAAE,EAAEE,MAAM,EAAE,GAAA;;AAE7C,QAAA,IAAIJ,kBAAkB,IAAA,EAAM;AAC1B,YAAA;AACF,QAAA;;QAGA,IAAI,EAAEK,KAAAA,CAAMC,OAAO,CAACN,kBAAkBA,aAAAA,CAAcO,KAAK,CAACC,QAAAA,CAAQ,CAAA,EAAI;YACpE,MAAM,IAAIC,UACR,CAAC,qDAAqD,EAAE,OAAOT,aAAAA,CAAc,CAAC,CAAC,CAAA;AAEnF,QAAA;AAEA,QAAA,IAAIE,QAAQ,IAAA,EAAM;AAChB,YAAA;AACF,QAAA;AAEA,QAAA,MAAMQ,iBAAiBC,iBAAAA,CAAkBT,IAAAA,CAAAA;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCC,QACD,MAAMU,aAAAA,GAAgBZ,aAAAA,CAAca,IAAI,CACtC,CAACC,CAAAA,GAAMJ,cAAAA,CAAeK,QAAQ,CAACD,MAAMA,CAAAA,CAAEE,UAAU,CAAC,CAAA,EAAGd,IAAAA,CAAK,CAAC,CAAC,CAAA,CAAA;AAG9D,QAAA,IAAIU,aAAAA,EAAe;AACjB,YAAA;AACF,QAAA;;QAGAR,MAAAA,CAAOH,GAAAA,CAAAA;AACT,IAAA,CAAA;AAEF;;;;;;;;;;;;;;IAeA,MAAMU,oBAAoB,CAACT,IAAAA,GAAAA;AACzB,IAAA,MAAMe,QAAQC,MAAAA,CAAOhB,IAAAA,CAAAA;AAErB,IAAA,OAAOe,MAAME,MAAM,CAAC,CAACC,GAAAA,EAAKC,OAAOC,KAAAA,EAAOC,IAAAA,GAAAA;QACtC,OAAO;AAAIH,YAAAA,GAAAA,GAAAA;AAAKG,YAAAA,IAAAA,CAAKC,KAAK,CAAC,CAAA,EAAGF,KAAAA,GAAQ,CAAA,CAAA,CAAGG,IAAI,CAAC,GAAA;AAAK,SAAA;AACrD,IAAA,CAAA,EAAG,EAAE,CAAA;AACP,CAAA;;;;"}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var fp = require('lodash/fp');
3
+ var _ = require('lodash');
4
4
 
5
5
  var removeRestrictedFields = ((restrictedFields = null)=>({ key, path: { attribute: path } }, { remove })=>{
6
6
  // Remove all fields
@@ -9,7 +9,7 @@ var removeRestrictedFields = ((restrictedFields = null)=>({ key, path: { attribu
9
9
  return;
10
10
  }
11
11
  // Throw on invalid formats
12
- if (!(fp.isArray(restrictedFields) && restrictedFields.every(fp.isString))) {
12
+ if (!(Array.isArray(restrictedFields) && restrictedFields.every(_.isString))) {
13
13
  throw new TypeError(`Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`);
14
14
  }
15
15
  // Remove if an exact match was found
@@ -1 +1 @@
1
- {"version":3,"file":"remove-restricted-fields.js","sources":["../../../src/sanitize/visitors/remove-restricted-fields.ts"],"sourcesContent":["import { isArray, isString } from 'lodash/fp';\nimport type { Visitor } from '../../traverse/factory';\n\nexport default (restrictedFields: string[] | null = null): Visitor =>\n ({ key, path: { attribute: path } }, { remove }) => {\n // Remove all fields\n if (restrictedFields === null) {\n remove(key);\n return;\n }\n\n // Throw on invalid formats\n if (!(isArray(restrictedFields) && restrictedFields.every(isString))) {\n throw new TypeError(\n `Expected array of strings for restrictedFields but got \"${typeof restrictedFields}\"`\n );\n }\n\n // Remove if an exact match was found\n if (restrictedFields.includes(path as string)) {\n remove(key);\n return;\n }\n\n // Remove nested matches\n const isRestrictedNested = restrictedFields.some((allowedPath) =>\n path?.toString().startsWith(`${allowedPath}.`)\n );\n if (isRestrictedNested) {\n remove(key);\n }\n };\n"],"names":["restrictedFields","key","path","attribute","remove","isArray","every","isString","TypeError","includes","isRestrictedNested","some","allowedPath","toString","startsWith"],"mappings":";;;;AAGA,6BAAe,CAAA,CAACA,gBAAAA,GAAoC,IAAI,GACtD,CAAC,EAAEC,GAAG,EAAEC,IAAAA,EAAM,EAAEC,WAAWD,IAAI,EAAE,EAAE,EAAE,EAAEE,MAAM,EAAE,GAAA;;AAE7C,QAAA,IAAIJ,qBAAqB,IAAA,EAAM;YAC7BI,MAAAA,CAAOH,GAAAA,CAAAA;AACP,YAAA;AACF,QAAA;;QAGA,IAAI,EAAEI,UAAAA,CAAQL,gBAAAA,CAAAA,IAAqBA,iBAAiBM,KAAK,CAACC,YAAQ,CAAA,EAAI;YACpE,MAAM,IAAIC,UACR,CAAC,wDAAwD,EAAE,OAAOR,gBAAAA,CAAiB,CAAC,CAAC,CAAA;AAEzF,QAAA;;QAGA,IAAIA,gBAAAA,CAAiBS,QAAQ,CAACP,IAAAA,CAAAA,EAAiB;YAC7CE,MAAAA,CAAOH,GAAAA,CAAAA;AACP,YAAA;AACF,QAAA;;AAGA,QAAA,MAAMS,kBAAAA,GAAqBV,gBAAAA,CAAiBW,IAAI,CAAC,CAACC,WAAAA,GAChDV,IAAAA,EAAMW,QAAAA,EAAAA,CAAWC,UAAAA,CAAW,CAAA,EAAGF,WAAAA,CAAY,CAAC,CAAC,CAAA,CAAA;AAE/C,QAAA,IAAIF,kBAAAA,EAAoB;YACtBN,MAAAA,CAAOH,GAAAA,CAAAA;AACT,QAAA;AACF,IAAA,CAAA;;;;"}
1
+ {"version":3,"file":"remove-restricted-fields.js","sources":["../../../src/sanitize/visitors/remove-restricted-fields.ts"],"sourcesContent":["import { isString } from 'lodash';\nimport type { Visitor } from '../../traverse/factory';\n\nexport default (restrictedFields: string[] | null = null): Visitor =>\n ({ key, path: { attribute: path } }, { remove }) => {\n // Remove all fields\n if (restrictedFields === null) {\n remove(key);\n return;\n }\n\n // Throw on invalid formats\n if (!(Array.isArray(restrictedFields) && restrictedFields.every(isString))) {\n throw new TypeError(\n `Expected array of strings for restrictedFields but got \"${typeof restrictedFields}\"`\n );\n }\n\n // Remove if an exact match was found\n if (restrictedFields.includes(path as string)) {\n remove(key);\n return;\n }\n\n // Remove nested matches\n const isRestrictedNested = restrictedFields.some((allowedPath) =>\n path?.toString().startsWith(`${allowedPath}.`)\n );\n if (isRestrictedNested) {\n remove(key);\n }\n };\n"],"names":["restrictedFields","key","path","attribute","remove","Array","isArray","every","isString","TypeError","includes","isRestrictedNested","some","allowedPath","toString","startsWith"],"mappings":";;;;AAGA,6BAAe,CAAA,CAACA,gBAAAA,GAAoC,IAAI,GACtD,CAAC,EAAEC,GAAG,EAAEC,IAAAA,EAAM,EAAEC,WAAWD,IAAI,EAAE,EAAE,EAAE,EAAEE,MAAM,EAAE,GAAA;;AAE7C,QAAA,IAAIJ,qBAAqB,IAAA,EAAM;YAC7BI,MAAAA,CAAOH,GAAAA,CAAAA;AACP,YAAA;AACF,QAAA;;QAGA,IAAI,EAAEI,KAAAA,CAAMC,OAAO,CAACN,qBAAqBA,gBAAAA,CAAiBO,KAAK,CAACC,UAAAA,CAAQ,CAAA,EAAI;YAC1E,MAAM,IAAIC,UACR,CAAC,wDAAwD,EAAE,OAAOT,gBAAAA,CAAiB,CAAC,CAAC,CAAA;AAEzF,QAAA;;QAGA,IAAIA,gBAAAA,CAAiBU,QAAQ,CAACR,IAAAA,CAAAA,EAAiB;YAC7CE,MAAAA,CAAOH,GAAAA,CAAAA;AACP,YAAA;AACF,QAAA;;AAGA,QAAA,MAAMU,kBAAAA,GAAqBX,gBAAAA,CAAiBY,IAAI,CAAC,CAACC,WAAAA,GAChDX,IAAAA,EAAMY,QAAAA,EAAAA,CAAWC,UAAAA,CAAW,CAAA,EAAGF,WAAAA,CAAY,CAAC,CAAC,CAAA,CAAA;AAE/C,QAAA,IAAIF,kBAAAA,EAAoB;YACtBP,MAAAA,CAAOH,GAAAA,CAAAA;AACT,QAAA;AACF,IAAA,CAAA;;;;"}
@@ -1,4 +1,4 @@
1
- import { isArray, isString } from 'lodash/fp';
1
+ import { isString } from 'lodash';
2
2
 
3
3
  var removeRestrictedFields = ((restrictedFields = null)=>({ key, path: { attribute: path } }, { remove })=>{
4
4
  // Remove all fields
@@ -7,7 +7,7 @@ var removeRestrictedFields = ((restrictedFields = null)=>({ key, path: { attribu
7
7
  return;
8
8
  }
9
9
  // Throw on invalid formats
10
- if (!(isArray(restrictedFields) && restrictedFields.every(isString))) {
10
+ if (!(Array.isArray(restrictedFields) && restrictedFields.every(isString))) {
11
11
  throw new TypeError(`Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`);
12
12
  }
13
13
  // Remove if an exact match was found
@@ -1 +1 @@
1
- {"version":3,"file":"remove-restricted-fields.mjs","sources":["../../../src/sanitize/visitors/remove-restricted-fields.ts"],"sourcesContent":["import { isArray, isString } from 'lodash/fp';\nimport type { Visitor } from '../../traverse/factory';\n\nexport default (restrictedFields: string[] | null = null): Visitor =>\n ({ key, path: { attribute: path } }, { remove }) => {\n // Remove all fields\n if (restrictedFields === null) {\n remove(key);\n return;\n }\n\n // Throw on invalid formats\n if (!(isArray(restrictedFields) && restrictedFields.every(isString))) {\n throw new TypeError(\n `Expected array of strings for restrictedFields but got \"${typeof restrictedFields}\"`\n );\n }\n\n // Remove if an exact match was found\n if (restrictedFields.includes(path as string)) {\n remove(key);\n return;\n }\n\n // Remove nested matches\n const isRestrictedNested = restrictedFields.some((allowedPath) =>\n path?.toString().startsWith(`${allowedPath}.`)\n );\n if (isRestrictedNested) {\n remove(key);\n }\n };\n"],"names":["restrictedFields","key","path","attribute","remove","isArray","every","isString","TypeError","includes","isRestrictedNested","some","allowedPath","toString","startsWith"],"mappings":";;AAGA,6BAAe,CAAA,CAACA,gBAAAA,GAAoC,IAAI,GACtD,CAAC,EAAEC,GAAG,EAAEC,IAAAA,EAAM,EAAEC,WAAWD,IAAI,EAAE,EAAE,EAAE,EAAEE,MAAM,EAAE,GAAA;;AAE7C,QAAA,IAAIJ,qBAAqB,IAAA,EAAM;YAC7BI,MAAAA,CAAOH,GAAAA,CAAAA;AACP,YAAA;AACF,QAAA;;QAGA,IAAI,EAAEI,OAAAA,CAAQL,gBAAAA,CAAAA,IAAqBA,iBAAiBM,KAAK,CAACC,SAAQ,CAAA,EAAI;YACpE,MAAM,IAAIC,UACR,CAAC,wDAAwD,EAAE,OAAOR,gBAAAA,CAAiB,CAAC,CAAC,CAAA;AAEzF,QAAA;;QAGA,IAAIA,gBAAAA,CAAiBS,QAAQ,CAACP,IAAAA,CAAAA,EAAiB;YAC7CE,MAAAA,CAAOH,GAAAA,CAAAA;AACP,YAAA;AACF,QAAA;;AAGA,QAAA,MAAMS,kBAAAA,GAAqBV,gBAAAA,CAAiBW,IAAI,CAAC,CAACC,WAAAA,GAChDV,IAAAA,EAAMW,QAAAA,EAAAA,CAAWC,UAAAA,CAAW,CAAA,EAAGF,WAAAA,CAAY,CAAC,CAAC,CAAA,CAAA;AAE/C,QAAA,IAAIF,kBAAAA,EAAoB;YACtBN,MAAAA,CAAOH,GAAAA,CAAAA;AACT,QAAA;AACF,IAAA,CAAA;;;;"}
1
+ {"version":3,"file":"remove-restricted-fields.mjs","sources":["../../../src/sanitize/visitors/remove-restricted-fields.ts"],"sourcesContent":["import { isString } from 'lodash';\nimport type { Visitor } from '../../traverse/factory';\n\nexport default (restrictedFields: string[] | null = null): Visitor =>\n ({ key, path: { attribute: path } }, { remove }) => {\n // Remove all fields\n if (restrictedFields === null) {\n remove(key);\n return;\n }\n\n // Throw on invalid formats\n if (!(Array.isArray(restrictedFields) && restrictedFields.every(isString))) {\n throw new TypeError(\n `Expected array of strings for restrictedFields but got \"${typeof restrictedFields}\"`\n );\n }\n\n // Remove if an exact match was found\n if (restrictedFields.includes(path as string)) {\n remove(key);\n return;\n }\n\n // Remove nested matches\n const isRestrictedNested = restrictedFields.some((allowedPath) =>\n path?.toString().startsWith(`${allowedPath}.`)\n );\n if (isRestrictedNested) {\n remove(key);\n }\n };\n"],"names":["restrictedFields","key","path","attribute","remove","Array","isArray","every","isString","TypeError","includes","isRestrictedNested","some","allowedPath","toString","startsWith"],"mappings":";;AAGA,6BAAe,CAAA,CAACA,gBAAAA,GAAoC,IAAI,GACtD,CAAC,EAAEC,GAAG,EAAEC,IAAAA,EAAM,EAAEC,WAAWD,IAAI,EAAE,EAAE,EAAE,EAAEE,MAAM,EAAE,GAAA;;AAE7C,QAAA,IAAIJ,qBAAqB,IAAA,EAAM;YAC7BI,MAAAA,CAAOH,GAAAA,CAAAA;AACP,YAAA;AACF,QAAA;;QAGA,IAAI,EAAEI,KAAAA,CAAMC,OAAO,CAACN,qBAAqBA,gBAAAA,CAAiBO,KAAK,CAACC,QAAAA,CAAQ,CAAA,EAAI;YAC1E,MAAM,IAAIC,UACR,CAAC,wDAAwD,EAAE,OAAOT,gBAAAA,CAAiB,CAAC,CAAC,CAAA;AAEzF,QAAA;;QAGA,IAAIA,gBAAAA,CAAiBU,QAAQ,CAACR,IAAAA,CAAAA,EAAiB;YAC7CE,MAAAA,CAAOH,GAAAA,CAAAA;AACP,YAAA;AACF,QAAA;;AAGA,QAAA,MAAMU,kBAAAA,GAAqBX,gBAAAA,CAAiBY,IAAI,CAAC,CAACC,WAAAA,GAChDX,IAAAA,EAAMY,QAAAA,EAAAA,CAAWC,UAAAA,CAAW,CAAA,EAAGF,WAAAA,CAAY,CAAC,CAAC,CAAA,CAAA;AAE/C,QAAA,IAAIF,kBAAAA,EAAoB;YACtBP,MAAAA,CAAOH,GAAAA,CAAAA;AACT,QAAA;AACF,IAAA,CAAA;;;;"}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var fp = require('lodash/fp');
3
+ var _ = require('lodash');
4
4
  var contentTypes = require('../../content-types.js');
5
5
  var relations = require('../../relations.js');
6
6
 
@@ -83,13 +83,13 @@ const visitRelationAttribute = async (auth, { data, key, attribute, schema }, {
83
83
  } else {
84
84
  const newMorphValue = await handleMorphElements(elements);
85
85
  if (!newMorphValue.length) {
86
- if (fp.isArray(elements) && elements.length === 0) {
86
+ if (Array.isArray(elements) && elements.length === 0) {
87
87
  return;
88
88
  }
89
89
  remove(key);
90
90
  return;
91
91
  }
92
- if (fp.isArray(elements)) {
92
+ if (Array.isArray(elements)) {
93
93
  set(key, newMorphValue);
94
94
  return;
95
95
  }
@@ -97,11 +97,11 @@ const visitRelationAttribute = async (auth, { data, key, attribute, schema }, {
97
97
  }
98
98
  };
99
99
  const isMorphMutationPayload = (value)=>{
100
- return fp.isObject(value) && ('connect' in value || 'set' in value || 'disconnect' in value);
100
+ return _.isObject(value) && ('connect' in value || 'set' in value || 'disconnect' in value);
101
101
  };
102
102
  const isMorphPopulateCount = (value)=>value === true || value === 'true';
103
103
  const isMorphPopulatePayload = (value)=>{
104
- return fp.isObject(value) && !('__type' in value) && 'on' in value && fp.isObject(value.on);
104
+ return _.isObject(value) && !('__type' in value) && 'on' in value && _.isObject(value.on);
105
105
  };
106
106
  const buildAllowedMorphPopulateFragment = async (subPopulate)=>{
107
107
  const newOn = {};
@@ -115,18 +115,18 @@ const visitRelationAttribute = async (auth, { data, key, attribute, schema }, {
115
115
  return newOn;
116
116
  };
117
117
  const isMorphPopulateAllOrCount = (value)=>{
118
- return value === true || value === 'true' || fp.isObject(value) && 'count' in value && isMorphPopulateCount(value.count) && !('on' in value);
118
+ return value === true || value === 'true' || _.isObject(value) && 'count' in value && isMorphPopulateCount(value.count) && !('on' in value);
119
119
  };
120
120
  const isMorphCountOutput = (value)=>{
121
- return fp.isObject(value) && 'count' in value && typeof value.count === 'number' && Object.keys(value).length === 1;
121
+ return _.isObject(value) && 'count' in value && typeof value.count === 'number' && Object.keys(value).length === 1;
122
122
  };
123
123
  const handleMorphElements = async (elements)=>{
124
124
  const allowedElements = [];
125
- const elementsToCheck = fp.isArray(elements) ? elements : [
125
+ const elementsToCheck = Array.isArray(elements) ? elements : [
126
126
  elements
127
127
  ];
128
128
  for (const element of elementsToCheck){
129
- if (!fp.isObject(element) || !('__type' in element) || typeof element.__type !== 'string') {
129
+ if (!_.isObject(element) || !('__type' in element) || typeof element.__type !== 'string') {
130
130
  continue;
131
131
  }
132
132
  const scopes = ACTIONS_TO_VERIFY.map((action)=>`${element.__type}.${action}`);
@@ -1 +1 @@
1
- {"version":3,"file":"remove-restricted-relations.js","sources":["../../../src/sanitize/visitors/remove-restricted-relations.ts"],"sourcesContent":["import { isArray, isObject } from 'lodash/fp';\nimport * as contentTypeUtils from '../../content-types';\nimport type { Model, RelationOrderingOptions } from '../../types';\nimport type { Visitor } from '../../traverse/factory';\nimport { VALID_RELATION_ORDERING_KEYS } from '../../relations';\n\nconst ACTIONS_TO_VERIFY = ['find'];\nconst { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypeUtils.constants;\n\ntype MorphArray = Array<{ __type: string }>;\ntype MorphElement = Record<string, unknown> & { __type: string };\ntype MorphMutationPayload = {\n connect?: unknown;\n set?: unknown;\n disconnect?: unknown;\n options?: Record<string, unknown> | null;\n};\ntype MorphPopulatePayload = {\n on: Record<string, unknown>;\n count?: unknown;\n};\n\nexport default (auth: unknown): Visitor =>\n (visitorOptions, visitorUtils) => {\n const { attribute } = visitorOptions;\n\n // Deliberately not an `async` function. This visitor is invoked for every key of\n // every node of every entity, and only relation attributes need any work at all.\n // Declaring it `async` meant each of those keys allocated a promise purely to\n // resolve it immediately, and the traversal then awaited it. Returning early\n // without a promise lets the traversal stay synchronous for the common case.\n if (!attribute || attribute.type !== 'relation') {\n return;\n }\n\n return visitRelationAttribute(auth, visitorOptions, visitorUtils) as unknown as void;\n };\n\nconst visitRelationAttribute = async (\n auth: unknown,\n { data, key, attribute, schema }: Parameters<Visitor>[0],\n { remove, set }: Parameters<Visitor>[1]\n) => {\n // Narrowing only; the caller reaches this for relation attributes exclusively.\n if (!attribute) {\n return;\n }\n\n const handleMorphRelation = async () => {\n const elements = (data as Record<string, MorphArray | MorphElement | MorphMutationPayload>)[\n key\n ];\n\n if (!elements) {\n return;\n }\n\n if (isMorphMutationPayload(elements)) {\n const newValue: Record<string, unknown> = {};\n\n const connect = await handleMorphElements(elements.connect || []);\n const relSet = await handleMorphElements(elements.set || []);\n const disconnect = await handleMorphElements(elements.disconnect || []);\n\n if (connect.length > 0) {\n newValue.connect = connect;\n }\n\n if (relSet.length > 0) {\n newValue.set = relSet;\n }\n\n if (disconnect.length > 0) {\n newValue.disconnect = disconnect;\n }\n\n // TODO: this should technically be in its own visitor to check morph options, but for now we'll handle it here\n const options = elements.options;\n if (options && typeof options === 'object') {\n const filteredOptions: RelationOrderingOptions = {};\n\n Object.keys(options).forEach((key) => {\n const optionKey = key as keyof RelationOrderingOptions;\n const validator = VALID_RELATION_ORDERING_KEYS[optionKey];\n const optionValue = options[key];\n\n if (validator && validator(optionValue)) {\n filteredOptions[optionKey] = optionValue as RelationOrderingOptions[typeof optionKey];\n }\n });\n\n newValue.options = filteredOptions;\n } else {\n newValue.options = {};\n }\n\n set(key, newValue);\n } else if (isMorphPopulatePayload(elements)) {\n const newOn: Record<string, unknown> = {};\n\n for (const [uid, subPopulate] of Object.entries(elements.on)) {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${uid}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n newOn[uid] = subPopulate;\n }\n }\n\n if (Object.keys(newOn).length === 0) {\n remove(key);\n return;\n }\n\n const count = isMorphPopulateCount(elements.count) ? true : elements.count;\n set(key, { ...elements, count, on: newOn });\n } else {\n const newMorphValue = await handleMorphElements(elements);\n\n if (!newMorphValue.length) {\n if (isArray(elements) && elements.length === 0) {\n return;\n }\n\n remove(key);\n return;\n }\n\n if (isArray(elements)) {\n set(key, newMorphValue);\n return;\n }\n\n set(key, newMorphValue[0]);\n }\n };\n\n const isMorphMutationPayload = (value: unknown): value is MorphMutationPayload => {\n return isObject(value) && ('connect' in value || 'set' in value || 'disconnect' in value);\n };\n\n const isMorphPopulateCount = (value: unknown) => value === true || value === 'true';\n\n const isMorphPopulatePayload = (value: unknown): value is MorphPopulatePayload => {\n return isObject(value) && !('__type' in value) && 'on' in value && isObject(value.on);\n };\n\n const buildAllowedMorphPopulateFragment = async (subPopulate: unknown) => {\n const newOn: Record<string, unknown> = {};\n\n for (const uid of getRegisteredContentTypeUIDs()) {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${uid}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n newOn[uid] = subPopulate;\n }\n }\n\n return newOn;\n };\n\n const isMorphPopulateAllOrCount = (value: unknown): value is true | 'true' | { count: true } => {\n return (\n value === true ||\n value === 'true' ||\n (isObject(value) && 'count' in value && isMorphPopulateCount(value.count) && !('on' in value))\n );\n };\n\n const isMorphCountOutput = (value: unknown): value is { count: number } => {\n return (\n isObject(value) &&\n 'count' in value &&\n typeof value.count === 'number' &&\n Object.keys(value).length === 1\n );\n };\n\n const handleMorphElements = async (elements: unknown) => {\n const allowedElements: Record<string, unknown>[] = [];\n const elementsToCheck = isArray(elements) ? elements : [elements];\n\n for (const element of elementsToCheck) {\n if (!isObject(element) || !('__type' in element) || typeof element.__type !== 'string') {\n continue;\n }\n\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n allowedElements.push(element);\n }\n }\n\n return allowedElements;\n };\n\n const handleRegularRelation = async () => {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${attribute.target}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (!isAllowed) {\n remove(key);\n }\n };\n\n const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key);\n\n if (contentTypeUtils.isMorphToRelationalAttribute(attribute)) {\n const value = (data as Record<string, unknown>)[key];\n\n if (isMorphPopulatePayload(value)) {\n await handleMorphRelation();\n return;\n }\n\n if (isMorphPopulateAllOrCount(value)) {\n const newOn = await buildAllowedMorphPopulateFragment(true);\n\n if (Object.keys(newOn).length === 0) {\n remove(key);\n return;\n }\n\n set(\n key,\n value === true || value === 'true' ? { on: newOn } : { ...value, count: true, on: newOn }\n );\n return;\n }\n\n if (isMorphCountOutput(value)) {\n return;\n }\n\n await handleMorphRelation();\n return;\n }\n\n if (isCreatorRelation && schema.options?.populateCreatorFields) {\n return;\n }\n\n await handleRegularRelation();\n};\n\n/**\n * Per-`auth` memo of scope decisions.\n *\n * The decision for a given scope depends only on the ability carried by `auth`, which is\n * built once per request and not mutated while the response is sanitized. Sanitizing a\n * list re-asks the same question for every entity, so a 25-entity page with four\n * relations asked ~100 identical questions; each denial also constructed an Error, and\n * capturing a stack trace is by far the most expensive part of that.\n *\n * Keyed weakly on the `auth` object so entries are collected with the request.\n */\nconst scopeDecisionCache = new WeakMap<object, Map<string, boolean>>();\n\nconst canAccessScope = async (scope: string, auth: unknown): Promise<boolean> => {\n const cacheable = typeof auth === 'object' && auth !== null;\n\n let decisions: Map<string, boolean> | undefined;\n\n if (cacheable) {\n decisions = scopeDecisionCache.get(auth as object);\n\n if (decisions === undefined) {\n decisions = new Map();\n scopeDecisionCache.set(auth as object, decisions);\n } else {\n const cached = decisions.get(scope);\n if (cached !== undefined) {\n return cached;\n }\n }\n }\n\n let allowed: boolean;\n try {\n await strapi.auth.verify(auth, { scope });\n allowed = true;\n } catch {\n allowed = false;\n }\n\n decisions?.set(scope, allowed);\n\n return allowed;\n};\n\nconst hasAccessToSomeScopes = async (scopes: string[], auth: unknown) => {\n for (const scope of scopes) {\n if (await canAccessScope(scope, auth)) {\n return true;\n }\n }\n\n return false;\n};\n\nconst getRegisteredContentTypeUIDs = () => {\n return (Object.values(strapi.contentTypes ?? {}) as Model[])\n .map((model) => model.uid)\n .filter((uid): uid is string => typeof uid === 'string');\n};\n"],"names":["ACTIONS_TO_VERIFY","CREATED_BY_ATTRIBUTE","UPDATED_BY_ATTRIBUTE","contentTypeUtils","auth","visitorOptions","visitorUtils","attribute","type","visitRelationAttribute","data","key","schema","remove","set","handleMorphRelation","elements","isMorphMutationPayload","newValue","connect","handleMorphElements","relSet","disconnect","length","options","filteredOptions","Object","keys","forEach","optionKey","validator","VALID_RELATION_ORDERING_KEYS","optionValue","isMorphPopulatePayload","newOn","uid","subPopulate","entries","on","scopes","map","action","isAllowed","hasAccessToSomeScopes","count","isMorphPopulateCount","newMorphValue","isArray","value","isObject","buildAllowedMorphPopulateFragment","getRegisteredContentTypeUIDs","isMorphPopulateAllOrCount","isMorphCountOutput","allowedElements","elementsToCheck","element","__type","push","handleRegularRelation","target","isCreatorRelation","includes","populateCreatorFields","scopeDecisionCache","WeakMap","canAccessScope","scope","cacheable","decisions","get","undefined","Map","cached","allowed","strapi","verify","values","contentTypes","model","filter"],"mappings":"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"}
1
+ {"version":3,"file":"remove-restricted-relations.js","sources":["../../../src/sanitize/visitors/remove-restricted-relations.ts"],"sourcesContent":["import { isObject } from 'lodash';\nimport * as contentTypeUtils from '../../content-types';\nimport type { Model, RelationOrderingOptions } from '../../types';\nimport type { Visitor } from '../../traverse/factory';\nimport { VALID_RELATION_ORDERING_KEYS } from '../../relations';\n\nconst ACTIONS_TO_VERIFY = ['find'];\nconst { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypeUtils.constants;\n\ntype MorphArray = Array<{ __type: string }>;\ntype MorphElement = Record<string, unknown> & { __type: string };\ntype MorphMutationPayload = {\n connect?: unknown;\n set?: unknown;\n disconnect?: unknown;\n options?: Record<string, unknown> | null;\n};\ntype MorphPopulatePayload = {\n on: Record<string, unknown>;\n count?: unknown;\n};\n\nexport default (auth: unknown): Visitor =>\n (visitorOptions, visitorUtils) => {\n const { attribute } = visitorOptions;\n\n // Deliberately not an `async` function. This visitor is invoked for every key of\n // every node of every entity, and only relation attributes need any work at all.\n // Declaring it `async` meant each of those keys allocated a promise purely to\n // resolve it immediately, and the traversal then awaited it. Returning early\n // without a promise lets the traversal stay synchronous for the common case.\n if (!attribute || attribute.type !== 'relation') {\n return;\n }\n\n return visitRelationAttribute(auth, visitorOptions, visitorUtils) as unknown as void;\n };\n\nconst visitRelationAttribute = async (\n auth: unknown,\n { data, key, attribute, schema }: Parameters<Visitor>[0],\n { remove, set }: Parameters<Visitor>[1]\n) => {\n // Narrowing only; the caller reaches this for relation attributes exclusively.\n if (!attribute) {\n return;\n }\n\n const handleMorphRelation = async () => {\n const elements = (data as Record<string, MorphArray | MorphElement | MorphMutationPayload>)[\n key\n ];\n\n if (!elements) {\n return;\n }\n\n if (isMorphMutationPayload(elements)) {\n const newValue: Record<string, unknown> = {};\n\n const connect = await handleMorphElements(elements.connect || []);\n const relSet = await handleMorphElements(elements.set || []);\n const disconnect = await handleMorphElements(elements.disconnect || []);\n\n if (connect.length > 0) {\n newValue.connect = connect;\n }\n\n if (relSet.length > 0) {\n newValue.set = relSet;\n }\n\n if (disconnect.length > 0) {\n newValue.disconnect = disconnect;\n }\n\n // TODO: this should technically be in its own visitor to check morph options, but for now we'll handle it here\n const options = elements.options;\n if (options && typeof options === 'object') {\n const filteredOptions: RelationOrderingOptions = {};\n\n Object.keys(options).forEach((key) => {\n const optionKey = key as keyof RelationOrderingOptions;\n const validator = VALID_RELATION_ORDERING_KEYS[optionKey];\n const optionValue = options[key];\n\n if (validator && validator(optionValue)) {\n filteredOptions[optionKey] = optionValue as RelationOrderingOptions[typeof optionKey];\n }\n });\n\n newValue.options = filteredOptions;\n } else {\n newValue.options = {};\n }\n\n set(key, newValue);\n } else if (isMorphPopulatePayload(elements)) {\n const newOn: Record<string, unknown> = {};\n\n for (const [uid, subPopulate] of Object.entries(elements.on)) {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${uid}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n newOn[uid] = subPopulate;\n }\n }\n\n if (Object.keys(newOn).length === 0) {\n remove(key);\n return;\n }\n\n const count = isMorphPopulateCount(elements.count) ? true : elements.count;\n set(key, { ...elements, count, on: newOn });\n } else {\n const newMorphValue = await handleMorphElements(elements);\n\n if (!newMorphValue.length) {\n if (Array.isArray(elements) && elements.length === 0) {\n return;\n }\n\n remove(key);\n return;\n }\n\n if (Array.isArray(elements)) {\n set(key, newMorphValue);\n return;\n }\n\n set(key, newMorphValue[0]);\n }\n };\n\n const isMorphMutationPayload = (value: unknown): value is MorphMutationPayload => {\n return isObject(value) && ('connect' in value || 'set' in value || 'disconnect' in value);\n };\n\n const isMorphPopulateCount = (value: unknown) => value === true || value === 'true';\n\n const isMorphPopulatePayload = (value: unknown): value is MorphPopulatePayload => {\n return isObject(value) && !('__type' in value) && 'on' in value && isObject(value.on);\n };\n\n const buildAllowedMorphPopulateFragment = async (subPopulate: unknown) => {\n const newOn: Record<string, unknown> = {};\n\n for (const uid of getRegisteredContentTypeUIDs()) {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${uid}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n newOn[uid] = subPopulate;\n }\n }\n\n return newOn;\n };\n\n const isMorphPopulateAllOrCount = (value: unknown): value is true | 'true' | { count: true } => {\n return (\n value === true ||\n value === 'true' ||\n (isObject(value) && 'count' in value && isMorphPopulateCount(value.count) && !('on' in value))\n );\n };\n\n const isMorphCountOutput = (value: unknown): value is { count: number } => {\n return (\n isObject(value) &&\n 'count' in value &&\n typeof value.count === 'number' &&\n Object.keys(value).length === 1\n );\n };\n\n const handleMorphElements = async (elements: unknown) => {\n const allowedElements: Record<string, unknown>[] = [];\n const elementsToCheck = Array.isArray(elements) ? elements : [elements];\n\n for (const element of elementsToCheck) {\n if (!isObject(element) || !('__type' in element) || typeof element.__type !== 'string') {\n continue;\n }\n\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n allowedElements.push(element);\n }\n }\n\n return allowedElements;\n };\n\n const handleRegularRelation = async () => {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${attribute.target}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (!isAllowed) {\n remove(key);\n }\n };\n\n const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key);\n\n if (contentTypeUtils.isMorphToRelationalAttribute(attribute)) {\n const value = (data as Record<string, unknown>)[key];\n\n if (isMorphPopulatePayload(value)) {\n await handleMorphRelation();\n return;\n }\n\n if (isMorphPopulateAllOrCount(value)) {\n const newOn = await buildAllowedMorphPopulateFragment(true);\n\n if (Object.keys(newOn).length === 0) {\n remove(key);\n return;\n }\n\n set(\n key,\n value === true || value === 'true' ? { on: newOn } : { ...value, count: true, on: newOn }\n );\n return;\n }\n\n if (isMorphCountOutput(value)) {\n return;\n }\n\n await handleMorphRelation();\n return;\n }\n\n if (isCreatorRelation && schema.options?.populateCreatorFields) {\n return;\n }\n\n await handleRegularRelation();\n};\n\n/**\n * Per-`auth` memo of scope decisions.\n *\n * The decision for a given scope depends only on the ability carried by `auth`, which is\n * built once per request and not mutated while the response is sanitized. Sanitizing a\n * list re-asks the same question for every entity, so a 25-entity page with four\n * relations asked ~100 identical questions; each denial also constructed an Error, and\n * capturing a stack trace is by far the most expensive part of that.\n *\n * Keyed weakly on the `auth` object so entries are collected with the request.\n */\nconst scopeDecisionCache = new WeakMap<object, Map<string, boolean>>();\n\nconst canAccessScope = async (scope: string, auth: unknown): Promise<boolean> => {\n const cacheable = typeof auth === 'object' && auth !== null;\n\n let decisions: Map<string, boolean> | undefined;\n\n if (cacheable) {\n decisions = scopeDecisionCache.get(auth as object);\n\n if (decisions === undefined) {\n decisions = new Map();\n scopeDecisionCache.set(auth as object, decisions);\n } else {\n const cached = decisions.get(scope);\n if (cached !== undefined) {\n return cached;\n }\n }\n }\n\n let allowed: boolean;\n try {\n await strapi.auth.verify(auth, { scope });\n allowed = true;\n } catch {\n allowed = false;\n }\n\n decisions?.set(scope, allowed);\n\n return allowed;\n};\n\nconst hasAccessToSomeScopes = async (scopes: string[], auth: unknown) => {\n for (const scope of scopes) {\n if (await canAccessScope(scope, auth)) {\n return true;\n }\n }\n\n return false;\n};\n\nconst getRegisteredContentTypeUIDs = () => {\n return (Object.values(strapi.contentTypes ?? {}) as Model[])\n .map((model) => model.uid)\n .filter((uid): uid is string => typeof uid === 'string');\n};\n"],"names":["ACTIONS_TO_VERIFY","CREATED_BY_ATTRIBUTE","UPDATED_BY_ATTRIBUTE","contentTypeUtils","auth","visitorOptions","visitorUtils","attribute","type","visitRelationAttribute","data","key","schema","remove","set","handleMorphRelation","elements","isMorphMutationPayload","newValue","connect","handleMorphElements","relSet","disconnect","length","options","filteredOptions","Object","keys","forEach","optionKey","validator","VALID_RELATION_ORDERING_KEYS","optionValue","isMorphPopulatePayload","newOn","uid","subPopulate","entries","on","scopes","map","action","isAllowed","hasAccessToSomeScopes","count","isMorphPopulateCount","newMorphValue","Array","isArray","value","isObject","buildAllowedMorphPopulateFragment","getRegisteredContentTypeUIDs","isMorphPopulateAllOrCount","isMorphCountOutput","allowedElements","elementsToCheck","element","__type","push","handleRegularRelation","target","isCreatorRelation","includes","populateCreatorFields","scopeDecisionCache","WeakMap","canAccessScope","scope","cacheable","decisions","get","undefined","Map","cached","allowed","strapi","verify","values","contentTypes","model","filter"],"mappings":";;;;;;AAMA,MAAMA,iBAAAA,GAAoB;AAAC,IAAA;AAAO,CAAA;AAClC,MAAM,EAAEC,oBAAoB,EAAEC,oBAAoB,EAAE,GAAGC,sBAA0B;AAejF,gCAAe,CAAA,CAACC,IAAAA,GACd,CAACC,cAAAA,EAAgBC,YAAAA,GAAAA;QACf,MAAM,EAAEC,SAAS,EAAE,GAAGF,cAAAA;;;;;;AAOtB,QAAA,IAAI,CAACE,SAAAA,IAAaA,SAAAA,CAAUC,IAAI,KAAK,UAAA,EAAY;AAC/C,YAAA;AACF,QAAA;QAEA,OAAOC,sBAAAA,CAAuBL,MAAMC,cAAAA,EAAgBC,YAAAA,CAAAA;AACtD,IAAA,CAAA;AAEF,MAAMG,yBAAyB,OAC7BL,IAAAA,EACA,EAAEM,IAAI,EAAEC,GAAG,EAAEJ,SAAS,EAAEK,MAAM,EAA0B,EACxD,EAAEC,MAAM,EAAEC,GAAG,EAA0B,GAAA;;AAGvC,IAAA,IAAI,CAACP,SAAAA,EAAW;AACd,QAAA;AACF,IAAA;AAEA,IAAA,MAAMQ,mBAAAA,GAAsB,UAAA;AAC1B,QAAA,MAAMC,QAAAA,GAAYN,IAAyE,CACzFC,GAAAA,CACD;AAED,QAAA,IAAI,CAACK,QAAAA,EAAU;AACb,YAAA;AACF,QAAA;AAEA,QAAA,IAAIC,uBAAuBD,QAAAA,CAAAA,EAAW;AACpC,YAAA,MAAME,WAAoC,EAAC;AAE3C,YAAA,MAAMC,UAAU,MAAMC,mBAAAA,CAAoBJ,QAAAA,CAASG,OAAO,IAAI,EAAE,CAAA;AAChE,YAAA,MAAME,SAAS,MAAMD,mBAAAA,CAAoBJ,QAAAA,CAASF,GAAG,IAAI,EAAE,CAAA;AAC3D,YAAA,MAAMQ,aAAa,MAAMF,mBAAAA,CAAoBJ,QAAAA,CAASM,UAAU,IAAI,EAAE,CAAA;YAEtE,IAAIH,OAAAA,CAAQI,MAAM,GAAG,CAAA,EAAG;AACtBL,gBAAAA,QAAAA,CAASC,OAAO,GAAGA,OAAAA;AACrB,YAAA;YAEA,IAAIE,MAAAA,CAAOE,MAAM,GAAG,CAAA,EAAG;AACrBL,gBAAAA,QAAAA,CAASJ,GAAG,GAAGO,MAAAA;AACjB,YAAA;YAEA,IAAIC,UAAAA,CAAWC,MAAM,GAAG,CAAA,EAAG;AACzBL,gBAAAA,QAAAA,CAASI,UAAU,GAAGA,UAAAA;AACxB,YAAA;;YAGA,MAAME,OAAAA,GAAUR,SAASQ,OAAO;YAChC,IAAIA,OAAAA,IAAW,OAAOA,OAAAA,KAAY,QAAA,EAAU;AAC1C,gBAAA,MAAMC,kBAA2C,EAAC;AAElDC,gBAAAA,MAAAA,CAAOC,IAAI,CAACH,OAAAA,CAAAA,CAASI,OAAO,CAAC,CAACjB,GAAAA,GAAAA;AAC5B,oBAAA,MAAMkB,SAAAA,GAAYlB,GAAAA;oBAClB,MAAMmB,SAAAA,GAAYC,sCAA4B,CAACF,SAAAA,CAAU;oBACzD,MAAMG,WAAAA,GAAcR,OAAO,CAACb,GAAAA,CAAI;oBAEhC,IAAImB,SAAAA,IAAaA,UAAUE,WAAAA,CAAAA,EAAc;wBACvCP,eAAe,CAACI,UAAU,GAAGG,WAAAA;AAC/B,oBAAA;AACF,gBAAA,CAAA,CAAA;AAEAd,gBAAAA,QAAAA,CAASM,OAAO,GAAGC,eAAAA;YACrB,CAAA,MAAO;gBACLP,QAAAA,CAASM,OAAO,GAAG,EAAC;AACtB,YAAA;AAEAV,YAAAA,GAAAA,CAAIH,GAAAA,EAAKO,QAAAA,CAAAA;QACX,CAAA,MAAO,IAAIe,uBAAuBjB,QAAAA,CAAAA,EAAW;AAC3C,YAAA,MAAMkB,QAAiC,EAAC;YAExC,KAAK,MAAM,CAACC,GAAAA,EAAKC,WAAAA,CAAY,IAAIV,OAAOW,OAAO,CAACrB,QAAAA,CAASsB,EAAE,CAAA,CAAG;gBAC5D,MAAMC,MAAAA,GAASvC,iBAAAA,CAAkBwC,GAAG,CAAC,CAACC,SAAW,CAAA,EAAGN,GAAAA,CAAI,CAAC,EAAEM,MAAAA,CAAAA,CAAQ,CAAA;gBACnE,MAAMC,SAAAA,GAAY,MAAMC,qBAAAA,CAAsBJ,MAAAA,EAAQnC,IAAAA,CAAAA;AAEtD,gBAAA,IAAIsC,SAAAA,EAAW;oBACbR,KAAK,CAACC,IAAI,GAAGC,WAAAA;AACf,gBAAA;AACF,YAAA;AAEA,YAAA,IAAIV,OAAOC,IAAI,CAACO,KAAAA,CAAAA,CAAOX,MAAM,KAAK,CAAA,EAAG;gBACnCV,MAAAA,CAAOF,GAAAA,CAAAA;AACP,gBAAA;AACF,YAAA;AAEA,YAAA,MAAMiC,QAAQC,oBAAAA,CAAqB7B,QAAAA,CAAS4B,KAAK,CAAA,GAAI,IAAA,GAAO5B,SAAS4B,KAAK;AAC1E9B,YAAAA,GAAAA,CAAIH,GAAAA,EAAK;AAAE,gBAAA,GAAGK,QAAQ;AAAE4B,gBAAAA,KAAAA;gBAAON,EAAAA,EAAIJ;AAAM,aAAA,CAAA;QAC3C,CAAA,MAAO;YACL,MAAMY,aAAAA,GAAgB,MAAM1B,mBAAAA,CAAoBJ,QAAAA,CAAAA;YAEhD,IAAI,CAAC8B,aAAAA,CAAcvB,MAAM,EAAE;AACzB,gBAAA,IAAIwB,MAAMC,OAAO,CAAChC,aAAaA,QAAAA,CAASO,MAAM,KAAK,CAAA,EAAG;AACpD,oBAAA;AACF,gBAAA;gBAEAV,MAAAA,CAAOF,GAAAA,CAAAA;AACP,gBAAA;AACF,YAAA;YAEA,IAAIoC,KAAAA,CAAMC,OAAO,CAAChC,QAAAA,CAAAA,EAAW;AAC3BF,gBAAAA,GAAAA,CAAIH,GAAAA,EAAKmC,aAAAA,CAAAA;AACT,gBAAA;AACF,YAAA;YAEAhC,GAAAA,CAAIH,GAAAA,EAAKmC,aAAa,CAAC,CAAA,CAAE,CAAA;AAC3B,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAM7B,yBAAyB,CAACgC,KAAAA,GAAAA;QAC9B,OAAOC,UAAAA,CAASD,WAAW,SAAA,IAAaA,SAAS,KAAA,IAASA,KAAAA,IAAS,gBAAgBA,KAAI,CAAA;AACzF,IAAA,CAAA;AAEA,IAAA,MAAMJ,oBAAAA,GAAuB,CAACI,KAAAA,GAAmBA,KAAAA,KAAU,QAAQA,KAAAA,KAAU,MAAA;AAE7E,IAAA,MAAMhB,yBAAyB,CAACgB,KAAAA,GAAAA;QAC9B,OAAOC,UAAAA,CAASD,KAAAA,CAAAA,IAAU,EAAE,QAAA,IAAYA,KAAI,CAAA,IAAM,IAAA,IAAQA,KAAAA,IAASC,UAAAA,CAASD,KAAAA,CAAMX,EAAE,CAAA;AACtF,IAAA,CAAA;AAEA,IAAA,MAAMa,oCAAoC,OAAOf,WAAAA,GAAAA;AAC/C,QAAA,MAAMF,QAAiC,EAAC;QAExC,KAAK,MAAMC,OAAOiB,4BAAAA,EAAAA,CAAgC;YAChD,MAAMb,MAAAA,GAASvC,iBAAAA,CAAkBwC,GAAG,CAAC,CAACC,SAAW,CAAA,EAAGN,GAAAA,CAAI,CAAC,EAAEM,MAAAA,CAAAA,CAAQ,CAAA;YACnE,MAAMC,SAAAA,GAAY,MAAMC,qBAAAA,CAAsBJ,MAAAA,EAAQnC,IAAAA,CAAAA;AAEtD,YAAA,IAAIsC,SAAAA,EAAW;gBACbR,KAAK,CAACC,IAAI,GAAGC,WAAAA;AACf,YAAA;AACF,QAAA;QAEA,OAAOF,KAAAA;AACT,IAAA,CAAA;AAEA,IAAA,MAAMmB,4BAA4B,CAACJ,KAAAA,GAAAA;AACjC,QAAA,OACEA,KAAAA,KAAU,IAAA,IACVA,KAAAA,KAAU,MAAA,IACTC,WAASD,KAAAA,CAAAA,IAAU,OAAA,IAAWA,KAAAA,IAASJ,oBAAAA,CAAqBI,MAAML,KAAK,CAAA,IAAK,EAAE,QAAQK,KAAI,CAAA;AAE/F,IAAA,CAAA;AAEA,IAAA,MAAMK,qBAAqB,CAACL,KAAAA,GAAAA;AAC1B,QAAA,OACEC,UAAAA,CAASD,KAAAA,CAAAA,IACT,OAAA,IAAWA,KAAAA,IACX,OAAOA,KAAAA,CAAML,KAAK,KAAK,QAAA,IACvBlB,MAAAA,CAAOC,IAAI,CAACsB,KAAAA,CAAAA,CAAO1B,MAAM,KAAK,CAAA;AAElC,IAAA,CAAA;AAEA,IAAA,MAAMH,sBAAsB,OAAOJ,QAAAA,GAAAA;AACjC,QAAA,MAAMuC,kBAA6C,EAAE;AACrD,QAAA,MAAMC,eAAAA,GAAkBT,KAAAA,CAAMC,OAAO,CAAChC,YAAYA,QAAAA,GAAW;AAACA,YAAAA;AAAS,SAAA;QAEvE,KAAK,MAAMyC,WAAWD,eAAAA,CAAiB;AACrC,YAAA,IAAI,CAACN,UAAAA,CAASO,OAAAA,CAAAA,IAAY,EAAE,QAAA,IAAYA,OAAM,CAAA,IAAM,OAAOA,OAAAA,CAAQC,MAAM,KAAK,QAAA,EAAU;AACtF,gBAAA;AACF,YAAA;AAEA,YAAA,MAAMnB,MAAAA,GAASvC,iBAAAA,CAAkBwC,GAAG,CAAC,CAACC,MAAAA,GAAW,CAAA,EAAGgB,OAAAA,CAAQC,MAAM,CAAC,CAAC,EAAEjB,MAAAA,CAAAA,CAAQ,CAAA;YAC9E,MAAMC,SAAAA,GAAY,MAAMC,qBAAAA,CAAsBJ,MAAAA,EAAQnC,IAAAA,CAAAA;AAEtD,YAAA,IAAIsC,SAAAA,EAAW;AACba,gBAAAA,eAAAA,CAAgBI,IAAI,CAACF,OAAAA,CAAAA;AACvB,YAAA;AACF,QAAA;QAEA,OAAOF,eAAAA;AACT,IAAA,CAAA;AAEA,IAAA,MAAMK,qBAAAA,GAAwB,UAAA;AAC5B,QAAA,MAAMrB,MAAAA,GAASvC,iBAAAA,CAAkBwC,GAAG,CAAC,CAACC,MAAAA,GAAW,CAAA,EAAGlC,SAAAA,CAAUsD,MAAM,CAAC,CAAC,EAAEpB,MAAAA,CAAAA,CAAQ,CAAA;QAChF,MAAMC,SAAAA,GAAY,MAAMC,qBAAAA,CAAsBJ,MAAAA,EAAQnC,IAAAA,CAAAA;AAEtD,QAAA,IAAI,CAACsC,SAAAA,EAAW;YACd7B,MAAAA,CAAOF,GAAAA,CAAAA;AACT,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMmD,iBAAAA,GAAoB;AAAC7D,QAAAA,oBAAAA;AAAsBC,QAAAA;AAAqB,KAAA,CAAC6D,QAAQ,CAACpD,GAAAA,CAAAA;IAEhF,IAAIR,yCAA6C,CAACI,SAAAA,CAAAA,EAAY;AAC5D,QAAA,MAAM0C,KAAAA,GAASvC,IAAgC,CAACC,GAAAA,CAAI;AAEpD,QAAA,IAAIsB,uBAAuBgB,KAAAA,CAAAA,EAAQ;YACjC,MAAMlC,mBAAAA,EAAAA;AACN,YAAA;AACF,QAAA;AAEA,QAAA,IAAIsC,0BAA0BJ,KAAAA,CAAAA,EAAQ;YACpC,MAAMf,KAAAA,GAAQ,MAAMiB,iCAAAA,CAAkC,IAAA,CAAA;AAEtD,YAAA,IAAIzB,OAAOC,IAAI,CAACO,KAAAA,CAAAA,CAAOX,MAAM,KAAK,CAAA,EAAG;gBACnCV,MAAAA,CAAOF,GAAAA,CAAAA;AACP,gBAAA;AACF,YAAA;AAEAG,YAAAA,GAAAA,CACEH,GAAAA,EACAsC,KAAAA,KAAU,IAAA,IAAQA,KAAAA,KAAU,MAAA,GAAS;gBAAEX,EAAAA,EAAIJ;aAAM,GAAI;AAAE,gBAAA,GAAGe,KAAK;gBAAEL,KAAAA,EAAO,IAAA;gBAAMN,EAAAA,EAAIJ;AAAM,aAAA,CAAA;AAE1F,YAAA;AACF,QAAA;AAEA,QAAA,IAAIoB,mBAAmBL,KAAAA,CAAAA,EAAQ;AAC7B,YAAA;AACF,QAAA;QAEA,MAAMlC,mBAAAA,EAAAA;AACN,QAAA;AACF,IAAA;AAEA,IAAA,IAAI+C,iBAAAA,IAAqBlD,MAAAA,CAAOY,OAAO,EAAEwC,qBAAAA,EAAuB;AAC9D,QAAA;AACF,IAAA;IAEA,MAAMJ,qBAAAA,EAAAA;AACR,CAAA;AAEA;;;;;;;;;;IAWA,MAAMK,qBAAqB,IAAIC,OAAAA,EAAAA;AAE/B,MAAMC,cAAAA,GAAiB,OAAOC,KAAAA,EAAehE,IAAAA,GAAAA;AAC3C,IAAA,MAAMiE,SAAAA,GAAY,OAAOjE,IAAAA,KAAS,QAAA,IAAYA,IAAAA,KAAS,IAAA;IAEvD,IAAIkE,SAAAA;AAEJ,IAAA,IAAID,SAAAA,EAAW;QACbC,SAAAA,GAAYL,kBAAAA,CAAmBM,GAAG,CAACnE,IAAAA,CAAAA;AAEnC,QAAA,IAAIkE,cAAcE,SAAAA,EAAW;AAC3BF,YAAAA,SAAAA,GAAY,IAAIG,GAAAA,EAAAA;YAChBR,kBAAAA,CAAmBnD,GAAG,CAACV,IAAAA,EAAgBkE,SAAAA,CAAAA;QACzC,CAAA,MAAO;YACL,MAAMI,MAAAA,GAASJ,SAAAA,CAAUC,GAAG,CAACH,KAAAA,CAAAA;AAC7B,YAAA,IAAIM,WAAWF,SAAAA,EAAW;gBACxB,OAAOE,MAAAA;AACT,YAAA;AACF,QAAA;AACF,IAAA;IAEA,IAAIC,OAAAA;IACJ,IAAI;AACF,QAAA,MAAMC,MAAAA,CAAOxE,IAAI,CAACyE,MAAM,CAACzE,IAAAA,EAAM;AAAEgE,YAAAA;AAAM,SAAA,CAAA;QACvCO,OAAAA,GAAU,IAAA;AACZ,IAAA,CAAA,CAAE,OAAM;QACNA,OAAAA,GAAU,KAAA;AACZ,IAAA;AAEAL,IAAAA,SAAAA,EAAWxD,IAAIsD,KAAAA,EAAOO,OAAAA,CAAAA;IAEtB,OAAOA,OAAAA;AACT,CAAA;AAEA,MAAMhC,qBAAAA,GAAwB,OAAOJ,MAAAA,EAAkBnC,IAAAA,GAAAA;IACrD,KAAK,MAAMgE,SAAS7B,MAAAA,CAAQ;QAC1B,IAAI,MAAM4B,cAAAA,CAAeC,KAAAA,EAAOhE,IAAAA,CAAAA,EAAO;YACrC,OAAO,IAAA;AACT,QAAA;AACF,IAAA;IAEA,OAAO,KAAA;AACT,CAAA;AAEA,MAAMgD,4BAAAA,GAA+B,IAAA;IACnC,OAAQ1B,OAAOoD,MAAM,CAACF,OAAOG,YAAY,IAAI,EAAC,CAAA,CAC3CvC,GAAG,CAAC,CAACwC,KAAAA,GAAUA,MAAM7C,GAAG,CAAA,CACxB8C,MAAM,CAAC,CAAC9C,GAAAA,GAAuB,OAAOA,GAAAA,KAAQ,QAAA,CAAA;AACnD,CAAA;;;;"}
@@ -1,4 +1,4 @@
1
- import { isObject, isArray } from 'lodash/fp';
1
+ import { isObject } from 'lodash';
2
2
  import { isMorphToRelationalAttribute, constants } from '../../content-types.mjs';
3
3
  import { VALID_RELATION_ORDERING_KEYS } from '../../relations.mjs';
4
4
 
@@ -81,13 +81,13 @@ const visitRelationAttribute = async (auth, { data, key, attribute, schema }, {
81
81
  } else {
82
82
  const newMorphValue = await handleMorphElements(elements);
83
83
  if (!newMorphValue.length) {
84
- if (isArray(elements) && elements.length === 0) {
84
+ if (Array.isArray(elements) && elements.length === 0) {
85
85
  return;
86
86
  }
87
87
  remove(key);
88
88
  return;
89
89
  }
90
- if (isArray(elements)) {
90
+ if (Array.isArray(elements)) {
91
91
  set(key, newMorphValue);
92
92
  return;
93
93
  }
@@ -120,7 +120,7 @@ const visitRelationAttribute = async (auth, { data, key, attribute, schema }, {
120
120
  };
121
121
  const handleMorphElements = async (elements)=>{
122
122
  const allowedElements = [];
123
- const elementsToCheck = isArray(elements) ? elements : [
123
+ const elementsToCheck = Array.isArray(elements) ? elements : [
124
124
  elements
125
125
  ];
126
126
  for (const element of elementsToCheck){
@@ -1 +1 @@
1
- {"version":3,"file":"remove-restricted-relations.mjs","sources":["../../../src/sanitize/visitors/remove-restricted-relations.ts"],"sourcesContent":["import { isArray, isObject } from 'lodash/fp';\nimport * as contentTypeUtils from '../../content-types';\nimport type { Model, RelationOrderingOptions } from '../../types';\nimport type { Visitor } from '../../traverse/factory';\nimport { VALID_RELATION_ORDERING_KEYS } from '../../relations';\n\nconst ACTIONS_TO_VERIFY = ['find'];\nconst { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypeUtils.constants;\n\ntype MorphArray = Array<{ __type: string }>;\ntype MorphElement = Record<string, unknown> & { __type: string };\ntype MorphMutationPayload = {\n connect?: unknown;\n set?: unknown;\n disconnect?: unknown;\n options?: Record<string, unknown> | null;\n};\ntype MorphPopulatePayload = {\n on: Record<string, unknown>;\n count?: unknown;\n};\n\nexport default (auth: unknown): Visitor =>\n (visitorOptions, visitorUtils) => {\n const { attribute } = visitorOptions;\n\n // Deliberately not an `async` function. This visitor is invoked for every key of\n // every node of every entity, and only relation attributes need any work at all.\n // Declaring it `async` meant each of those keys allocated a promise purely to\n // resolve it immediately, and the traversal then awaited it. Returning early\n // without a promise lets the traversal stay synchronous for the common case.\n if (!attribute || attribute.type !== 'relation') {\n return;\n }\n\n return visitRelationAttribute(auth, visitorOptions, visitorUtils) as unknown as void;\n };\n\nconst visitRelationAttribute = async (\n auth: unknown,\n { data, key, attribute, schema }: Parameters<Visitor>[0],\n { remove, set }: Parameters<Visitor>[1]\n) => {\n // Narrowing only; the caller reaches this for relation attributes exclusively.\n if (!attribute) {\n return;\n }\n\n const handleMorphRelation = async () => {\n const elements = (data as Record<string, MorphArray | MorphElement | MorphMutationPayload>)[\n key\n ];\n\n if (!elements) {\n return;\n }\n\n if (isMorphMutationPayload(elements)) {\n const newValue: Record<string, unknown> = {};\n\n const connect = await handleMorphElements(elements.connect || []);\n const relSet = await handleMorphElements(elements.set || []);\n const disconnect = await handleMorphElements(elements.disconnect || []);\n\n if (connect.length > 0) {\n newValue.connect = connect;\n }\n\n if (relSet.length > 0) {\n newValue.set = relSet;\n }\n\n if (disconnect.length > 0) {\n newValue.disconnect = disconnect;\n }\n\n // TODO: this should technically be in its own visitor to check morph options, but for now we'll handle it here\n const options = elements.options;\n if (options && typeof options === 'object') {\n const filteredOptions: RelationOrderingOptions = {};\n\n Object.keys(options).forEach((key) => {\n const optionKey = key as keyof RelationOrderingOptions;\n const validator = VALID_RELATION_ORDERING_KEYS[optionKey];\n const optionValue = options[key];\n\n if (validator && validator(optionValue)) {\n filteredOptions[optionKey] = optionValue as RelationOrderingOptions[typeof optionKey];\n }\n });\n\n newValue.options = filteredOptions;\n } else {\n newValue.options = {};\n }\n\n set(key, newValue);\n } else if (isMorphPopulatePayload(elements)) {\n const newOn: Record<string, unknown> = {};\n\n for (const [uid, subPopulate] of Object.entries(elements.on)) {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${uid}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n newOn[uid] = subPopulate;\n }\n }\n\n if (Object.keys(newOn).length === 0) {\n remove(key);\n return;\n }\n\n const count = isMorphPopulateCount(elements.count) ? true : elements.count;\n set(key, { ...elements, count, on: newOn });\n } else {\n const newMorphValue = await handleMorphElements(elements);\n\n if (!newMorphValue.length) {\n if (isArray(elements) && elements.length === 0) {\n return;\n }\n\n remove(key);\n return;\n }\n\n if (isArray(elements)) {\n set(key, newMorphValue);\n return;\n }\n\n set(key, newMorphValue[0]);\n }\n };\n\n const isMorphMutationPayload = (value: unknown): value is MorphMutationPayload => {\n return isObject(value) && ('connect' in value || 'set' in value || 'disconnect' in value);\n };\n\n const isMorphPopulateCount = (value: unknown) => value === true || value === 'true';\n\n const isMorphPopulatePayload = (value: unknown): value is MorphPopulatePayload => {\n return isObject(value) && !('__type' in value) && 'on' in value && isObject(value.on);\n };\n\n const buildAllowedMorphPopulateFragment = async (subPopulate: unknown) => {\n const newOn: Record<string, unknown> = {};\n\n for (const uid of getRegisteredContentTypeUIDs()) {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${uid}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n newOn[uid] = subPopulate;\n }\n }\n\n return newOn;\n };\n\n const isMorphPopulateAllOrCount = (value: unknown): value is true | 'true' | { count: true } => {\n return (\n value === true ||\n value === 'true' ||\n (isObject(value) && 'count' in value && isMorphPopulateCount(value.count) && !('on' in value))\n );\n };\n\n const isMorphCountOutput = (value: unknown): value is { count: number } => {\n return (\n isObject(value) &&\n 'count' in value &&\n typeof value.count === 'number' &&\n Object.keys(value).length === 1\n );\n };\n\n const handleMorphElements = async (elements: unknown) => {\n const allowedElements: Record<string, unknown>[] = [];\n const elementsToCheck = isArray(elements) ? elements : [elements];\n\n for (const element of elementsToCheck) {\n if (!isObject(element) || !('__type' in element) || typeof element.__type !== 'string') {\n continue;\n }\n\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n allowedElements.push(element);\n }\n }\n\n return allowedElements;\n };\n\n const handleRegularRelation = async () => {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${attribute.target}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (!isAllowed) {\n remove(key);\n }\n };\n\n const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key);\n\n if (contentTypeUtils.isMorphToRelationalAttribute(attribute)) {\n const value = (data as Record<string, unknown>)[key];\n\n if (isMorphPopulatePayload(value)) {\n await handleMorphRelation();\n return;\n }\n\n if (isMorphPopulateAllOrCount(value)) {\n const newOn = await buildAllowedMorphPopulateFragment(true);\n\n if (Object.keys(newOn).length === 0) {\n remove(key);\n return;\n }\n\n set(\n key,\n value === true || value === 'true' ? { on: newOn } : { ...value, count: true, on: newOn }\n );\n return;\n }\n\n if (isMorphCountOutput(value)) {\n return;\n }\n\n await handleMorphRelation();\n return;\n }\n\n if (isCreatorRelation && schema.options?.populateCreatorFields) {\n return;\n }\n\n await handleRegularRelation();\n};\n\n/**\n * Per-`auth` memo of scope decisions.\n *\n * The decision for a given scope depends only on the ability carried by `auth`, which is\n * built once per request and not mutated while the response is sanitized. Sanitizing a\n * list re-asks the same question for every entity, so a 25-entity page with four\n * relations asked ~100 identical questions; each denial also constructed an Error, and\n * capturing a stack trace is by far the most expensive part of that.\n *\n * Keyed weakly on the `auth` object so entries are collected with the request.\n */\nconst scopeDecisionCache = new WeakMap<object, Map<string, boolean>>();\n\nconst canAccessScope = async (scope: string, auth: unknown): Promise<boolean> => {\n const cacheable = typeof auth === 'object' && auth !== null;\n\n let decisions: Map<string, boolean> | undefined;\n\n if (cacheable) {\n decisions = scopeDecisionCache.get(auth as object);\n\n if (decisions === undefined) {\n decisions = new Map();\n scopeDecisionCache.set(auth as object, decisions);\n } else {\n const cached = decisions.get(scope);\n if (cached !== undefined) {\n return cached;\n }\n }\n }\n\n let allowed: boolean;\n try {\n await strapi.auth.verify(auth, { scope });\n allowed = true;\n } catch {\n allowed = false;\n }\n\n decisions?.set(scope, allowed);\n\n return allowed;\n};\n\nconst hasAccessToSomeScopes = async (scopes: string[], auth: unknown) => {\n for (const scope of scopes) {\n if (await canAccessScope(scope, auth)) {\n return true;\n }\n }\n\n return false;\n};\n\nconst getRegisteredContentTypeUIDs = () => {\n return (Object.values(strapi.contentTypes ?? {}) as Model[])\n .map((model) => model.uid)\n .filter((uid): uid is string => typeof uid === 'string');\n};\n"],"names":["ACTIONS_TO_VERIFY","CREATED_BY_ATTRIBUTE","UPDATED_BY_ATTRIBUTE","contentTypeUtils","auth","visitorOptions","visitorUtils","attribute","type","visitRelationAttribute","data","key","schema","remove","set","handleMorphRelation","elements","isMorphMutationPayload","newValue","connect","handleMorphElements","relSet","disconnect","length","options","filteredOptions","Object","keys","forEach","optionKey","validator","VALID_RELATION_ORDERING_KEYS","optionValue","isMorphPopulatePayload","newOn","uid","subPopulate","entries","on","scopes","map","action","isAllowed","hasAccessToSomeScopes","count","isMorphPopulateCount","newMorphValue","isArray","value","isObject","buildAllowedMorphPopulateFragment","getRegisteredContentTypeUIDs","isMorphPopulateAllOrCount","isMorphCountOutput","allowedElements","elementsToCheck","element","__type","push","handleRegularRelation","target","isCreatorRelation","includes","populateCreatorFields","scopeDecisionCache","WeakMap","canAccessScope","scope","cacheable","decisions","get","undefined","Map","cached","allowed","strapi","verify","values","contentTypes","model","filter"],"mappings":"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"}
1
+ {"version":3,"file":"remove-restricted-relations.mjs","sources":["../../../src/sanitize/visitors/remove-restricted-relations.ts"],"sourcesContent":["import { isObject } from 'lodash';\nimport * as contentTypeUtils from '../../content-types';\nimport type { Model, RelationOrderingOptions } from '../../types';\nimport type { Visitor } from '../../traverse/factory';\nimport { VALID_RELATION_ORDERING_KEYS } from '../../relations';\n\nconst ACTIONS_TO_VERIFY = ['find'];\nconst { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypeUtils.constants;\n\ntype MorphArray = Array<{ __type: string }>;\ntype MorphElement = Record<string, unknown> & { __type: string };\ntype MorphMutationPayload = {\n connect?: unknown;\n set?: unknown;\n disconnect?: unknown;\n options?: Record<string, unknown> | null;\n};\ntype MorphPopulatePayload = {\n on: Record<string, unknown>;\n count?: unknown;\n};\n\nexport default (auth: unknown): Visitor =>\n (visitorOptions, visitorUtils) => {\n const { attribute } = visitorOptions;\n\n // Deliberately not an `async` function. This visitor is invoked for every key of\n // every node of every entity, and only relation attributes need any work at all.\n // Declaring it `async` meant each of those keys allocated a promise purely to\n // resolve it immediately, and the traversal then awaited it. Returning early\n // without a promise lets the traversal stay synchronous for the common case.\n if (!attribute || attribute.type !== 'relation') {\n return;\n }\n\n return visitRelationAttribute(auth, visitorOptions, visitorUtils) as unknown as void;\n };\n\nconst visitRelationAttribute = async (\n auth: unknown,\n { data, key, attribute, schema }: Parameters<Visitor>[0],\n { remove, set }: Parameters<Visitor>[1]\n) => {\n // Narrowing only; the caller reaches this for relation attributes exclusively.\n if (!attribute) {\n return;\n }\n\n const handleMorphRelation = async () => {\n const elements = (data as Record<string, MorphArray | MorphElement | MorphMutationPayload>)[\n key\n ];\n\n if (!elements) {\n return;\n }\n\n if (isMorphMutationPayload(elements)) {\n const newValue: Record<string, unknown> = {};\n\n const connect = await handleMorphElements(elements.connect || []);\n const relSet = await handleMorphElements(elements.set || []);\n const disconnect = await handleMorphElements(elements.disconnect || []);\n\n if (connect.length > 0) {\n newValue.connect = connect;\n }\n\n if (relSet.length > 0) {\n newValue.set = relSet;\n }\n\n if (disconnect.length > 0) {\n newValue.disconnect = disconnect;\n }\n\n // TODO: this should technically be in its own visitor to check morph options, but for now we'll handle it here\n const options = elements.options;\n if (options && typeof options === 'object') {\n const filteredOptions: RelationOrderingOptions = {};\n\n Object.keys(options).forEach((key) => {\n const optionKey = key as keyof RelationOrderingOptions;\n const validator = VALID_RELATION_ORDERING_KEYS[optionKey];\n const optionValue = options[key];\n\n if (validator && validator(optionValue)) {\n filteredOptions[optionKey] = optionValue as RelationOrderingOptions[typeof optionKey];\n }\n });\n\n newValue.options = filteredOptions;\n } else {\n newValue.options = {};\n }\n\n set(key, newValue);\n } else if (isMorphPopulatePayload(elements)) {\n const newOn: Record<string, unknown> = {};\n\n for (const [uid, subPopulate] of Object.entries(elements.on)) {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${uid}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n newOn[uid] = subPopulate;\n }\n }\n\n if (Object.keys(newOn).length === 0) {\n remove(key);\n return;\n }\n\n const count = isMorphPopulateCount(elements.count) ? true : elements.count;\n set(key, { ...elements, count, on: newOn });\n } else {\n const newMorphValue = await handleMorphElements(elements);\n\n if (!newMorphValue.length) {\n if (Array.isArray(elements) && elements.length === 0) {\n return;\n }\n\n remove(key);\n return;\n }\n\n if (Array.isArray(elements)) {\n set(key, newMorphValue);\n return;\n }\n\n set(key, newMorphValue[0]);\n }\n };\n\n const isMorphMutationPayload = (value: unknown): value is MorphMutationPayload => {\n return isObject(value) && ('connect' in value || 'set' in value || 'disconnect' in value);\n };\n\n const isMorphPopulateCount = (value: unknown) => value === true || value === 'true';\n\n const isMorphPopulatePayload = (value: unknown): value is MorphPopulatePayload => {\n return isObject(value) && !('__type' in value) && 'on' in value && isObject(value.on);\n };\n\n const buildAllowedMorphPopulateFragment = async (subPopulate: unknown) => {\n const newOn: Record<string, unknown> = {};\n\n for (const uid of getRegisteredContentTypeUIDs()) {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${uid}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n newOn[uid] = subPopulate;\n }\n }\n\n return newOn;\n };\n\n const isMorphPopulateAllOrCount = (value: unknown): value is true | 'true' | { count: true } => {\n return (\n value === true ||\n value === 'true' ||\n (isObject(value) && 'count' in value && isMorphPopulateCount(value.count) && !('on' in value))\n );\n };\n\n const isMorphCountOutput = (value: unknown): value is { count: number } => {\n return (\n isObject(value) &&\n 'count' in value &&\n typeof value.count === 'number' &&\n Object.keys(value).length === 1\n );\n };\n\n const handleMorphElements = async (elements: unknown) => {\n const allowedElements: Record<string, unknown>[] = [];\n const elementsToCheck = Array.isArray(elements) ? elements : [elements];\n\n for (const element of elementsToCheck) {\n if (!isObject(element) || !('__type' in element) || typeof element.__type !== 'string') {\n continue;\n }\n\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (isAllowed) {\n allowedElements.push(element);\n }\n }\n\n return allowedElements;\n };\n\n const handleRegularRelation = async () => {\n const scopes = ACTIONS_TO_VERIFY.map((action) => `${attribute.target}.${action}`);\n const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n if (!isAllowed) {\n remove(key);\n }\n };\n\n const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key);\n\n if (contentTypeUtils.isMorphToRelationalAttribute(attribute)) {\n const value = (data as Record<string, unknown>)[key];\n\n if (isMorphPopulatePayload(value)) {\n await handleMorphRelation();\n return;\n }\n\n if (isMorphPopulateAllOrCount(value)) {\n const newOn = await buildAllowedMorphPopulateFragment(true);\n\n if (Object.keys(newOn).length === 0) {\n remove(key);\n return;\n }\n\n set(\n key,\n value === true || value === 'true' ? { on: newOn } : { ...value, count: true, on: newOn }\n );\n return;\n }\n\n if (isMorphCountOutput(value)) {\n return;\n }\n\n await handleMorphRelation();\n return;\n }\n\n if (isCreatorRelation && schema.options?.populateCreatorFields) {\n return;\n }\n\n await handleRegularRelation();\n};\n\n/**\n * Per-`auth` memo of scope decisions.\n *\n * The decision for a given scope depends only on the ability carried by `auth`, which is\n * built once per request and not mutated while the response is sanitized. Sanitizing a\n * list re-asks the same question for every entity, so a 25-entity page with four\n * relations asked ~100 identical questions; each denial also constructed an Error, and\n * capturing a stack trace is by far the most expensive part of that.\n *\n * Keyed weakly on the `auth` object so entries are collected with the request.\n */\nconst scopeDecisionCache = new WeakMap<object, Map<string, boolean>>();\n\nconst canAccessScope = async (scope: string, auth: unknown): Promise<boolean> => {\n const cacheable = typeof auth === 'object' && auth !== null;\n\n let decisions: Map<string, boolean> | undefined;\n\n if (cacheable) {\n decisions = scopeDecisionCache.get(auth as object);\n\n if (decisions === undefined) {\n decisions = new Map();\n scopeDecisionCache.set(auth as object, decisions);\n } else {\n const cached = decisions.get(scope);\n if (cached !== undefined) {\n return cached;\n }\n }\n }\n\n let allowed: boolean;\n try {\n await strapi.auth.verify(auth, { scope });\n allowed = true;\n } catch {\n allowed = false;\n }\n\n decisions?.set(scope, allowed);\n\n return allowed;\n};\n\nconst hasAccessToSomeScopes = async (scopes: string[], auth: unknown) => {\n for (const scope of scopes) {\n if (await canAccessScope(scope, auth)) {\n return true;\n }\n }\n\n return false;\n};\n\nconst getRegisteredContentTypeUIDs = () => {\n return (Object.values(strapi.contentTypes ?? {}) as Model[])\n .map((model) => model.uid)\n .filter((uid): uid is string => typeof uid === 'string');\n};\n"],"names":["ACTIONS_TO_VERIFY","CREATED_BY_ATTRIBUTE","UPDATED_BY_ATTRIBUTE","contentTypeUtils","auth","visitorOptions","visitorUtils","attribute","type","visitRelationAttribute","data","key","schema","remove","set","handleMorphRelation","elements","isMorphMutationPayload","newValue","connect","handleMorphElements","relSet","disconnect","length","options","filteredOptions","Object","keys","forEach","optionKey","validator","VALID_RELATION_ORDERING_KEYS","optionValue","isMorphPopulatePayload","newOn","uid","subPopulate","entries","on","scopes","map","action","isAllowed","hasAccessToSomeScopes","count","isMorphPopulateCount","newMorphValue","Array","isArray","value","isObject","buildAllowedMorphPopulateFragment","getRegisteredContentTypeUIDs","isMorphPopulateAllOrCount","isMorphCountOutput","allowedElements","elementsToCheck","element","__type","push","handleRegularRelation","target","isCreatorRelation","includes","populateCreatorFields","scopeDecisionCache","WeakMap","canAccessScope","scope","cacheable","decisions","get","undefined","Map","cached","allowed","strapi","verify","values","contentTypes","model","filter"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACxC,aAAa,CAAC,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,EAAE,EACzD,YAAY;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE;WADV,MAAM;aAAW,GAAG;IAyBrD,CAAC"}
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACxC,aAAa,CAAC,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,EAAE,EACzD,YAAY;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE;WADV,MAAM;aAAW,GAAG;IAqBrD,CAAC"}
package/dist/security.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var fp = require('lodash/fp');
3
+ var _ = require('lodash');
4
4
 
5
5
  const CSP_DEFAULTS = {
6
6
  'connect-src': [
@@ -33,12 +33,12 @@ const CSP_DEFAULTS = {
33
33
  }
34
34
  if (typeof currentMiddleware === 'object' && currentMiddleware.name === middleware.name) {
35
35
  // Deep merge (+ concat arrays) the new config with the current middleware config
36
- return fp.mergeWith((objValue, srcValue)=>{
36
+ return _.mergeWith({}, currentMiddleware, middleware, (objValue, srcValue)=>{
37
37
  if (Array.isArray(objValue)) {
38
38
  return Array.from(new Set(objValue.concat(srcValue)));
39
39
  }
40
40
  return undefined;
41
- }, currentMiddleware, middleware);
41
+ });
42
42
  }
43
43
  return currentMiddleware;
44
44
  });
@@ -1 +1 @@
1
- {"version":3,"file":"security.js","sources":["../src/security.ts"],"sourcesContent":["import { mergeWith } from 'lodash/fp';\n\nexport const CSP_DEFAULTS = {\n 'connect-src': [\"'self'\", 'https:'],\n 'img-src': [\"'self'\", 'data:', 'blob:', 'https://market-assets.strapi.io'],\n 'media-src': [\"'self'\", 'data:', 'blob:'],\n} as const;\n\n/**\n * Utility to extend Strapi middleware configuration. Mainly used to extend the CSP directives from the security middleware.\n *\n * @param middlewares - Array of middleware configurations\n * @param middleware - Middleware configuration to merge/add\n * @returns Modified middlewares array with the new configuration merged\n */\nexport const extendMiddlewareConfiguration = (\n middlewares: (string | { name?: string; config?: any })[],\n middleware: { name: string; config?: any }\n) => {\n return middlewares.map((currentMiddleware) => {\n if (typeof currentMiddleware === 'string' && currentMiddleware === middleware.name) {\n // Use the new config object if the middleware has no config property yet\n return middleware;\n }\n\n if (typeof currentMiddleware === 'object' && currentMiddleware.name === middleware.name) {\n // Deep merge (+ concat arrays) the new config with the current middleware config\n return mergeWith(\n (objValue, srcValue) => {\n if (Array.isArray(objValue)) {\n return Array.from(new Set(objValue.concat(srcValue)));\n }\n return undefined;\n },\n currentMiddleware,\n middleware\n );\n }\n\n return currentMiddleware;\n });\n};\n"],"names":["CSP_DEFAULTS","extendMiddlewareConfiguration","middlewares","middleware","map","currentMiddleware","name","mergeWith","objValue","srcValue","Array","isArray","from","Set","concat","undefined"],"mappings":";;;;MAEaA,YAAAA,GAAe;IAC1B,aAAA,EAAe;AAAC,QAAA,QAAA;AAAU,QAAA;AAAS,KAAA;IACnC,SAAA,EAAW;AAAC,QAAA,QAAA;AAAU,QAAA,OAAA;AAAS,QAAA,OAAA;AAAS,QAAA;AAAkC,KAAA;IAC1E,WAAA,EAAa;AAAC,QAAA,QAAA;AAAU,QAAA,OAAA;AAAS,QAAA;AAAQ;AAC3C;AAEA;;;;;;AAMC,IACM,MAAMC,6BAAAA,GAAgC,CAC3CC,WAAAA,EACAC,UAAAA,GAAAA;IAEA,OAAOD,WAAAA,CAAYE,GAAG,CAAC,CAACC,iBAAAA,GAAAA;AACtB,QAAA,IAAI,OAAOA,iBAAAA,KAAsB,QAAA,IAAYA,iBAAAA,KAAsBF,UAAAA,CAAWG,IAAI,EAAE;;YAElF,OAAOH,UAAAA;AACT,QAAA;QAEA,IAAI,OAAOE,sBAAsB,QAAA,IAAYA,iBAAAA,CAAkBC,IAAI,KAAKH,UAAAA,CAAWG,IAAI,EAAE;;YAEvF,OAAOC,YAAAA,CACL,CAACC,QAAAA,EAAUC,QAAAA,GAAAA;gBACT,IAAIC,KAAAA,CAAMC,OAAO,CAACH,QAAAA,CAAAA,EAAW;AAC3B,oBAAA,OAAOE,MAAME,IAAI,CAAC,IAAIC,GAAAA,CAAIL,QAAAA,CAASM,MAAM,CAACL,QAAAA,CAAAA,CAAAA,CAAAA;AAC5C,gBAAA;gBACA,OAAOM,SAAAA;AACT,YAAA,CAAA,EACAV,iBAAAA,EACAF,UAAAA,CAAAA;AAEJ,QAAA;QAEA,OAAOE,iBAAAA;AACT,IAAA,CAAA,CAAA;AACF;;;;;"}
1
+ {"version":3,"file":"security.js","sources":["../src/security.ts"],"sourcesContent":["import { mergeWith } from 'lodash';\n\nexport const CSP_DEFAULTS = {\n 'connect-src': [\"'self'\", 'https:'],\n 'img-src': [\"'self'\", 'data:', 'blob:', 'https://market-assets.strapi.io'],\n 'media-src': [\"'self'\", 'data:', 'blob:'],\n} as const;\n\n/**\n * Utility to extend Strapi middleware configuration. Mainly used to extend the CSP directives from the security middleware.\n *\n * @param middlewares - Array of middleware configurations\n * @param middleware - Middleware configuration to merge/add\n * @returns Modified middlewares array with the new configuration merged\n */\nexport const extendMiddlewareConfiguration = (\n middlewares: (string | { name?: string; config?: any })[],\n middleware: { name: string; config?: any }\n) => {\n return middlewares.map((currentMiddleware) => {\n if (typeof currentMiddleware === 'string' && currentMiddleware === middleware.name) {\n // Use the new config object if the middleware has no config property yet\n return middleware;\n }\n\n if (typeof currentMiddleware === 'object' && currentMiddleware.name === middleware.name) {\n // Deep merge (+ concat arrays) the new config with the current middleware config\n return mergeWith({}, currentMiddleware, middleware, (objValue, srcValue) => {\n if (Array.isArray(objValue)) {\n return Array.from(new Set(objValue.concat(srcValue)));\n }\n return undefined;\n });\n }\n\n return currentMiddleware;\n });\n};\n"],"names":["CSP_DEFAULTS","extendMiddlewareConfiguration","middlewares","middleware","map","currentMiddleware","name","mergeWith","objValue","srcValue","Array","isArray","from","Set","concat","undefined"],"mappings":";;;;MAEaA,YAAAA,GAAe;IAC1B,aAAA,EAAe;AAAC,QAAA,QAAA;AAAU,QAAA;AAAS,KAAA;IACnC,SAAA,EAAW;AAAC,QAAA,QAAA;AAAU,QAAA,OAAA;AAAS,QAAA,OAAA;AAAS,QAAA;AAAkC,KAAA;IAC1E,WAAA,EAAa;AAAC,QAAA,QAAA;AAAU,QAAA,OAAA;AAAS,QAAA;AAAQ;AAC3C;AAEA;;;;;;AAMC,IACM,MAAMC,6BAAAA,GAAgC,CAC3CC,WAAAA,EACAC,UAAAA,GAAAA;IAEA,OAAOD,WAAAA,CAAYE,GAAG,CAAC,CAACC,iBAAAA,GAAAA;AACtB,QAAA,IAAI,OAAOA,iBAAAA,KAAsB,QAAA,IAAYA,iBAAAA,KAAsBF,UAAAA,CAAWG,IAAI,EAAE;;YAElF,OAAOH,UAAAA;AACT,QAAA;QAEA,IAAI,OAAOE,sBAAsB,QAAA,IAAYA,iBAAAA,CAAkBC,IAAI,KAAKH,UAAAA,CAAWG,IAAI,EAAE;;AAEvF,YAAA,OAAOC,YAAU,EAAC,EAAGF,iBAAAA,EAAmBF,UAAAA,EAAY,CAACK,QAAAA,EAAUC,QAAAA,GAAAA;gBAC7D,IAAIC,KAAAA,CAAMC,OAAO,CAACH,QAAAA,CAAAA,EAAW;AAC3B,oBAAA,OAAOE,MAAME,IAAI,CAAC,IAAIC,GAAAA,CAAIL,QAAAA,CAASM,MAAM,CAACL,QAAAA,CAAAA,CAAAA,CAAAA;AAC5C,gBAAA;gBACA,OAAOM,SAAAA;AACT,YAAA,CAAA,CAAA;AACF,QAAA;QAEA,OAAOV,iBAAAA;AACT,IAAA,CAAA,CAAA;AACF;;;;;"}
package/dist/security.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { mergeWith } from 'lodash/fp';
1
+ import { mergeWith } from 'lodash';
2
2
 
3
3
  const CSP_DEFAULTS = {
4
4
  'connect-src': [
@@ -31,12 +31,12 @@ const CSP_DEFAULTS = {
31
31
  }
32
32
  if (typeof currentMiddleware === 'object' && currentMiddleware.name === middleware.name) {
33
33
  // Deep merge (+ concat arrays) the new config with the current middleware config
34
- return mergeWith((objValue, srcValue)=>{
34
+ return mergeWith({}, currentMiddleware, middleware, (objValue, srcValue)=>{
35
35
  if (Array.isArray(objValue)) {
36
36
  return Array.from(new Set(objValue.concat(srcValue)));
37
37
  }
38
38
  return undefined;
39
- }, currentMiddleware, middleware);
39
+ });
40
40
  }
41
41
  return currentMiddleware;
42
42
  });
@@ -1 +1 @@
1
- {"version":3,"file":"security.mjs","sources":["../src/security.ts"],"sourcesContent":["import { mergeWith } from 'lodash/fp';\n\nexport const CSP_DEFAULTS = {\n 'connect-src': [\"'self'\", 'https:'],\n 'img-src': [\"'self'\", 'data:', 'blob:', 'https://market-assets.strapi.io'],\n 'media-src': [\"'self'\", 'data:', 'blob:'],\n} as const;\n\n/**\n * Utility to extend Strapi middleware configuration. Mainly used to extend the CSP directives from the security middleware.\n *\n * @param middlewares - Array of middleware configurations\n * @param middleware - Middleware configuration to merge/add\n * @returns Modified middlewares array with the new configuration merged\n */\nexport const extendMiddlewareConfiguration = (\n middlewares: (string | { name?: string; config?: any })[],\n middleware: { name: string; config?: any }\n) => {\n return middlewares.map((currentMiddleware) => {\n if (typeof currentMiddleware === 'string' && currentMiddleware === middleware.name) {\n // Use the new config object if the middleware has no config property yet\n return middleware;\n }\n\n if (typeof currentMiddleware === 'object' && currentMiddleware.name === middleware.name) {\n // Deep merge (+ concat arrays) the new config with the current middleware config\n return mergeWith(\n (objValue, srcValue) => {\n if (Array.isArray(objValue)) {\n return Array.from(new Set(objValue.concat(srcValue)));\n }\n return undefined;\n },\n currentMiddleware,\n middleware\n );\n }\n\n return currentMiddleware;\n });\n};\n"],"names":["CSP_DEFAULTS","extendMiddlewareConfiguration","middlewares","middleware","map","currentMiddleware","name","mergeWith","objValue","srcValue","Array","isArray","from","Set","concat","undefined"],"mappings":";;MAEaA,YAAAA,GAAe;IAC1B,aAAA,EAAe;AAAC,QAAA,QAAA;AAAU,QAAA;AAAS,KAAA;IACnC,SAAA,EAAW;AAAC,QAAA,QAAA;AAAU,QAAA,OAAA;AAAS,QAAA,OAAA;AAAS,QAAA;AAAkC,KAAA;IAC1E,WAAA,EAAa;AAAC,QAAA,QAAA;AAAU,QAAA,OAAA;AAAS,QAAA;AAAQ;AAC3C;AAEA;;;;;;AAMC,IACM,MAAMC,6BAAAA,GAAgC,CAC3CC,WAAAA,EACAC,UAAAA,GAAAA;IAEA,OAAOD,WAAAA,CAAYE,GAAG,CAAC,CAACC,iBAAAA,GAAAA;AACtB,QAAA,IAAI,OAAOA,iBAAAA,KAAsB,QAAA,IAAYA,iBAAAA,KAAsBF,UAAAA,CAAWG,IAAI,EAAE;;YAElF,OAAOH,UAAAA;AACT,QAAA;QAEA,IAAI,OAAOE,sBAAsB,QAAA,IAAYA,iBAAAA,CAAkBC,IAAI,KAAKH,UAAAA,CAAWG,IAAI,EAAE;;YAEvF,OAAOC,SAAAA,CACL,CAACC,QAAAA,EAAUC,QAAAA,GAAAA;gBACT,IAAIC,KAAAA,CAAMC,OAAO,CAACH,QAAAA,CAAAA,EAAW;AAC3B,oBAAA,OAAOE,MAAME,IAAI,CAAC,IAAIC,GAAAA,CAAIL,QAAAA,CAASM,MAAM,CAACL,QAAAA,CAAAA,CAAAA,CAAAA;AAC5C,gBAAA;gBACA,OAAOM,SAAAA;AACT,YAAA,CAAA,EACAV,iBAAAA,EACAF,UAAAA,CAAAA;AAEJ,QAAA;QAEA,OAAOE,iBAAAA;AACT,IAAA,CAAA,CAAA;AACF;;;;"}
1
+ {"version":3,"file":"security.mjs","sources":["../src/security.ts"],"sourcesContent":["import { mergeWith } from 'lodash';\n\nexport const CSP_DEFAULTS = {\n 'connect-src': [\"'self'\", 'https:'],\n 'img-src': [\"'self'\", 'data:', 'blob:', 'https://market-assets.strapi.io'],\n 'media-src': [\"'self'\", 'data:', 'blob:'],\n} as const;\n\n/**\n * Utility to extend Strapi middleware configuration. Mainly used to extend the CSP directives from the security middleware.\n *\n * @param middlewares - Array of middleware configurations\n * @param middleware - Middleware configuration to merge/add\n * @returns Modified middlewares array with the new configuration merged\n */\nexport const extendMiddlewareConfiguration = (\n middlewares: (string | { name?: string; config?: any })[],\n middleware: { name: string; config?: any }\n) => {\n return middlewares.map((currentMiddleware) => {\n if (typeof currentMiddleware === 'string' && currentMiddleware === middleware.name) {\n // Use the new config object if the middleware has no config property yet\n return middleware;\n }\n\n if (typeof currentMiddleware === 'object' && currentMiddleware.name === middleware.name) {\n // Deep merge (+ concat arrays) the new config with the current middleware config\n return mergeWith({}, currentMiddleware, middleware, (objValue, srcValue) => {\n if (Array.isArray(objValue)) {\n return Array.from(new Set(objValue.concat(srcValue)));\n }\n return undefined;\n });\n }\n\n return currentMiddleware;\n });\n};\n"],"names":["CSP_DEFAULTS","extendMiddlewareConfiguration","middlewares","middleware","map","currentMiddleware","name","mergeWith","objValue","srcValue","Array","isArray","from","Set","concat","undefined"],"mappings":";;MAEaA,YAAAA,GAAe;IAC1B,aAAA,EAAe;AAAC,QAAA,QAAA;AAAU,QAAA;AAAS,KAAA;IACnC,SAAA,EAAW;AAAC,QAAA,QAAA;AAAU,QAAA,OAAA;AAAS,QAAA,OAAA;AAAS,QAAA;AAAkC,KAAA;IAC1E,WAAA,EAAa;AAAC,QAAA,QAAA;AAAU,QAAA,OAAA;AAAS,QAAA;AAAQ;AAC3C;AAEA;;;;;;AAMC,IACM,MAAMC,6BAAAA,GAAgC,CAC3CC,WAAAA,EACAC,UAAAA,GAAAA;IAEA,OAAOD,WAAAA,CAAYE,GAAG,CAAC,CAACC,iBAAAA,GAAAA;AACtB,QAAA,IAAI,OAAOA,iBAAAA,KAAsB,QAAA,IAAYA,iBAAAA,KAAsBF,UAAAA,CAAWG,IAAI,EAAE;;YAElF,OAAOH,UAAAA;AACT,QAAA;QAEA,IAAI,OAAOE,sBAAsB,QAAA,IAAYA,iBAAAA,CAAkBC,IAAI,KAAKH,UAAAA,CAAWG,IAAI,EAAE;;AAEvF,YAAA,OAAOC,UAAU,EAAC,EAAGF,iBAAAA,EAAmBF,UAAAA,EAAY,CAACK,QAAAA,EAAUC,QAAAA,GAAAA;gBAC7D,IAAIC,KAAAA,CAAMC,OAAO,CAACH,QAAAA,CAAAA,EAAW;AAC3B,oBAAA,OAAOE,MAAME,IAAI,CAAC,IAAIC,GAAAA,CAAIL,QAAAA,CAASM,MAAM,CAACL,QAAAA,CAAAA,CAAAA,CAAAA;AAC5C,gBAAA;gBACA,OAAOM,SAAAA;AACT,YAAA,CAAA,CAAA;AACF,QAAA;QAEA,OAAOV,iBAAAA;AACT,IAAA,CAAA,CAAA;AACF;;;;"}
@@ -1,3 +1,4 @@
1
+ declare const UPDATED_BY_ATTRIBUTE: string;
1
2
  export interface Options {
2
3
  user: User;
3
4
  isEdition?: boolean;
@@ -5,6 +6,8 @@ export interface Options {
5
6
  interface User {
6
7
  id: string | number;
7
8
  }
8
- declare const setCreatorFields: <TData extends object>({ user, isEdition }: Options) => <TDataInner extends object = TData>(data: TDataInner) => TDataInner;
9
+ declare const setCreatorFields: <TData extends object>({ user, isEdition }: Options) => <TDataInner extends object = TData>(data: TDataInner) => TDataInner & {
10
+ [UPDATED_BY_ATTRIBUTE]: string | number;
11
+ };
9
12
  export default setCreatorFields;
10
13
  //# sourceMappingURL=set-creator-fields.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"set-creator-fields.d.ts","sourceRoot":"","sources":["../src/set-creator-fields.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,IAAI;IACZ,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB;AAED,QAAA,MAAM,gBAAgB,GACnB,KAAK,SAAS,MAAM,EAAE,qBAA6B,OAAO,MAC1D,UAAU,SAAS,MAAM,GAAG,KAAK,EAAE,MAAM,UAAU,eASnD,CAAC;AAEJ,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"set-creator-fields.d.ts","sourceRoot":"","sources":["../src/set-creator-fields.ts"],"names":[],"mappings":"AAEA,QAAA,MAA8B,oBAAoB,QAA2B,CAAC;AAE9E,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,IAAI;IACZ,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB;AAED,QAAA,MAAM,gBAAgB,GACnB,KAAK,SAAS,MAAM,EAAE,qBAA6B,OAAO,MAC1D,UAAU,SAAS,MAAM,GAAG,KAAK,EAAE,MAAM,UAAU;IAE9B,CAAC,oBAAoB,CAAC,kBAAS;CAQpD,CAAC;AAEJ,eAAe,gBAAgB,CAAC"}
@@ -1,17 +1,20 @@
1
1
  'use strict';
2
2
 
3
- var fp = require('lodash/fp');
4
3
  var contentTypes = require('./content-types.js');
5
4
 
6
5
  const { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypes.constants;
7
6
  const setCreatorFields = ({ user, isEdition = false })=>(data)=>{
8
7
  if (isEdition) {
9
- return fp.assoc(UPDATED_BY_ATTRIBUTE, user.id, data);
8
+ return {
9
+ ...data,
10
+ [UPDATED_BY_ATTRIBUTE]: user.id
11
+ };
10
12
  }
11
- return fp.assign(data, {
13
+ return {
14
+ ...data,
12
15
  [CREATED_BY_ATTRIBUTE]: user.id,
13
16
  [UPDATED_BY_ATTRIBUTE]: user.id
14
- });
17
+ };
15
18
  };
16
19
 
17
20
  module.exports = setCreatorFields;
@@ -1 +1 @@
1
- {"version":3,"file":"set-creator-fields.js","sources":["../src/set-creator-fields.ts"],"sourcesContent":["import { assign, assoc } from 'lodash/fp';\nimport * as contentTypes from './content-types';\n\nconst { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypes.constants;\n\nexport interface Options {\n user: User;\n isEdition?: boolean;\n}\n\ninterface User {\n id: string | number;\n}\n\nconst setCreatorFields =\n <TData extends object>({ user, isEdition = false }: Options) =>\n <TDataInner extends object = TData>(data: TDataInner) => {\n if (isEdition) {\n return assoc(UPDATED_BY_ATTRIBUTE, user.id, data);\n }\n\n return assign(data, {\n [CREATED_BY_ATTRIBUTE]: user.id,\n [UPDATED_BY_ATTRIBUTE]: user.id,\n });\n };\n\nexport default setCreatorFields;\n"],"names":["CREATED_BY_ATTRIBUTE","UPDATED_BY_ATTRIBUTE","contentTypes","setCreatorFields","user","isEdition","data","assoc","id","assign"],"mappings":";;;;;AAGA,MAAM,EAAEA,oBAAoB,EAAEC,oBAAoB,EAAE,GAAGC,sBAAsB;AAW7E,MAAMC,gBAAAA,GACJ,CAAuB,EAAEC,IAAI,EAAEC,SAAAA,GAAY,KAAK,EAAW,GAC3D,CAAoCC,IAAAA,GAAAA;AAClC,QAAA,IAAID,SAAAA,EAAW;AACb,YAAA,OAAOE,QAAAA,CAAMN,oBAAAA,EAAsBG,IAAAA,CAAKI,EAAE,EAAEF,IAAAA,CAAAA;AAC9C,QAAA;AAEA,QAAA,OAAOG,UAAOH,IAAAA,EAAM;YAClB,CAACN,oBAAAA,GAAuBI,IAAAA,CAAKI,EAAE;YAC/B,CAACP,oBAAAA,GAAuBG,IAAAA,CAAKI;AAC/B,SAAA,CAAA;AACF,IAAA;;;;"}
1
+ {"version":3,"file":"set-creator-fields.js","sources":["../src/set-creator-fields.ts"],"sourcesContent":["import * as contentTypes from './content-types';\n\nconst { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypes.constants;\n\nexport interface Options {\n user: User;\n isEdition?: boolean;\n}\n\ninterface User {\n id: string | number;\n}\n\nconst setCreatorFields =\n <TData extends object>({ user, isEdition = false }: Options) =>\n <TDataInner extends object = TData>(data: TDataInner) => {\n if (isEdition) {\n return { ...data, [UPDATED_BY_ATTRIBUTE]: user.id };\n }\n\n return {\n ...data,\n [CREATED_BY_ATTRIBUTE]: user.id,\n [UPDATED_BY_ATTRIBUTE]: user.id,\n };\n };\n\nexport default setCreatorFields;\n"],"names":["CREATED_BY_ATTRIBUTE","UPDATED_BY_ATTRIBUTE","contentTypes","setCreatorFields","user","isEdition","data","id"],"mappings":";;;;AAEA,MAAM,EAAEA,oBAAoB,EAAEC,oBAAoB,EAAE,GAAGC,sBAAsB;AAW7E,MAAMC,gBAAAA,GACJ,CAAuB,EAAEC,IAAI,EAAEC,SAAAA,GAAY,KAAK,EAAW,GAC3D,CAAoCC,IAAAA,GAAAA;AAClC,QAAA,IAAID,SAAAA,EAAW;YACb,OAAO;AAAE,gBAAA,GAAGC,IAAI;gBAAE,CAACL,oBAAAA,GAAuBG,IAAAA,CAAKG;AAAG,aAAA;AACpD,QAAA;QAEA,OAAO;AACL,YAAA,GAAGD,IAAI;YACP,CAACN,oBAAAA,GAAuBI,IAAAA,CAAKG,EAAE;YAC/B,CAACN,oBAAAA,GAAuBG,IAAAA,CAAKG;AAC/B,SAAA;AACF,IAAA;;;;"}
@@ -1,15 +1,18 @@
1
- import { assoc, assign } from 'lodash/fp';
2
1
  import { constants } from './content-types.mjs';
3
2
 
4
3
  const { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = constants;
5
4
  const setCreatorFields = ({ user, isEdition = false })=>(data)=>{
6
5
  if (isEdition) {
7
- return assoc(UPDATED_BY_ATTRIBUTE, user.id, data);
6
+ return {
7
+ ...data,
8
+ [UPDATED_BY_ATTRIBUTE]: user.id
9
+ };
8
10
  }
9
- return assign(data, {
11
+ return {
12
+ ...data,
10
13
  [CREATED_BY_ATTRIBUTE]: user.id,
11
14
  [UPDATED_BY_ATTRIBUTE]: user.id
12
- });
15
+ };
13
16
  };
14
17
 
15
18
  export { setCreatorFields as default };
@@ -1 +1 @@
1
- {"version":3,"file":"set-creator-fields.mjs","sources":["../src/set-creator-fields.ts"],"sourcesContent":["import { assign, assoc } from 'lodash/fp';\nimport * as contentTypes from './content-types';\n\nconst { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypes.constants;\n\nexport interface Options {\n user: User;\n isEdition?: boolean;\n}\n\ninterface User {\n id: string | number;\n}\n\nconst setCreatorFields =\n <TData extends object>({ user, isEdition = false }: Options) =>\n <TDataInner extends object = TData>(data: TDataInner) => {\n if (isEdition) {\n return assoc(UPDATED_BY_ATTRIBUTE, user.id, data);\n }\n\n return assign(data, {\n [CREATED_BY_ATTRIBUTE]: user.id,\n [UPDATED_BY_ATTRIBUTE]: user.id,\n });\n };\n\nexport default setCreatorFields;\n"],"names":["CREATED_BY_ATTRIBUTE","UPDATED_BY_ATTRIBUTE","contentTypes","setCreatorFields","user","isEdition","data","assoc","id","assign"],"mappings":";;;AAGA,MAAM,EAAEA,oBAAoB,EAAEC,oBAAoB,EAAE,GAAGC,SAAsB;AAW7E,MAAMC,gBAAAA,GACJ,CAAuB,EAAEC,IAAI,EAAEC,SAAAA,GAAY,KAAK,EAAW,GAC3D,CAAoCC,IAAAA,GAAAA;AAClC,QAAA,IAAID,SAAAA,EAAW;AACb,YAAA,OAAOE,KAAAA,CAAMN,oBAAAA,EAAsBG,IAAAA,CAAKI,EAAE,EAAEF,IAAAA,CAAAA;AAC9C,QAAA;AAEA,QAAA,OAAOG,OAAOH,IAAAA,EAAM;YAClB,CAACN,oBAAAA,GAAuBI,IAAAA,CAAKI,EAAE;YAC/B,CAACP,oBAAAA,GAAuBG,IAAAA,CAAKI;AAC/B,SAAA,CAAA;AACF,IAAA;;;;"}
1
+ {"version":3,"file":"set-creator-fields.mjs","sources":["../src/set-creator-fields.ts"],"sourcesContent":["import * as contentTypes from './content-types';\n\nconst { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypes.constants;\n\nexport interface Options {\n user: User;\n isEdition?: boolean;\n}\n\ninterface User {\n id: string | number;\n}\n\nconst setCreatorFields =\n <TData extends object>({ user, isEdition = false }: Options) =>\n <TDataInner extends object = TData>(data: TDataInner) => {\n if (isEdition) {\n return { ...data, [UPDATED_BY_ATTRIBUTE]: user.id };\n }\n\n return {\n ...data,\n [CREATED_BY_ATTRIBUTE]: user.id,\n [UPDATED_BY_ATTRIBUTE]: user.id,\n };\n };\n\nexport default setCreatorFields;\n"],"names":["CREATED_BY_ATTRIBUTE","UPDATED_BY_ATTRIBUTE","contentTypes","setCreatorFields","user","isEdition","data","id"],"mappings":";;AAEA,MAAM,EAAEA,oBAAoB,EAAEC,oBAAoB,EAAE,GAAGC,SAAsB;AAW7E,MAAMC,gBAAAA,GACJ,CAAuB,EAAEC,IAAI,EAAEC,SAAAA,GAAY,KAAK,EAAW,GAC3D,CAAoCC,IAAAA,GAAAA;AAClC,QAAA,IAAID,SAAAA,EAAW;YACb,OAAO;AAAE,gBAAA,GAAGC,IAAI;gBAAE,CAACL,oBAAAA,GAAuBG,IAAAA,CAAKG;AAAG,aAAA;AACpD,QAAA;QAEA,OAAO;AACL,YAAA,GAAGD,IAAI;YACP,CAACN,oBAAAA,GAAuBI,IAAAA,CAAKG,EAAE;YAC/B,CAACN,oBAAAA,GAAuBG,IAAAA,CAAKG;AAC/B,SAAA;AACF,IAAA;;;;"}