@sap/cds 5.9.6 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (381) hide show
  1. package/CHANGELOG.md +266 -20
  2. package/apis/services.d.ts +1 -1
  3. package/app/fiori/preview.js +2 -6
  4. package/app/index.js +3 -3
  5. package/bin/build/buildTaskEngine.js +17 -15
  6. package/bin/build/buildTaskFactory.js +29 -19
  7. package/bin/build/buildTaskHandler.js +27 -11
  8. package/bin/build/buildTaskProvider.js +2 -4
  9. package/bin/build/buildTaskProviderFactory.js +11 -16
  10. package/bin/build/constants.js +14 -6
  11. package/bin/build/csv-reader.js +2 -1
  12. package/bin/build/index.js +12 -18
  13. package/bin/build/provider/buildTaskHandlerEdmx.js +3 -39
  14. package/bin/build/provider/buildTaskHandlerFeatureToggles.js +149 -0
  15. package/bin/build/provider/buildTaskHandlerInternal.js +2 -3
  16. package/bin/build/provider/buildTaskProviderInternal.js +108 -239
  17. package/bin/build/provider/fiori/index.js +2 -2
  18. package/bin/build/provider/hana/2migration.js +11 -11
  19. package/bin/build/provider/hana/2tabledata.js +3 -3
  20. package/bin/build/provider/hana/index.js +89 -99
  21. package/bin/build/provider/hana/migrationtable.js +4 -3
  22. package/bin/build/provider/java/index.js +101 -0
  23. package/bin/build/provider/java-cf/index.js +1 -101
  24. package/bin/build/provider/mtx/index.js +90 -53
  25. package/bin/build/provider/mtx/resourcesTarBuilder.js +68 -0
  26. package/bin/build/provider/mtx-sidecar/index.js +80 -0
  27. package/bin/build/provider/node-cf/index.js +1 -308
  28. package/bin/build/provider/nodejs/index.js +189 -0
  29. package/bin/build/util.js +19 -31
  30. package/bin/cds.js +5 -3
  31. package/bin/deploy/to-hana/cfUtil.js +31 -6
  32. package/bin/deploy/to-hana/gitUtil.js +5 -3
  33. package/bin/deploy/to-hana/hana.js +9 -10
  34. package/bin/{build → deploy/to-hana}/mtaUtil.js +10 -9
  35. package/bin/mtx/in-cds.js +19 -7
  36. package/bin/serve.js +56 -21
  37. package/bin/utils/log.js +13 -30
  38. package/bin/version.js +5 -4
  39. package/common.cds +61 -16
  40. package/lib/compile/cdsc.js +3 -2
  41. package/lib/compile/etc/_localized.js +15 -14
  42. package/lib/compile/for/drafts.js +3 -4
  43. package/lib/compile/for/java.js +13 -10
  44. package/lib/compile/for/nodejs.js +8 -8
  45. package/lib/compile/for/odata.js +7 -12
  46. package/lib/compile/for/sql.js +5 -6
  47. package/lib/compile/index.js +5 -4
  48. package/lib/compile/load.js +9 -11
  49. package/lib/compile/minify.js +8 -5
  50. package/lib/compile/parse.js +4 -2
  51. package/lib/compile/resolve.js +18 -15
  52. package/lib/compile/to/edm.js +0 -1
  53. package/lib/compile/to/gql.js +3 -2
  54. package/lib/compile/to/json.js +24 -17
  55. package/lib/connect/bindings.js +3 -2
  56. package/lib/connect/index.js +5 -5
  57. package/lib/core/classes.js +74 -2
  58. package/lib/core/entities.js +52 -3
  59. package/lib/core/reflect.js +2 -1
  60. package/lib/deploy.js +11 -8
  61. package/lib/env/defaults.js +4 -3
  62. package/lib/env/index.js +71 -31
  63. package/lib/env/presets.js +1 -14
  64. package/lib/env/requires.js +70 -20
  65. package/lib/env/serviceBindings.js +147 -0
  66. package/lib/i18n/localize.js +22 -23
  67. package/lib/index.js +148 -144
  68. package/lib/log/errors.js +55 -12
  69. package/lib/log/format/kibana.js +1 -1
  70. package/lib/log/index.js +4 -0
  71. package/lib/ql/SELECT.js +7 -2
  72. package/lib/ql/Whereable.js +8 -2
  73. package/lib/ql/index.js +2 -2
  74. package/lib/req/assert.js +71 -0
  75. package/lib/req/cds-context.js +38 -70
  76. package/lib/req/context.js +34 -21
  77. package/lib/req/request.js +12 -18
  78. package/lib/req/response.js +6 -2
  79. package/lib/req/user.js +30 -22
  80. package/lib/serve/Service-api.js +17 -12
  81. package/lib/serve/Service-dispatch.js +5 -9
  82. package/lib/serve/Service-methods.js +4 -3
  83. package/lib/serve/Transaction.js +24 -21
  84. package/lib/serve/adapters.js +15 -5
  85. package/lib/serve/factory.js +23 -20
  86. package/lib/serve/index.js +51 -54
  87. package/lib/utils/axios.js +8 -12
  88. package/lib/utils/index.js +3 -3
  89. package/lib/utils/resources/index.js +1 -44
  90. package/lib/utils/resources/tar.js +2 -1
  91. package/lib/utils/tests.js +13 -15
  92. package/libx/_runtime/.eslintrc +1 -1
  93. package/libx/_runtime/audit/Service.js +6 -4
  94. package/libx/_runtime/audit/generic/personal/access.js +19 -43
  95. package/libx/_runtime/audit/generic/personal/index.js +40 -34
  96. package/libx/_runtime/audit/generic/personal/modification.js +11 -9
  97. package/libx/_runtime/audit/generic/personal/utils.js +13 -6
  98. package/libx/_runtime/audit/utils/v2.js +6 -3
  99. package/libx/_runtime/auth/index.js +71 -66
  100. package/libx/_runtime/auth/strategies/JWT.js +3 -2
  101. package/libx/_runtime/auth/strategies/mock.js +54 -53
  102. package/libx/_runtime/auth/strategies/xssecUtils.js +3 -4
  103. package/libx/_runtime/auth/strategies/xsuaa.js +3 -2
  104. package/libx/_runtime/auth/utils.js +2 -15
  105. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +128 -42
  106. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +6 -3
  107. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +93 -73
  108. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +10 -45
  109. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +5 -9
  110. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +9 -5
  111. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +4 -2
  112. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +60 -53
  113. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +1 -1
  114. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +15 -21
  115. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +8 -15
  116. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +29 -41
  117. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +1 -4
  118. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +13 -13
  119. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/selectToCQN.js +0 -7
  120. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +24 -1
  121. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/EdmEntityContainer.js +1 -1
  122. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriHelper.js +4 -3
  123. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/PrimitiveValueDecoder.js +4 -5
  124. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/ValueConverter.js +4 -3
  125. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/validator/ValueValidator.js +5 -3
  126. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/core/ResponseHeaderSetter.js +2 -0
  127. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/DebugSerializingCommand.js +1 -1
  128. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/PresetResponseHeadersCommand.js +1 -1
  129. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/SerializingCommand.js +1 -1
  130. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/SetResponseHeadersCommand.js +1 -1
  131. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ContextURLFactory.js +3 -2
  132. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ErrorJsonSerializer.js +3 -1
  133. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/SerializerFactory.js +1 -0
  134. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/TrustedResourceJsonSerializer.js +3 -3
  135. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +36 -25
  136. package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +100 -91
  137. package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +382 -0
  138. package/libx/_runtime/cds-services/adapter/odata-v4/utils/oDataConfiguration.js +1 -4
  139. package/libx/_runtime/cds-services/adapter/odata-v4/utils/omitValues.js +5 -6
  140. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +77 -21
  141. package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +3 -11
  142. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +91 -69
  143. package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +27 -6
  144. package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +7 -17
  145. package/libx/_runtime/cds-services/services/Service.js +17 -76
  146. package/libx/_runtime/cds-services/services/utils/columns.js +6 -4
  147. package/libx/_runtime/cds-services/services/utils/compareJson.js +1 -53
  148. package/libx/_runtime/cds-services/services/utils/differ.js +15 -19
  149. package/libx/_runtime/cds-services/util/assert.js +107 -34
  150. package/libx/_runtime/cds.js +1 -31
  151. package/libx/_runtime/common/aspects/Association.js +40 -54
  152. package/libx/_runtime/common/aspects/any.js +61 -6
  153. package/libx/_runtime/common/aspects/entity.js +19 -79
  154. package/libx/_runtime/common/composition/data.js +2 -2
  155. package/libx/_runtime/common/composition/delete.js +16 -18
  156. package/libx/_runtime/common/composition/tree.js +10 -10
  157. package/libx/_runtime/common/composition/update.js +3 -2
  158. package/libx/_runtime/common/constants/events.js +15 -0
  159. package/libx/_runtime/common/error/entry.js +9 -3
  160. package/libx/_runtime/common/error/frontend.js +13 -19
  161. package/libx/_runtime/common/error/index.js +8 -3
  162. package/libx/_runtime/common/generic/auth/capabilities.js +2 -1
  163. package/libx/_runtime/common/generic/auth/constants.js +1 -4
  164. package/libx/_runtime/common/generic/auth/requires.js +1 -1
  165. package/libx/_runtime/common/generic/auth/restrict.js +12 -28
  166. package/libx/_runtime/common/generic/auth/restrictions.js +12 -4
  167. package/libx/_runtime/common/generic/auth/utils.js +2 -1
  168. package/libx/_runtime/common/generic/crud.js +9 -60
  169. package/libx/_runtime/common/generic/etag.js +41 -7
  170. package/libx/_runtime/common/generic/input.js +128 -66
  171. package/libx/_runtime/common/generic/paging.js +9 -3
  172. package/libx/_runtime/common/generic/put.js +2 -2
  173. package/libx/_runtime/common/generic/sorting.js +11 -4
  174. package/libx/_runtime/common/generic/temporal.js +0 -5
  175. package/libx/_runtime/common/i18n/messages.properties +2 -1
  176. package/libx/_runtime/common/utils/binary.js +69 -0
  177. package/libx/_runtime/common/utils/cqn.js +39 -14
  178. package/libx/_runtime/common/utils/cqn2cqn4sql.js +93 -59
  179. package/libx/_runtime/common/utils/csn.js +87 -85
  180. package/libx/_runtime/common/utils/dollar.js +8 -7
  181. package/libx/_runtime/common/utils/draft.js +1 -1
  182. package/libx/_runtime/common/utils/foreignKeyPropagations.js +23 -7
  183. package/libx/_runtime/common/utils/generateOnCond.js +2 -1
  184. package/libx/_runtime/common/utils/keys.js +30 -13
  185. package/libx/_runtime/common/utils/postProcessing.js +6 -1
  186. package/libx/_runtime/common/utils/quotingStyles.js +0 -23
  187. package/libx/_runtime/common/utils/resolveStructured.js +23 -26
  188. package/libx/_runtime/common/utils/resolveView.js +4 -1
  189. package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -0
  190. package/libx/_runtime/common/utils/search2cqn4sql.js +4 -13
  191. package/libx/_runtime/common/utils/searchToLike.js +9 -13
  192. package/libx/_runtime/common/utils/streamProp.js +35 -0
  193. package/libx/_runtime/common/utils/structured.js +12 -18
  194. package/libx/_runtime/common/utils/template.js +3 -5
  195. package/libx/_runtime/common/utils/templateProcessor.js +22 -14
  196. package/libx/_runtime/common/utils/unionCqnTemplate.js +4 -14
  197. package/libx/_runtime/db/Service.js +2 -1
  198. package/libx/_runtime/db/expand/expand-v2.js +2 -2
  199. package/libx/_runtime/db/expand/expandCQNToJoin.js +7 -6
  200. package/libx/_runtime/db/generic/input.js +14 -17
  201. package/libx/_runtime/db/generic/integrity.js +1 -2
  202. package/libx/_runtime/db/generic/update.js +14 -1
  203. package/libx/_runtime/db/query/read.js +0 -1
  204. package/libx/_runtime/db/query/update.js +1 -1
  205. package/libx/_runtime/db/sql-builder/BaseBuilder.js +1 -1
  206. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +5 -31
  207. package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
  208. package/libx/_runtime/db/sql-builder/ReferenceBuilder.js +0 -9
  209. package/libx/_runtime/db/sql-builder/SelectBuilder.js +11 -10
  210. package/libx/_runtime/db/sql-builder/UpdateBuilder.js +2 -2
  211. package/libx/_runtime/db/sql-builder/annotations.js +1 -2
  212. package/libx/_runtime/db/utils/coloredTxCommands.js +5 -0
  213. package/libx/_runtime/db/utils/columns.js +1 -1
  214. package/libx/_runtime/db/utils/propagateForeignKeys.js +10 -2
  215. package/libx/_runtime/extensibility/activate.js +69 -0
  216. package/libx/_runtime/extensibility/add.js +41 -0
  217. package/libx/_runtime/extensibility/addExtension.js +68 -0
  218. package/libx/_runtime/extensibility/defaults.js +39 -0
  219. package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformREAD.js +0 -0
  220. package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformRESULT.js +2 -2
  221. package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformWRITE.js +2 -2
  222. package/libx/_runtime/extensibility/push.js +61 -0
  223. package/libx/_runtime/extensibility/service.js +21 -0
  224. package/libx/_runtime/extensibility/{uiflex/utils.js → utils.js} +39 -3
  225. package/libx/_runtime/extensibility/validation.js +53 -0
  226. package/libx/_runtime/extensibility/views.js +12 -0
  227. package/libx/_runtime/fiori/generic/activate.js +6 -4
  228. package/libx/_runtime/fiori/generic/before.js +17 -29
  229. package/libx/_runtime/fiori/generic/cancel.js +2 -4
  230. package/libx/_runtime/fiori/generic/delete.js +2 -4
  231. package/libx/_runtime/fiori/generic/edit.js +3 -7
  232. package/libx/_runtime/fiori/generic/index.js +31 -0
  233. package/libx/_runtime/fiori/generic/new.js +2 -4
  234. package/libx/_runtime/fiori/generic/patch.js +4 -8
  235. package/libx/_runtime/fiori/generic/prepare.js +2 -4
  236. package/libx/_runtime/fiori/generic/read.js +137 -162
  237. package/libx/_runtime/fiori/generic/readOverDraft.js +10 -4
  238. package/libx/_runtime/fiori/utils/handler.js +10 -5
  239. package/libx/_runtime/fiori/utils/where.js +1 -4
  240. package/libx/_runtime/hana/Service.js +14 -7
  241. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +1 -1
  242. package/libx/_runtime/hana/dynatrace.js +2 -2
  243. package/libx/_runtime/hana/localized.js +7 -6
  244. package/libx/_runtime/hana/pool.js +9 -6
  245. package/libx/_runtime/hana/search.js +2 -3
  246. package/libx/_runtime/hana/{searchToContains.js → search2Contains.js} +5 -2
  247. package/libx/_runtime/hana/search2cqn4sql.js +20 -17
  248. package/libx/_runtime/index.js +2 -6
  249. package/libx/_runtime/messaging/AMQPWebhookMessaging.js +11 -2
  250. package/libx/_runtime/messaging/common-utils/AMQPClient.js +4 -3
  251. package/libx/_runtime/messaging/common-utils/appId.js +9 -0
  252. package/libx/_runtime/messaging/common-utils/authorizedRequest.js +2 -18
  253. package/libx/_runtime/messaging/common-utils/connections.js +1 -1
  254. package/libx/_runtime/messaging/enterprise-messaging-shared.js +2 -2
  255. package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +305 -231
  256. package/libx/_runtime/messaging/enterprise-messaging-utils/cloudEvents.js +2 -2
  257. package/libx/_runtime/messaging/enterprise-messaging-utils/options-management.js +15 -8
  258. package/libx/_runtime/messaging/enterprise-messaging-utils/options-messaging.js +57 -14
  259. package/libx/_runtime/messaging/enterprise-messaging.js +14 -19
  260. package/libx/_runtime/messaging/file-based.js +2 -1
  261. package/libx/_runtime/messaging/http-utils/token.js +18 -6
  262. package/libx/_runtime/messaging/message-queuing-utils/options-management.js +22 -12
  263. package/libx/_runtime/messaging/message-queuing-utils/options-messaging.js +27 -14
  264. package/libx/_runtime/messaging/message-queuing.js +138 -85
  265. package/libx/_runtime/messaging/outbox/utils.js +13 -7
  266. package/libx/_runtime/messaging/redis-messaging.js +0 -1
  267. package/libx/_runtime/messaging/service.js +4 -1
  268. package/libx/_runtime/remote/Service.js +24 -18
  269. package/libx/_runtime/remote/utils/client.js +84 -46
  270. package/libx/_runtime/remote/utils/data.js +23 -6
  271. package/libx/_runtime/sqlite/Service.js +14 -13
  272. package/libx/_runtime/sqlite/convertAssocToOneManaged.js +2 -0
  273. package/libx/_runtime/sqlite/customBuilder/CustomSelectBuilder.js +1 -0
  274. package/libx/_runtime/sqlite/execute.js +3 -9
  275. package/libx/_runtime/types/api.js +23 -11
  276. package/libx/common/utils/ucsn.js +15 -9
  277. package/libx/odata/afterburner.js +109 -29
  278. package/libx/odata/cqn2odata.js +48 -9
  279. package/libx/odata/grammar.pegjs +261 -157
  280. package/libx/odata/index.js +21 -9
  281. package/libx/odata/parseToCqn.js +8 -5
  282. package/libx/odata/parser.js +1 -1
  283. package/libx/odata/utils.js +13 -3
  284. package/libx/rest/RestAdapter.js +173 -113
  285. package/libx/rest/RestRequest.js +3 -2
  286. package/libx/rest/middleware/create.js +8 -6
  287. package/libx/rest/middleware/delete.js +6 -13
  288. package/libx/rest/middleware/error.js +1 -1
  289. package/libx/rest/middleware/input.js +6 -6
  290. package/libx/rest/middleware/operation.js +8 -3
  291. package/libx/rest/middleware/parse.js +3 -3
  292. package/libx/rest/middleware/payload.js +12 -0
  293. package/libx/rest/middleware/read.js +12 -2
  294. package/libx/rest/middleware/update.js +3 -3
  295. package/package.json +4 -6
  296. package/server.js +3 -44
  297. package/srv/extensibility-service.cds +56 -0
  298. package/srv/extensibility-service.js +1 -0
  299. package/srv/extensions.cds +8 -0
  300. package/srv/model-provider.cds +59 -0
  301. package/srv/model-provider.js +163 -0
  302. package/srv/mtx.cds +2 -0
  303. package/srv/mtx.js +22 -0
  304. package/srv/outbox.cds +2 -0
  305. package/tasks/enterprise-messaging-deploy.js +19 -12
  306. package/lib/serve/Service-compat.js +0 -36
  307. package/libx/_runtime/audit/generic/personal/constants.js +0 -4
  308. package/libx/_runtime/auth/strategies/dwc.js +0 -45
  309. package/libx/_runtime/cds-services/adapter/odata-v4/utils/dispatcherUtils.js +0 -56
  310. package/libx/_runtime/cds-services/adapter/rest/Rest.js +0 -183
  311. package/libx/_runtime/cds-services/adapter/rest/RestRequest.js +0 -67
  312. package/libx/_runtime/cds-services/adapter/rest/handlers/create.js +0 -82
  313. package/libx/_runtime/cds-services/adapter/rest/handlers/delete.js +0 -39
  314. package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +0 -63
  315. package/libx/_runtime/cds-services/adapter/rest/handlers/read.js +0 -52
  316. package/libx/_runtime/cds-services/adapter/rest/handlers/update.js +0 -81
  317. package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +0 -56
  318. package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/utils.js +0 -33
  319. package/libx/_runtime/cds-services/adapter/rest/to.js +0 -8
  320. package/libx/_runtime/cds-services/adapter/rest/utils/binary.js +0 -50
  321. package/libx/_runtime/cds-services/adapter/rest/utils/data.js +0 -117
  322. package/libx/_runtime/cds-services/adapter/rest/utils/header-checks.js +0 -14
  323. package/libx/_runtime/cds-services/adapter/rest/utils/key-value-utils.js +0 -30
  324. package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +0 -250
  325. package/libx/_runtime/cds-services/adapter/rest/utils/result.js +0 -26
  326. package/libx/_runtime/cds-services/services/utils/handlerUtils.js +0 -200
  327. package/libx/_runtime/common/aspects/utils.js +0 -152
  328. package/libx/_runtime/common/toggles/handler.js +0 -21
  329. package/libx/_runtime/common/utils/extensibilityUtils.js +0 -18
  330. package/libx/_runtime/extensibility/mps/index.js +0 -5
  331. package/libx/_runtime/extensibility/mps/service.js +0 -111
  332. package/libx/_runtime/extensibility/mps/tar.js +0 -42
  333. package/libx/_runtime/extensibility/mps/utils.js +0 -11
  334. package/libx/_runtime/extensibility/uiflex/index.js +0 -54
  335. package/libx/_runtime/extensibility/uiflex/service.js +0 -276
  336. package/libx/_runtime/messaging/common-utils/naming-conventions.js +0 -20
  337. package/libx/_runtime/remote/utils/client-types.d.ts +0 -7
  338. package/libx/gql/GraphQLAdapter.js +0 -33
  339. package/libx/gql/constants/adapter.js +0 -69
  340. package/libx/gql/constants/cds.js +0 -18
  341. package/libx/gql/constants/graphql.js +0 -33
  342. package/libx/gql/readme.md +0 -1
  343. package/libx/gql/resolvers/crud/create.js +0 -20
  344. package/libx/gql/resolvers/crud/delete.js +0 -29
  345. package/libx/gql/resolvers/crud/index.js +0 -6
  346. package/libx/gql/resolvers/crud/read.js +0 -30
  347. package/libx/gql/resolvers/crud/update.js +0 -42
  348. package/libx/gql/resolvers/crud/utils/index.js +0 -36
  349. package/libx/gql/resolvers/field.js +0 -5
  350. package/libx/gql/resolvers/index.js +0 -7
  351. package/libx/gql/resolvers/mutation.js +0 -23
  352. package/libx/gql/resolvers/parse/ast/enrich.js +0 -52
  353. package/libx/gql/resolvers/parse/ast/fragment.js +0 -11
  354. package/libx/gql/resolvers/parse/ast/fromObject.js +0 -39
  355. package/libx/gql/resolvers/parse/ast/index.js +0 -3
  356. package/libx/gql/resolvers/parse/ast/meta.js +0 -4
  357. package/libx/gql/resolvers/parse/ast/variable.js +0 -7
  358. package/libx/gql/resolvers/parse/ast2cqn/columns.js +0 -44
  359. package/libx/gql/resolvers/parse/ast2cqn/entries.js +0 -31
  360. package/libx/gql/resolvers/parse/ast2cqn/index.js +0 -8
  361. package/libx/gql/resolvers/parse/ast2cqn/limit.js +0 -6
  362. package/libx/gql/resolvers/parse/ast2cqn/orderBy.js +0 -24
  363. package/libx/gql/resolvers/parse/ast2cqn/utils/index.js +0 -3
  364. package/libx/gql/resolvers/parse/ast2cqn/where.js +0 -70
  365. package/libx/gql/resolvers/parse/utils/index.js +0 -8
  366. package/libx/gql/resolvers/query.js +0 -13
  367. package/libx/gql/resolvers/root.js +0 -34
  368. package/libx/gql/schema/generate.js +0 -18
  369. package/libx/gql/schema/index.js +0 -5
  370. package/libx/gql/schema/mutation.js +0 -76
  371. package/libx/gql/schema/query.js +0 -108
  372. package/libx/gql/schema/typeDefMap.js +0 -45
  373. package/libx/gql/schema/utils/index.js +0 -54
  374. package/libx/gql/utils/index.js +0 -12
  375. package/libx/rest/middleware/auth.js +0 -20
  376. package/libx/rest/middleware/content.js +0 -19
  377. package/srv/flex.cds +0 -21
  378. package/srv/flex.js +0 -1
  379. package/srv/mps.cds +0 -23
  380. package/srv/mps.js +0 -1
  381. package/srv/outbox.js +0 -0
@@ -7,7 +7,7 @@ const ANONYMOUS = 'anonymous'
7
7
 
8
8
  const _getTenantAndUser = () => ({
9
9
  user: (cds.context && cds.context.user && cds.context.user.id) || ANONYMOUS,
10
- tenant: (cds.context && cds.context.tenant) || ANONYMOUS
10
+ tenant: cds.context && cds.context.tenant
11
11
  })
12
12
 
13
13
  module.exports = class AuditLogService extends OutboxService {
@@ -117,7 +117,7 @@ module.exports = class AuditLogService extends OutboxService {
117
117
  let { tenant, user } = _getTenantAndUser()
118
118
 
119
119
  // cds.context may not be proper on auth-related errors -> try to extract from data
120
- if (tenant === ANONYMOUS && user === ANONYMOUS) {
120
+ if (!tenant && user === ANONYMOUS) {
121
121
  try {
122
122
  const parsed = JSON.parse(data)
123
123
  if (parsed.tenant) {
@@ -129,7 +129,9 @@ module.exports = class AuditLogService extends OutboxService {
129
129
  delete parsed.user
130
130
  }
131
131
  data = JSON.stringify(parsed)
132
- } catch (e) {}
132
+ } catch (e) {
133
+ // ignore
134
+ }
133
135
  }
134
136
 
135
137
  // build the log
@@ -140,7 +142,7 @@ module.exports = class AuditLogService extends OutboxService {
140
142
  }
141
143
 
142
144
  // REVISIT: action and success not used in auditlog v2
143
- async _configChangeLog({ data: { action, success, configurations } }) {
145
+ async _configChangeLog({ data: { configurations } }) {
144
146
  const { tenant, user } = _getTenantAndUser()
145
147
 
146
148
  // build the logs
@@ -13,8 +13,6 @@ const {
13
13
  resolveDataSubjectPromises
14
14
  } = require('./utils')
15
15
 
16
- let auditLogService
17
-
18
16
  const _processorFnAccess = (accessLogs, model, req) => {
19
17
  return ({ row, key, element, plain }) => {
20
18
  if (row.IsActiveEntity === false) return
@@ -22,64 +20,42 @@ const _processorFnAccess = (accessLogs, model, req) => {
22
20
  const entity = getRootEntity(element)
23
21
 
24
22
  // create or augment log entry
25
- const accessLog = createLogEntry(accessLogs, entity, row)
23
+ const entry = createLogEntry(accessLogs, entity, row)
26
24
 
27
25
  // process categories
28
26
  for (const category of plain.categories) {
29
- if (category === 'ObjectID') {
30
- addObjectID(accessLog, row, key)
31
- } else if (category === 'DataSubjectID') {
32
- addDataSubject(accessLog, row, key, entity)
33
- } else if (category === 'IsPotentiallySensitive' && key in row) {
34
- // add attribute
35
- if (!accessLog.attributes.find(ele => ele.name === key)) accessLog.attributes.push({ name: key })
27
+ if (category === 'ObjectID') addObjectID(entry, row, key)
28
+ else if (category === 'DataSubjectID') addDataSubject(entry, row, key, entity)
29
+ else if (category === 'IsPotentiallySensitive' && key in row) {
30
+ if (!entry.attributes.some(e => e.name === key)) entry.attributes.push({ name: key })
36
31
  // REVISIT: attribute vs. attachment?
37
32
  }
38
33
  }
39
34
 
40
35
  // add promise to determine data subject if a DataSubjectDetails entity
36
+ const semantics = entity['@PersonalData.EntitySemantics']
41
37
  if (
42
- (entity['@PersonalData.EntitySemantics'] === 'DataSubjectDetails' ||
43
- entity['@PersonalData.EntitySemantics'] === 'Other') &&
44
- accessLog.dataSubject.id.length === 0 // > id still an array -> promise not yet set
38
+ (semantics === 'DataSubjectDetails' || semantics === 'Other') &&
39
+ entry.dataSubject.id.length === 0 // > id still an array -> promise not yet set
45
40
  ) {
46
- addDataSubjectForDetailsEntity(row, accessLog, req, entity, model)
41
+ addDataSubjectForDetailsEntity(row, entry, req, entity, model)
47
42
  }
48
43
  }
49
44
  }
50
45
 
51
- const _getDataAccessLogs = (data, req, tx) => {
52
- const template = getTemplate(
53
- 'personal_read',
54
- Object.assign({ name: req.target._service.name, model: tx.model }),
55
- req.target,
56
- { pick: getPick('READ') }
57
- )
58
-
46
+ const auditAccessHandler = async function (data, req) {
47
+ const auditLogService = await cds.connect.to('audit-log')
48
+ const mock = Object.assign({ name: req.target._service.name, model: this.model })
49
+ const template = getTemplate('personal_read', mock, req.target, { pick: getPick('READ') })
50
+ if (!template.elements.size) return
59
51
  const accessLogs = {}
60
-
61
52
  if (typeof data === 'object' && data !== null) {
62
- const processFn = _processorFnAccess(accessLogs, tx.model, req)
53
+ const processFn = _processorFnAccess(accessLogs, this.model, req)
63
54
  const data_ = Array.isArray(data) ? data : [data]
64
- data_.forEach(row => {
65
- templateProcessor({ processFn, row, template })
66
- })
55
+ data_.forEach(row => templateProcessor({ processFn, row, template }))
56
+ const accesses = (await resolveDataSubjectPromises(accessLogs)).filter(ele => ele.attributes.length)
57
+ if (accesses.length) await auditLogService.emit('dataAccessLog', { accesses })
67
58
  }
68
-
69
- return accessLogs
70
59
  }
71
60
 
72
- const auditAccessHandler = async function (data, req) {
73
- auditLogService = auditLogService || (await cds.connect.to('audit-log'))
74
-
75
- const accessLogs = _getDataAccessLogs(data, req, this)
76
- // REVISIT: a function called resolveDataSubjectPromises should not also convert an object to an array
77
- let accesses = await resolveDataSubjectPromises(accessLogs)
78
- accesses = accesses.filter(ele => ele.attributes.length)
79
-
80
- if (accesses.length) await auditLogService.emit('dataAccessLog', { accesses })
81
- }
82
-
83
- module.exports = {
84
- auditAccessHandler
85
- }
61
+ module.exports = { auditAccessHandler }
@@ -1,5 +1,4 @@
1
1
  const cds = require('../../../cds')
2
-
3
2
  const {
4
3
  attachDiffToContextHandler,
5
4
  calcModificationLogsHandler4Before,
@@ -8,43 +7,50 @@ const {
8
7
  } = require('./modification')
9
8
  const { auditAccessHandler } = require('./access')
10
9
 
11
- module.exports = function () {
12
- /*
13
- * prep context
14
- */
15
- this.before('*', req => (req.context._audit = req.context._audit || {}))
16
-
17
- /*
18
- * data modification
19
- */
10
+ exports.impl = cds.service.impl(function () {
11
+ if (!cds.db) return cds.on('connect', srv => srv instanceof cds.DatabaseService && exports.impl.call(this))
20
12
  // REVISIT: diff() doesn't work in srv after phase but foreign key propagation has not yet taken place in srv before phase
21
13
  // -> calc diff in db layer and store in audit data structure at context
22
14
  // -> REVISIT for GA: clear req._.partialPersistentState?
23
15
  attachDiffToContextHandler._initial = true
24
- for (const entity of Object.values(this.entities).filter(e => e._auditCreate)) {
25
- cds.db.before('CREATE', entity, attachDiffToContextHandler)
26
- // create -> all new -> calcModificationLogsHandler in after phase
27
- cds.db.after('CREATE', entity, calcModificationLogsHandler4After)
28
- this.after('CREATE', entity, emitModificationHandler)
29
- }
30
- for (const entity of Object.values(this.entities).filter(e => e._auditUpdate)) {
31
- cds.db.before('UPDATE', entity, attachDiffToContextHandler)
32
- // update -> mixed (via deep) -> calcModificationLogsHandler in before and after phase
33
- cds.db.before('UPDATE', entity, calcModificationLogsHandler4Before)
34
- cds.db.after('UPDATE', entity, calcModificationLogsHandler4After)
35
- this.after('UPDATE', entity, emitModificationHandler)
36
- }
37
- for (const entity of Object.values(this.entities).filter(e => e._auditDelete)) {
38
- cds.db.before('DELETE', entity, attachDiffToContextHandler)
39
- // delete -> all done -> calcModificationLogsHandler in before phase
40
- cds.db.before('DELETE', entity, calcModificationLogsHandler4Before)
41
- this.after('DELETE', entity, emitModificationHandler)
42
- }
16
+ for (const e of this.entities) {
17
+ if (!_hasPersonalData(e)) continue
43
18
 
44
- /*
45
- * data access
46
- */
47
- for (const entity of Object.values(this.entities).filter(e => e._auditRead)) {
48
- this.after('READ', entity, auditAccessHandler)
19
+ if (e['@AuditLog.Operation.Insert']) {
20
+ cds.db.before('CREATE', e, attachDiffToContextHandler)
21
+ // create -> all new -> calcModificationLogsHandler in after phase
22
+ cds.db.after('CREATE', e, calcModificationLogsHandler4After)
23
+ this.after('CREATE', e, emitModificationHandler)
24
+ }
25
+
26
+ if (e['@AuditLog.Operation.Update']) {
27
+ cds.db.before('UPDATE', e, attachDiffToContextHandler)
28
+ // update -> mixed (via deep) -> calcModificationLogsHandler in before and after phase
29
+ cds.db.before('UPDATE', e, calcModificationLogsHandler4Before)
30
+ cds.db.after('UPDATE', e, calcModificationLogsHandler4After)
31
+ this.after('UPDATE', e, emitModificationHandler)
32
+ }
33
+
34
+ if (e['@AuditLog.Operation.Delete']) {
35
+ cds.db.before('DELETE', e, attachDiffToContextHandler)
36
+ // delete -> all done -> calcModificationLogsHandler in before phase
37
+ cds.db.before('DELETE', e, calcModificationLogsHandler4Before)
38
+ this.after('DELETE', e, emitModificationHandler)
39
+ }
40
+
41
+ if (e['@AuditLog.Operation.Read']) {
42
+ this.after('READ', e, auditAccessHandler)
43
+ }
49
44
  }
45
+ })
46
+
47
+ const _hasPersonalData = e => {
48
+ if (!e['@PersonalData.DataSubjectRole']) return
49
+ if (!e['@PersonalData.EntitySemantics']) return
50
+ return !!Object.values(e.elements).some(
51
+ e =>
52
+ e['@PersonalData.IsPotentiallyPersonal'] ||
53
+ e['@PersonalData.IsPotentiallySensitive'] ||
54
+ (e['@PersonalData.FieldSemantics'] && e['@PersonalData.FieldSemantics'] === 'DataSubjectID')
55
+ )
50
56
  }
@@ -18,8 +18,9 @@ let auditLogService
18
18
 
19
19
  const attachDiffToContextHandler = async function (req) {
20
20
  // store diff in audit data structure at context
21
- if (!req.context._audit.diffs) req.context._audit.diffs = new Map()
22
- req.context._audit.diffs.set(req._.query, await req.diff())
21
+ const _audit = req.context._audit || (req.context._audit = {})
22
+ if (!_audit.diffs) _audit.diffs = new Map()
23
+ _audit.diffs.set(req._.query, await req.diff())
23
24
  }
24
25
 
25
26
  const _getOldAndNew = (action, row, key) => {
@@ -38,10 +39,10 @@ const _addAttribute = (log, action, row, key) => {
38
39
  }
39
40
  }
40
41
 
41
- const _processorFnModification = (modificationLogs, model, req, beforeWrite) => processArgs => {
42
- if (!processArgs.row._op) return
42
+ const _processorFnModification = (modificationLogs, model, req, beforeWrite) => elementInfo => {
43
+ if (!elementInfo.row._op) return
43
44
 
44
- const { row, key, element, plain } = processArgs
45
+ const { row, key, element, plain } = elementInfo
45
46
 
46
47
  // delete in before phase, create and update in after phase
47
48
  if ((row._op === 'delete') !== !!beforeWrite) return
@@ -91,12 +92,13 @@ const _getDataModificationLogs = (req, tx, diff, beforeWrite) => {
91
92
  const _calcModificationLogsHandler = async function (req, beforeWrite, that) {
92
93
  const mapKey = getMapKeyForCurrentRequest(req)
93
94
 
94
- const modificationLogs = _getDataModificationLogs(req, that, req.context._audit.diffs.get(mapKey), beforeWrite)
95
+ const _audit = req.context._audit || (req.context._audit = {})
96
+ const modificationLogs = _getDataModificationLogs(req, that, _audit.diffs.get(mapKey), beforeWrite)
95
97
 
96
98
  // store modificationLogs in audit data structure at context
97
- if (!req.context._audit.modificationLogs) req.context._audit.modificationLogs = new Map()
98
- const existingLogs = req.context._audit.modificationLogs.get(mapKey) || {}
99
- req.context._audit.modificationLogs.set(mapKey, Object.assign(existingLogs, modificationLogs))
99
+ if (!_audit.modificationLogs) _audit.modificationLogs = new Map()
100
+ const existingLogs = _audit.modificationLogs.get(mapKey) || {}
101
+ _audit.modificationLogs.set(mapKey, Object.assign(existingLogs, modificationLogs))
100
102
 
101
103
  // execute the data subject promises before going along to on phase
102
104
  // guarantees that the reads are executed before the data is modified
@@ -3,11 +3,11 @@ const cds = require('../../../cds')
3
3
  const { getDataSubject } = require('../../../common/utils/csn')
4
4
 
5
5
  const WRITE = { CREATE: 1, UPDATE: 1, DELETE: 1 }
6
- const ASPECTS = { CREATE: '_auditCreate', READ: '_auditRead', UPDATE: '_auditUpdate', DELETE: '_auditDelete' }
7
6
 
8
7
  const getMapKeyForCurrentRequest = req => {
9
8
  // running in srv or db layer? -> srv's req.query used as key of diff and logs maps at req.context
10
- return req._tx instanceof cds.DatabaseService ? req._.query : req.query
9
+ // REVISIT: req._tx should not be used like that!
10
+ return req.tx instanceof cds.DatabaseService ? req._.query : req.query
11
11
  }
12
12
 
13
13
  const getRootEntity = element => {
@@ -18,7 +18,13 @@ const getRootEntity = element => {
18
18
 
19
19
  const getPick = event => {
20
20
  return (element, target) => {
21
- if (!target[ASPECTS[event]]) return
21
+ const annotation = {
22
+ CREATE: '@AuditLog.Operation.Insert',
23
+ UPDATE: '@AuditLog.Operation.Update',
24
+ DELETE: '@AuditLog.Operation.Delete',
25
+ READ: '@AuditLog.Operation.Read'
26
+ }[event]
27
+ if (!annotation || !target[annotation]) return
22
28
  const categories = []
23
29
  if (!element.isAssociation && element.key) categories.push('ObjectID')
24
30
  if (
@@ -125,9 +131,10 @@ const addDataSubjectForDetailsEntity = (row, log, req, entity, model) => {
125
131
  * store (in audit data structure at context) and reuse a single promise to look up the respective data subject
126
132
  */
127
133
  const mapKey = getMapKeyForCurrentRequest(req)
128
- if (!req.context._audit.dataSubjects) req.context._audit.dataSubjects = new Map()
129
- if (!req.context._audit.dataSubjects.has(mapKey)) req.context._audit.dataSubjects.set(mapKey, new Map())
130
- const map = req.context._audit.dataSubjects.get(mapKey)
134
+ const _audit = req.context._audit || (req.context._audit = {})
135
+ if (!_audit.dataSubjects) _audit.dataSubjects = new Map()
136
+ if (!_audit.dataSubjects.has(mapKey)) _audit.dataSubjects.set(mapKey, new Map())
137
+ const map = _audit.dataSubjects.get(mapKey)
131
138
  if (map.has(role)) log.dataSubject.id = map.get(role)
132
139
  // REVISIT by downward lookups row might already contain ID - some potential to optimize
133
140
  else map.set(role, _getDataSubjectIdPromise(dataSubjectInfo, row, req, model))
@@ -97,7 +97,8 @@ function buildDataAccessLogs(alc, accesses, tenant, user) {
97
97
  for (const access of accesses) {
98
98
  try {
99
99
  const { dataObject, dataSubject } = getObjectAndDataSubject(access)
100
- const entry = alc.read(dataObject).dataSubject(dataSubject).tenant(tenant).by(user)
100
+ const entry = alc.read(dataObject).dataSubject(dataSubject).by(user)
101
+ if (tenant) entry.tenant(tenant)
101
102
  for (const each of access.attributes) entry.attribute(each)
102
103
  for (const each of access.attachments) entry.attachment(each)
103
104
  entries.push(entry)
@@ -117,7 +118,8 @@ function buildDataModificationLogs(alc, modifications, tenant, user) {
117
118
  for (const modification of modifications) {
118
119
  try {
119
120
  const { dataObject, dataSubject } = getObjectAndDataSubject(modification)
120
- const entry = alc.update(dataObject).dataSubject(dataSubject).tenant(tenant).by(user)
121
+ const entry = alc.update(dataObject).dataSubject(dataSubject).by(user)
122
+ if (tenant) entry.tenant(tenant)
121
123
  for (const each of modification.attributes) entry.attribute(getAttributeToLog(each))
122
124
  entries.push(entry)
123
125
  } catch (err) {
@@ -151,7 +153,8 @@ function buildConfigChangeLogs(alc, configurations, tenant, user) {
151
153
  for (const configuration of configurations) {
152
154
  try {
153
155
  const { dataObject } = getObjectAndDataSubject(configuration)
154
- const entry = alc.configurationChange(dataObject).tenant(tenant).by(user)
156
+ const entry = alc.configurationChange(dataObject).by(user)
157
+ if (tenant) entry.tenant(tenant)
155
158
  for (const each of configuration.attributes) entry.attribute(getAttributeToLog(each))
156
159
  entries.push(entry)
157
160
  } catch (err) {
@@ -2,7 +2,7 @@ const cds = require('../cds')
2
2
  const LOG = cds.log()
3
3
 
4
4
  const _require = require('../common/utils/require')
5
- const { UNAUTHORIZED, isRestricted } = require('./utils')
5
+ const { UNAUTHORIZED, FORBIDDEN, isRestricted } = require('./utils')
6
6
 
7
7
  let passport, logged
8
8
 
@@ -17,10 +17,6 @@ const _initializers = {
17
17
  const DummyStrategy = require('./strategies/dummy')
18
18
  passport.use(new DummyStrategy())
19
19
  },
20
- dwc: () => {
21
- const DwcStrategy = require('./strategies/dwc')
22
- passport.use(new DwcStrategy())
23
- },
24
20
  jwt: ({ credentials, uaa }) => {
25
21
  const JWTStrategy = require('./strategies/JWT')
26
22
  if (credentials) {
@@ -85,11 +81,16 @@ const _authCallback = (req, res, next, internalError, user, challenges) => {
85
81
  next()
86
82
  }
87
83
 
84
+ const _mountCustomAuth = (srv, app, config) => {
85
+ const impl = cds.resolve(config.impl)
86
+ app.use(srv.path, _require(impl))
87
+ }
88
+
88
89
  const _mountMockAuth = (srv, app, strategy, config) => {
89
90
  const impl =
90
91
  strategy === 'dummy'
91
92
  ? new (require('./strategies/dummy'))()
92
- : new (require('./strategies/mock'))(config.users, `mock_${srv.name}`)
93
+ : new (require('./strategies/mock'))(config, `mock_${srv.name}`)
93
94
 
94
95
  app.use(srv.path, (req, res, next) => {
95
96
  let user, challenge
@@ -101,10 +102,18 @@ const _mountMockAuth = (srv, app, strategy, config) => {
101
102
  }
102
103
 
103
104
  const _mountPassportAuth = (srv, app, strategy, config) => {
104
- passport = passport || _require('passport')
105
+ if (!config.credentials)
106
+ return (
107
+ LOG._warn &&
108
+ LOG.warn(`
109
+ No XSUAA instance bound to application, but "${config.strategy}" configured.
110
+ This is NOT recommended in production!
111
+ `)
112
+ )
113
+ if (!passport) passport = _require('passport')
105
114
 
106
115
  // initialize strategy
107
- if (!_authenticators[strategy] || strategy === 'mock' || process.env.NODE_ENV === 'test') {
116
+ if (!_authenticators[strategy] || process.env.NODE_ENV === 'test') {
108
117
  _initializers[strategy](config, srv.name)
109
118
  _authenticators[strategy] = true
110
119
  }
@@ -125,78 +134,74 @@ const _mountPassportAuth = (srv, app, strategy, config) => {
125
134
  module.exports = (srv, app, options) => {
126
135
  // NOTE: options.auth is not an official API
127
136
  let config = 'auth' in options ? options.auth : cds.env.requires.auth
128
-
129
- // cds.env.requires.auth = { kind: 'xsuaa-auth' } was briefly documented on capire -> also support
130
- if (config && config.kind === 'xsuaa-auth' && !config.credentials) config = cds.env.requires.xsuaa
131
-
132
- // mount custom authentication middleware
133
- if (config && config.impl) {
134
- app.use(srv.path, _require(cds.resolve(config.impl)))
135
- return
136
- }
137
-
138
- const restricted = isRestricted(srv)
139
- if (restricted && !config) {
140
- // REVISIT: why exitCode needed?
141
- process.exitCode = 1
142
- throw new Error('Authentication required for authorization checks')
143
- }
144
-
145
- const isMultiTenant = cds.env.requires.db && cds.env.requires.db.multiTenant
146
- if (isMultiTenant && !config) {
147
- // REVISIT: why exitCode needed?
148
- process.exitCode = 1
149
- throw new Error('Authentication required for multitenancy')
150
- }
151
-
152
137
  if (!config) {
153
- if (!logged) {
154
- const msg = 'No authentication configured'
155
- if (process.env.NODE_ENV !== 'production') LOG._debug && LOG.debug(msg)
156
- else LOG._info && LOG.info(`${msg}. This is not recommended in production.`)
138
+ if (cds.requires.db && cds.requires.multitenancy) {
139
+ process.exitCode = 1 // REVISIT: why exitCode needed?
140
+ throw new Error('Authentication required for multitenancy')
141
+ }
142
+ if (isRestricted(srv)) {
143
+ process.exitCode = 1 // REVISIT: why exitCode needed?
144
+ throw new Error('Authentication required for authorization checks')
145
+ }
146
+ if (process.env.NODE_ENV !== 'production' && !logged) {
147
+ LOG._warn && LOG.warn(`No authentication configured. This is not recommended in production.`)
157
148
  }
158
-
159
149
  // no auth wanted > return
160
150
  return
161
151
  }
162
152
 
163
- // strategy from kind
164
- let strategy
165
- // compat for auth.strategy
166
- if (config.strategy) {
167
- strategy = config.strategy.toLowerCase()
168
- }
169
- strategy = strategy || config.kind.replace('-auth', '').toLowerCase()
170
- if (strategy === 'mocked') strategy = 'mock'
153
+ // cds.env.requires.auth = { kind: 'xsuaa-auth' } was briefly documented on capire -> also support
154
+ if (config.kind === 'xsuaa-auth' && !config.credentials) config = cds.env.requires.xsuaa
171
155
 
172
- if (!_initializers[strategy]) {
173
- // REVISIT: why exitCode needed?
174
- process.exitCode = 1
175
- throw new Error(`Authentication kind "${config.kind}" is not supported`)
176
- }
156
+ // mount authentication middleware or strategy
157
+ if (!logged) LOG._debug && LOG.debug(`Using authentication`, { kind: config.kind })
177
158
 
178
- if (!logged) LOG._debug && LOG.debug(`Using authentication kind "${config.kind}"`)
159
+ // Security by default: set restrict_all_services if not disabled
160
+ // this is done dynamically to also cover custom auth impl
161
+ if (process.env.NODE_ENV === 'production' && config.restrict_all_services !== false) {
162
+ config.restrict_all_services = true
163
+ }
179
164
 
180
- if (strategy in { dummy: 1, mock: 1 }) {
181
- // > dummy or mock authentication (for development/testing)
182
- _mountMockAuth(srv, app, strategy, config)
165
+ if (config.impl) {
166
+ // mount custom authentication middleware
167
+ _mountCustomAuth(srv, app, config)
183
168
  } else {
184
- // if no restriction and no binding, don't mount passport middleware
185
- if (!restricted && !config.credentials) {
186
- if (!logged) {
187
- const msg = `Service ${srv.name} is unrestricted`
188
- if (process.env.NODE_ENV !== 'production') LOG._debug && LOG.debug(msg)
189
- else LOG._info && LOG.info(`${msg}. This is not recommended in production.`)
190
- }
191
-
192
- // no auth wanted > return
193
- return
169
+ // mount our authentication strategies (legacy style)
170
+ const strategy = _strategy4(config)
171
+ if (strategy in { dummy: 1, mock: 1 }) {
172
+ _mountMockAuth(srv, app, strategy, config)
173
+ } else {
174
+ _mountPassportAuth(srv, app, strategy, config)
194
175
  }
176
+ }
195
177
 
196
- // > passport authentication
197
- _mountPassportAuth(srv, app, strategy, config)
178
+ // Security by default: enforce authenticated users in production if auth service bound
179
+ if (
180
+ cds.requires.multitenancy ||
181
+ (process.env.NODE_ENV === 'production' && config.credentials && config.restrict_all_services)
182
+ ) {
183
+ if (!logged) LOG._debug && LOG.debug(`Enforcing authenticated users for all services`)
184
+ app.use(srv.path, _enforce_authenticated_user)
198
185
  }
199
186
 
200
187
  // so we don't log the same stuff multiple times
201
188
  logged = true
202
189
  }
190
+
191
+ const _strategy4 = config => {
192
+ const strategy = config.strategy ? config.strategy.toLowerCase() : config.kind.replace('-auth', '')
193
+ if (strategy === 'mocked') return 'mock'
194
+ if (strategy in _initializers) return strategy
195
+ process.exitCode = 1 // REVISIT: why exitCode needed?
196
+ throw new Error(`Authentication kind "${config.kind}" is not supported`)
197
+ }
198
+
199
+ const _enforce_authenticated_user = (req, res, next) => {
200
+ if (req.user && req.user.is('authenticated-user')) return next() // pass if user is authenticated
201
+ if (!req.user || req.user._is_anonymous) {
202
+ if (req.user && req.user._challenges) res.set('WWW-Authenticate', req.user._challenges.join(';'))
203
+ return res.status(401).json(UNAUTHORIZED) // no details to client // REVISIT: security log in else case?
204
+ } else {
205
+ return res.status(403).json(FORBIDDEN) // no details to client // REVISIT: security log?
206
+ }
207
+ }
@@ -21,10 +21,11 @@ class JWTStrategy extends JS {
21
21
  // create cds.User
22
22
  user = new cds.User({
23
23
  id: xssecUtils.getUserId(user, info),
24
- tenant: xssecUtils.getTenant(info) || null,
25
- _roles: xssecUtils.getRoles(['any', 'identified-user'], info, credentials),
24
+ roles: xssecUtils.getRoles(['any', 'identified-user'], info, credentials),
26
25
  attr: xssecUtils.getAttrForJWT(info)
27
26
  })
27
+ const tenant = xssecUtils.getTenant(info)
28
+ if (tenant) user.tenant = tenant
28
29
  // call "super.success"
29
30
  _success(user, info)
30
31
  }