@sap/cds 7.7.0 → 7.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@
4
4
  - The format is based on [Keep a Changelog](http://keepachangelog.com/).
5
5
  - This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## Version 7.7.1 - 2024-03-06
8
+
9
+ ### Fixed
10
+
11
+ - JWT authentication for Event Mesh endpoints
12
+ - `cds.log`'s json formatter: ensure `type` is set (required on kubernetes until CLS defaults this)
13
+ - Erroneously generated foreign keys in `req.data` for UPDATE using path expressions
14
+ - `INSERT.columns.rows` for multiple nested composition of aspects
15
+ - Paths passed to `tar` on Windows are now normalized to use forward slashes.
16
+
7
17
  ## Version 7.7.0 - 2024-02-26
8
18
 
9
19
  ### Added
@@ -86,6 +86,9 @@ module.exports = function format(module, level, ...args) {
86
86
  // append remaining args via util.format()
87
87
  if (args.length) toLog.msg = toLog.msg ? util.format(toLog.msg, ...args) : util.format(...args)
88
88
 
89
+ // ensure type (required on kubernetes if logs are pulled instead of pushed through binding)
90
+ toLog.type ??= 'log'
91
+
89
92
  // REVISIT: should not be necessary with new protocol adapters
90
93
  // 4xx: lower to warning (if error)
91
94
  if (toLog.level && toLog.level.match(/error/i) && _is4xx(toLog)) toLog.level = 'warn'
package/lib/utils/tar.js CHANGED
@@ -11,7 +11,7 @@ const _resolve = (...x) => path.resolve (cds.root,...x)
11
11
  // tar does not work properly on Windows (by npm/jest tests) w/o this change
12
12
  const win = path => {
13
13
  if (!path) return path
14
- if (typeof path === 'string') return path.replace('C:', '//localhost/c$')
14
+ if (typeof path === 'string') return path.replace('C:', '//localhost/c$').replace(/\\+/g, '/')
15
15
  if (Array.isArray(path)) return path.map(el => win(el))
16
16
  }
17
17
 
@@ -37,7 +37,7 @@ function where2obj(where, target = null, data = {}) {
37
37
  // optional validation if target is passed
38
38
  if (target) {
39
39
  const colEl = target.elements[colName]
40
- if (!colEl || !(colEl.key || colEl.__foreignKey4)) continue
40
+ if (!colEl || !colEl.key) continue
41
41
  }
42
42
  const opWhere = where[i + 1]
43
43
  const valWhere = where[i + 2]
@@ -803,7 +803,7 @@ class JoinCQNFromExpanded {
803
803
  return 'DRAFT.DraftAdministrativeData'
804
804
  }
805
805
 
806
- if (isActiveRequired && !defaultLanguage) {
806
+ if (this._SELECT.localized !== false && isActiveRequired && !defaultLanguage) {
807
807
  const locale = this._locale ? `${this._locale}.` : ''
808
808
  const localized = `localized.${locale}${target}`
809
809
  if (this._csn.definitions[localized]) {
@@ -243,7 +243,7 @@ class InsertBuilder extends BaseBuilder {
243
243
  if (this.uuidKeys) {
244
244
  for (const key of this.uuidKeys) {
245
245
  if (!flattenColumnMap.get(key)) {
246
- columns.push(...this.uuidKeys.map(key => this._quoteElement(key)))
246
+ columns.push(this._quoteElement(key))
247
247
  }
248
248
  }
249
249
  }
@@ -17,15 +17,15 @@ class EndpointRegistry {
17
17
  if (isSecured()) {
18
18
  if (cds.requires.auth.impl) {
19
19
  if (cds.env.requires.middlewares !== false) {
20
- paths.forEach(path => cds.app.use(path, cds.middlewares.before)) // contains auth, trace, context
20
+ cds.app.use(basePath, cds.middlewares.before) // contains auth, trace, context
21
21
  } else {
22
22
  const impl = _require(cds.resolve(cds.requires.auth.impl))
23
- paths.forEach(path => cds.app.use(path, impl))
23
+ cds.app.use(basePath, impl)
24
24
  }
25
25
  } else {
26
26
  if (cds.env.requires.middlewares !== false) {
27
27
  const jwt_auth = require('../../../../lib/auth/jwt-auth.js')
28
- paths.forEach(path => cds.app.use(path, jwt_auth(cds.requires.auth)))
28
+ cds.app.use(basePath, jwt_auth(cds.requires.auth))
29
29
  } else {
30
30
  const JWTStrategy = require('../../auth/strategies/JWT.js')
31
31
  // eslint-disable-next-line cds/no-missing-dependencies -- needs to be added by app dev
@@ -33,28 +33,22 @@ class EndpointRegistry {
33
33
  // REVISIT: It's unclear if the credentials from cds.requires.auth need to be used here.
34
34
  // In principle, user-facing endpoints might differ from messaging ones.
35
35
  passport.use(new JWTStrategy(cds.requires.auth.credentials))
36
- paths.forEach(path => {
37
- cds.app.use(path, passport.initialize())
38
- cds.app.use(path, passport.authenticate('JWT', { session: false }))
39
- })
36
+ cds.app.use(basePath, passport.initialize())
37
+ cds.app.use(basePath, passport.authenticate('JWT', { session: false }))
40
38
  }
41
39
  }
42
40
  // unsuccessful auth doesn't automatically reject!
43
- paths.forEach(path => {
44
- cds.app.use(path, (req, res, next) => {
45
- // REVISIT: we should probably pass an error into next so that a (custom) error middleware can handle it
46
- if (!req.user) res.status(401).json({ error: ODATA_UNAUTHORIZED })
47
- next()
48
- })
41
+ cds.app.use(basePath, (req, res, next) => {
42
+ // REVISIT: we should probably pass an error into next so that a (custom) error middleware can handle it
43
+ if (!req.user) res.status(401).json({ error: ODATA_UNAUTHORIZED })
44
+ next()
49
45
  })
50
46
  } else if (process.env.NODE_ENV === 'production') {
51
47
  LOG.warn('Messaging endpoints not secured')
52
48
  }
53
- paths.forEach(path => {
54
- cds.app.use(path, express.json({ type: 'application/*+json' }))
55
- cds.app.use(path, express.json())
56
- cds.app.use(path, express.urlencoded({ extended: true }))
57
- })
49
+ cds.app.use(basePath, express.json({ type: 'application/*+json' }))
50
+ cds.app.use(basePath, express.json())
51
+ cds.app.use(basePath, express.urlencoded({ extended: true }))
58
52
  LOG._debug && LOG.debug('Register inbound endpoint', { basePath, method: 'OPTIONS' })
59
53
 
60
54
  // Clear cds.context as it would interfere with subsequent transactions
@@ -62,10 +56,6 @@ class EndpointRegistry {
62
56
  cds.context = undefined
63
57
  next()
64
58
  })
65
- cds.app.use(deployPath, (_req, _res, next) => {
66
- cds.context = undefined
67
- next()
68
- })
69
59
 
70
60
  cds.app.options(basePath, (req, res) => {
71
61
  try {
@@ -295,9 +295,13 @@ const getKeysFromPath = (from, srv) => {
295
295
  const join = [...relation[0].xpr]
296
296
  while (join.length >= 3) {
297
297
  const [left, _, right] = join.splice(0, 4)
298
- if (left.ref?.[0] === 'target') keys[left.ref[1]] = 'val' in right ? right.val : seg_keys[right.ref[1]]
299
- else if (right.ref?.[0] === 'target') keys[right.ref[1]] = 'val' in left ? left.val : seg_keys[left.ref[1]]
300
- else {
298
+ if (left.ref?.[0] === 'target') {
299
+ if (left.ref[1] in keys) break // we already added the foreign key for the last segment
300
+ keys[left.ref[1]] = 'val' in right ? right.val : seg_keys[right.ref[1]]
301
+ } else if (right.ref?.[0] === 'target') {
302
+ if (right.ref[1] in keys) break // we already added the foreign key for the last segment
303
+ keys[right.ref[1]] = 'val' in left ? left.val : seg_keys[left.ref[1]]
304
+ } else {
301
305
  // REVISIT: what to do here?
302
306
  }
303
307
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds",
3
- "version": "7.7.0",
3
+ "version": "7.7.1",
4
4
  "description": "SAP Cloud Application Programming Model - CDS for Node.js",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "keywords": [