@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 +10 -0
- package/lib/log/format/json.js +3 -0
- package/lib/utils/tar.js +1 -1
- package/libx/_runtime/common/utils/cqn.js +1 -1
- package/libx/_runtime/db/expand/expandCQNToJoin.js +1 -1
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +12 -22
- package/libx/odata/utils/index.js +7 -3
- package/package.json +1 -1
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
|
package/lib/log/format/json.js
CHANGED
|
@@ -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 || !
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
37
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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')
|
|
299
|
-
|
|
300
|
-
|
|
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
|
}
|