@sap/cds 7.4.2 → 7.5.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 +100 -0
- package/apis/cds.d.ts +1 -38
- package/apis/core.d.ts +21 -101
- package/apis/cqn.d.ts +18 -76
- package/apis/csn.d.ts +18 -114
- package/apis/events.d.ts +16 -123
- package/apis/internal/inference.d.ts +18 -32
- package/apis/linked.d.ts +18 -97
- package/apis/log.d.ts +19 -164
- package/apis/models.d.ts +18 -180
- package/apis/ql.d.ts +16 -323
- package/apis/reflect.d.ts +32 -0
- package/apis/server.d.ts +18 -135
- package/apis/services.d.ts +18 -380
- package/bin/cds-serve.js +5 -2
- package/bin/serve.js +7 -16
- package/lib/auth/basic-auth.js +3 -1
- package/lib/auth/ias-auth.js +62 -48
- package/lib/auth/ias-claims.js +34 -0
- package/lib/auth/index.js +55 -33
- package/lib/auth/jwt-auth.js +55 -52
- package/lib/compile/cdsc.js +2 -2
- package/lib/compile/to/edm.js +4 -4
- package/lib/compile/to/hdbtabledata.js +5 -8
- package/lib/compile/to/srvinfo.js +2 -2
- package/lib/env/cds-env.js +3 -9
- package/lib/env/cds-requires.js +16 -17
- package/lib/env/compat.js +0 -9
- package/lib/env/defaults.js +17 -6
- package/lib/i18n/localize.js +46 -42
- package/lib/index.js +6 -8
- package/lib/linked/classes.js +7 -118
- package/lib/linked/entities.js +1 -1
- package/lib/log/cds-log.js +15 -10
- package/lib/log/format/aspects/als.js +41 -0
- package/lib/log/format/aspects/cf.js +36 -0
- package/lib/log/format/json.js +96 -0
- package/lib/plugins.js +7 -3
- package/lib/req/context.js +4 -2
- package/lib/srv/cds-connect.js +3 -5
- package/lib/srv/cds-serve.js +13 -26
- package/lib/srv/factory.js +3 -3
- package/lib/srv/middlewares/index.js +0 -2
- package/lib/srv/middlewares/trace.js +2 -3
- package/lib/srv/protocols/_legacy.js +27 -30
- package/lib/srv/protocols/index.js +173 -58
- package/lib/srv/protocols/odata-v4.js +29 -16
- package/lib/srv/srv-api.js +8 -13
- package/lib/srv/srv-handlers.js +14 -14
- package/lib/utils/cds-utils.js +15 -0
- package/libx/_runtime/auth/index.js +4 -5
- package/libx/_runtime/auth/strategies/basic.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +23 -13
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +6 -15
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +10 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +5 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +2 -1
- package/libx/_runtime/cds-services/services/utils/columns.js +3 -9
- package/libx/_runtime/cds.js +13 -0
- package/libx/_runtime/common/composition/data.js +3 -0
- package/libx/_runtime/common/composition/delete.js +1 -1
- package/libx/_runtime/common/error/frontend.js +2 -2
- package/libx/_runtime/common/generic/auth/readOnly.js +1 -1
- package/libx/_runtime/common/generic/auth/restrictions.js +1 -1
- package/libx/_runtime/common/generic/sorting.js +4 -5
- package/libx/_runtime/common/utils/csn.js +23 -18
- package/libx/_runtime/common/utils/restrictions.js +6 -15
- package/libx/_runtime/db/generic/input.js +3 -2
- package/libx/_runtime/fiori/generic/readOverDraft.js +2 -5
- package/libx/_runtime/fiori/lean-draft.js +69 -5
- package/libx/_runtime/hana/Service.js +1 -1
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +1 -1
- package/libx/_runtime/messaging/Outbox.js +3 -8
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +1 -0
- package/libx/_runtime/messaging/enterprise-messaging.js +1 -1
- package/libx/_runtime/messaging/file-based.js +1 -1
- package/libx/_runtime/messaging/service.js +7 -10
- package/libx/_runtime/remote/Service.js +15 -45
- package/libx/_runtime/remote/utils/client.js +20 -33
- package/libx/_runtime/remote/utils/cloudSdkProvider.js +30 -0
- package/libx/_runtime/sqlite/Service.js +2 -2
- package/libx/odata/afterburner.js +29 -21
- package/libx/odata/cqn2odata.js +1 -1
- package/libx/odata/error.js +7 -0
- package/libx/odata/grammar.peggy +16 -20
- package/libx/odata/metadata.js +73 -78
- package/libx/odata/parser.js +1 -1
- package/libx/odata/read.js +94 -0
- package/libx/odata/result.js +91 -0
- package/libx/odata/service-document.js +31 -37
- package/libx/odata/utils.js +2 -1
- package/libx/outbox/index.js +9 -4
- package/libx/rest/RestAdapter.js +68 -67
- package/libx/rest/middleware/create.js +20 -26
- package/libx/rest/middleware/delete.js +5 -3
- package/libx/rest/middleware/error.js +2 -3
- package/libx/rest/middleware/input.js +5 -5
- package/libx/rest/middleware/operation.js +96 -41
- package/libx/rest/middleware/parse.js +4 -6
- package/libx/rest/middleware/payload.js +5 -5
- package/libx/rest/middleware/read.js +11 -17
- package/libx/rest/middleware/update.js +20 -25
- package/package.json +2 -1
- package/server.js +7 -4
- package/srv/outbox.cds +9 -10
- package/apis/env.d.ts +0 -25
- package/apis/test.d.ts +0 -81
- package/apis/utils.d.ts +0 -15
- package/lib/auth/passport-basic.js +0 -14
- package/lib/auth/passport-digest.js +0 -16
- package/lib/env/presets.js +0 -35
- package/lib/log/format/cf.js +0 -16
- package/lib/log/format/kibana.js +0 -92
- package/lib/srv/middlewares/ctx-auth.js +0 -11
- package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +0 -119
package/lib/auth/index.js
CHANGED
|
@@ -1,38 +1,60 @@
|
|
|
1
|
-
const cds = require ('../index')
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
const cds = require ('../index')
|
|
2
|
+
|
|
3
|
+
const _builtin = {
|
|
4
|
+
mocked: 'basic-auth',
|
|
5
|
+
basic: 'basic-auth',
|
|
6
|
+
ias: 'ias-auth',
|
|
7
|
+
jwt: 'jwt-auth',
|
|
8
|
+
xsuaa: 'jwt-auth',
|
|
9
|
+
dummy: 'dummy-auth',
|
|
10
|
+
}
|
|
11
|
+
for (let b in _builtin) _builtin[b+'-auth'] = _builtin[b]
|
|
12
|
+
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Constructs
|
|
15
|
+
* Constructs auth middlewares as configured
|
|
16
16
|
*/
|
|
17
|
-
function auth_factory (
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
17
|
+
module.exports = function auth_factory (o) {
|
|
18
|
+
|
|
19
|
+
// prepare options
|
|
20
|
+
const options = { ...o, ...cds.requires.auth }
|
|
21
|
+
let { kind, impl } = options
|
|
22
|
+
|
|
23
|
+
// if no impl is given, it's a built-in strategy
|
|
24
|
+
if (!impl) impl = __dirname + '/' + _builtin[kind]
|
|
25
|
+
else if (kind in _builtin) kind = 'custom'
|
|
26
|
+
// NOTE: ^^^^^^^^^^^^^^^
|
|
27
|
+
// This is a workaround to avoid displaying kind:'mocked-auth'
|
|
28
|
+
// from [development] defaults with impl: './custom-auth'
|
|
29
|
+
// from cds.requires.auth in the log or error output below.
|
|
30
|
+
|
|
31
|
+
// try resolving the impl, throw if not found
|
|
32
|
+
const config = { kind, impl: cds.utils.local(impl) }
|
|
33
|
+
// use cds.resolve() to allow './srv/auth.js' and 'srv/auth.js'
|
|
34
|
+
try { impl = require.resolve (cds.resolve (impl)?.[0], {paths:[cds.root]}) } catch {
|
|
35
|
+
throw cds.error `Didn't find auth implementation for ${config}`
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
|
|
38
|
+
// load the auth middleware from the resolved path
|
|
39
|
+
cds.log().info ('using auth strategy', config, '\n')
|
|
40
|
+
let auth = require (impl)
|
|
41
|
+
|
|
42
|
+
// if auth is a factory itself, call it to get the middleware
|
|
43
|
+
if (typeof auth === 'function' && auth.length < 3) auth = auth(options)
|
|
44
|
+
|
|
45
|
+
// return the auth middleware followed by a middleware to fill in cds.context
|
|
46
|
+
return [ auth, ctx_auth ]
|
|
38
47
|
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Propagate user and tenant from req to cds.context
|
|
51
|
+
*/
|
|
52
|
+
function ctx_auth (req, res, next) {
|
|
53
|
+
const ctx = cds.context
|
|
54
|
+
ctx.user = req.user
|
|
55
|
+
ctx.tenant = req.tenant || ctx.user?.tenant
|
|
56
|
+
next()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// export ctx_auth for legacy protocol adapter -> remove with cds^8
|
|
60
|
+
module.exports._ctx_auth = ctx_auth
|
package/lib/auth/jwt-auth.js
CHANGED
|
@@ -3,76 +3,79 @@ const LOG = cds.log('auth')
|
|
|
3
3
|
|
|
4
4
|
// _require for better error message
|
|
5
5
|
const _require = require('../../libx/_runtime/common/utils/require')
|
|
6
|
-
const
|
|
7
|
-
const passport = _require('passport')
|
|
8
|
-
const { JWTStrategy } = _require('@sap/xssec')
|
|
6
|
+
const xssec = _require('@sap/xssec')
|
|
9
7
|
|
|
10
8
|
module.exports = function jwt_auth(config) {
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const { kind, credentials } = config
|
|
10
|
+
|
|
11
|
+
if (!credentials) {
|
|
12
|
+
let msg = `Authentication kind "${kind}" configured, but no XSUAA instance bound to application.`
|
|
13
13
|
msg += ' Either bind an IAS instance, or switch to an authentication kind that does not require a binding.'
|
|
14
14
|
throw new Error(msg)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return express
|
|
20
|
-
.Router()
|
|
21
|
-
.use((req, res, next) => {
|
|
22
|
-
// callback needed in order to suppress 401 and continue with anonymous to allow @requires: 'any'/ restrict_all_services=false
|
|
23
|
-
const callback = (err, user, info, _status) => {
|
|
24
|
-
if (err) return next(err)
|
|
25
|
-
|
|
26
|
-
if (user) {
|
|
27
|
-
req.user = user
|
|
28
|
-
req.authInfo = info
|
|
29
|
-
} else {
|
|
30
|
-
req.user = new cds.User.default
|
|
31
|
-
if (LOG._debug && req.tokenInfo)
|
|
32
|
-
LOG.debug('Error during token validation:', req.tokenInfo.getErrorObject().message)
|
|
33
|
-
}
|
|
17
|
+
function getUser(tokenInfo) {
|
|
18
|
+
const payload = tokenInfo.getPayload()
|
|
34
19
|
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
passport.authenticate('JWT', { session: false }, callback)(req, res, next)
|
|
38
|
-
})
|
|
39
|
-
.use((req, res, next) => {
|
|
40
|
-
if (!('authInfo' in req)) return next()
|
|
20
|
+
let id = payload.user_name
|
|
41
21
|
|
|
42
|
-
|
|
22
|
+
// Roles = scope names w/o xsappname
|
|
23
|
+
const xsappname = new RegExp(`^${credentials.xsappname}\\.`)
|
|
24
|
+
let roles = payload.scope.map(s => s.replace(xsappname, ''))
|
|
43
25
|
|
|
44
|
-
|
|
26
|
+
// Disallow setting system roles from external
|
|
27
|
+
roles = roles.filter(r => !(r in { 'internal-user': 1, 'system-user': 1 }))
|
|
45
28
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
29
|
+
if (payload.grant_type in { client_credentials: 1, client_x509: 1 }) {
|
|
30
|
+
id = 'system'
|
|
31
|
+
roles.push('system-user')
|
|
32
|
+
if (tokenInfo.getClientId() === credentials.clientid) roles.push('internal-user')
|
|
33
|
+
}
|
|
49
34
|
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
const attr = Object.assign({}, payload['xs.user.attributes'])
|
|
36
|
+
if (kind === 'xsuaa') {
|
|
37
|
+
attr.logonName = payload.user_name
|
|
38
|
+
attr.givenName = payload.given_name
|
|
39
|
+
attr.familyName = payload.family_name
|
|
40
|
+
attr.email = payload.email
|
|
41
|
+
}
|
|
52
42
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// > not "weak"
|
|
56
|
-
roles.push('authenticated-user')
|
|
43
|
+
return new cds.User({ id, roles, attr })
|
|
44
|
+
}
|
|
57
45
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
46
|
+
return (req, _, next) => {
|
|
47
|
+
const token = req.headers.authorization?.split(/^bearer /i)[1]
|
|
48
|
+
xssec.createSecurityContext(token, credentials, function (err, securityContext, tokenInfo) {
|
|
49
|
+
if (err && !tokenInfo) {
|
|
50
|
+
// here, there is a general problem, .e.g., bad credentials -> throw the error
|
|
51
|
+
return next(err)
|
|
63
52
|
}
|
|
64
53
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
54
|
+
if (err && LOG._debug) LOG.debug('User could not be authenticated due to error:', err)
|
|
55
|
+
|
|
56
|
+
// if no general problem, tokenInfo object is always available -> add to req via getter for compat reasons
|
|
57
|
+
Object.defineProperty(req, 'tokenInfo', {
|
|
58
|
+
get() {
|
|
59
|
+
cds._logDeprecation('req.tokenInfo was added for compatibility purposes but will be removed in the next major version.')
|
|
60
|
+
return tokenInfo
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
if (!securityContext) {
|
|
65
|
+
if (!req.headers.authorization) {
|
|
66
|
+
LOG._debug && LOG.debug('No authorization header provided, continuing with default user.')
|
|
67
|
+
req.user = new cds.User.default()
|
|
68
|
+
return next()
|
|
69
|
+
}
|
|
70
|
+
return next(new cds.error('Unauthorized', { statusCode: 401 }))
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
req.user =
|
|
74
|
-
req.tenant =
|
|
73
|
+
req.user = getUser(tokenInfo)
|
|
74
|
+
req.tenant = tokenInfo.getZoneId()
|
|
75
|
+
|
|
76
|
+
req.authInfo = securityContext //> compat req.authInfo
|
|
75
77
|
|
|
76
78
|
next()
|
|
77
79
|
})
|
|
80
|
+
}
|
|
78
81
|
}
|
package/lib/compile/cdsc.js
CHANGED
|
@@ -63,8 +63,8 @@ const _options = {for: Object.assign (_options4, {
|
|
|
63
63
|
|
|
64
64
|
sql(o,_env) {
|
|
65
65
|
// REVISIT: compiler requires to only provide assertIntegrityType if defined
|
|
66
|
-
let
|
|
67
|
-
let constraints =
|
|
66
|
+
let { assert_integrity } = cds.env.features
|
|
67
|
+
let constraints = assert_integrity && { assertIntegrityType: assert_integrity.toUpperCase() }
|
|
68
68
|
return _options4 ({ ...constraints, ..._env||cds.env.sql, ...o }, {
|
|
69
69
|
sql_mapping : 'names', //> legacy
|
|
70
70
|
sqlDialect : 'dialect', //> legacy
|
package/lib/compile/to/edm.js
CHANGED
|
@@ -3,12 +3,12 @@ const cds = require ('../../index')
|
|
|
3
3
|
|
|
4
4
|
if (cds.env.features.precompile_edms !== false) {
|
|
5
5
|
const _precompiled = new WeakMap
|
|
6
|
+
const to_edm = cdsc.to.edm
|
|
6
7
|
cdsc.to.edm = Object.assign((csn, o) => {
|
|
7
|
-
if (o.to === 'openapi') return
|
|
8
|
+
if (o.to === 'openapi') return to_edm(csn, o)
|
|
8
9
|
if (!_precompiled.has(csn)) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
_precompiled.set(csn, cdsc.to.edm.all(csn, Object.assign({ serviceNames }, o)))
|
|
10
|
+
if (!o.serviceNames) o = { ...o, serviceNames: cds.linked(csn).services.filter(srv => srv._serves_odata).map(d => d.name) }
|
|
11
|
+
_precompiled.set(csn, cdsc.to.edm.all(csn, o))
|
|
12
12
|
}
|
|
13
13
|
return _precompiled.get(csn)[o.service]
|
|
14
14
|
}, { all: cdsc.to.edm.all })
|
|
@@ -2,13 +2,9 @@ const cds = require('../../../lib')
|
|
|
2
2
|
const { getElementCdsPersistenceName, getArtifactCdsPersistenceName } = require('@sap/cds-compiler')
|
|
3
3
|
const { fs, path, isdir, csv } = cds.utils
|
|
4
4
|
const { readdir } = fs.promises
|
|
5
|
-
let
|
|
5
|
+
let LOG = cds.log('hdbtabledata|build|all')
|
|
6
6
|
|
|
7
7
|
module.exports = async (model, options = {}) => {
|
|
8
|
-
if (options.logger) {
|
|
9
|
-
logger = options.logger
|
|
10
|
-
}
|
|
11
|
-
|
|
12
8
|
model = cds.minify(model)
|
|
13
9
|
const baseDir = options.baseDir // where the hdbtabledata will be located, for usage in the file_name path
|
|
14
10
|
const dirs = Array.isArray(options.dirs) ? options.dirs : _csvDirs(model.$sources.map(path.dirname))
|
|
@@ -36,7 +32,7 @@ async function _tabledata4(dir, csvFile, model, baseDir, naming) {
|
|
|
36
32
|
.filter(name => !name.startsWith('localized.'))
|
|
37
33
|
.find(name => name.toLowerCase().includes(entityName.toLowerCase()))
|
|
38
34
|
if (candidate) message += `. Did you mean '${candidate}'?`
|
|
39
|
-
return
|
|
35
|
+
return LOG.warn(`[hdbtabledata] ${message}`)
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
const tableName = getArtifactCdsPersistenceName(entity.name, naming, model, 'hana')
|
|
@@ -95,7 +91,7 @@ function _entity4(name, csn) {
|
|
|
95
91
|
}
|
|
96
92
|
return
|
|
97
93
|
}
|
|
98
|
-
if (entity['@cds.persistence.skip'] === true) return
|
|
94
|
+
if (entity['@cds.persistence.skip'] === true) return LOG.warn(`[hdbtabledata] exclude skipped entity '${name}'`)
|
|
99
95
|
const p = entity.query && entity.query.SELECT || entity.projection
|
|
100
96
|
if (p) {
|
|
101
97
|
let from = p.from
|
|
@@ -120,6 +116,7 @@ function _csvDirs(sources) {
|
|
|
120
116
|
return folders
|
|
121
117
|
}
|
|
122
118
|
|
|
119
|
+
|
|
123
120
|
function _csvs(filename, _, allFiles) {
|
|
124
121
|
if (filename[0] === '-' || !filename.endsWith('.csv')) return false
|
|
125
122
|
// ignores 'Books_texts.csv' if there is any 'Books_texts_LANG.csv'
|
|
@@ -127,7 +124,7 @@ function _csvs(filename, _, allFiles) {
|
|
|
127
124
|
const basename = RegExp.$1
|
|
128
125
|
const monoLangFiles = allFiles.filter(file => new RegExp(basename + '_texts_').test(file))
|
|
129
126
|
if (monoLangFiles.length > 0) {
|
|
130
|
-
|
|
127
|
+
LOG.debug(`[hdbtabledata] ignoring '${filename}' in favor of [${monoLangFiles}]`)
|
|
131
128
|
return false
|
|
132
129
|
}
|
|
133
130
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
const cds = require('../..')
|
|
3
|
-
const { isfile, path: { join
|
|
3
|
+
const { isfile, path: { join } } = cds.utils
|
|
4
4
|
|
|
5
5
|
// Produces information on provided services in the model:
|
|
6
6
|
// name, expected URL path at runtime,...
|
|
@@ -37,7 +37,7 @@ module.exports = (model, options={}) => {
|
|
|
37
37
|
function _makeNode(service) {
|
|
38
38
|
return {
|
|
39
39
|
name: service.name,
|
|
40
|
-
urlPath: _url4 (cds.service.path4(service)),
|
|
40
|
+
urlPath: _url4 (cds.service.protocols.path4(service)),
|
|
41
41
|
destination: 'srv-api', // the name to register in xs-app.json
|
|
42
42
|
runtime: 'Node.js',
|
|
43
43
|
location: service.$location
|
package/lib/env/cds-env.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const { isdir, isfile, fs, path } = require('../utils/cds-utils')
|
|
2
2
|
const DEFAULTS = require('./defaults'), defaults = require.resolve ('./defaults')
|
|
3
3
|
const compat = require('./compat')
|
|
4
|
-
const presets = require('./presets')
|
|
5
4
|
const serviceBindings = require('./serviceBindings');
|
|
6
5
|
|
|
7
6
|
|
|
@@ -88,10 +87,6 @@ class Config {
|
|
|
88
87
|
// Complete service configurations from cloud service bindings
|
|
89
88
|
this._add_cloud_service_bindings(process.env)
|
|
90
89
|
|
|
91
|
-
// Apply presets
|
|
92
|
-
presets (this)
|
|
93
|
-
|
|
94
|
-
|
|
95
90
|
// Only if feature is enabled
|
|
96
91
|
if (this.features && this.features.emulate_vcap_services) {
|
|
97
92
|
this._emulate_vcap_services()
|
|
@@ -127,8 +122,7 @@ class Config {
|
|
|
127
122
|
|
|
128
123
|
|
|
129
124
|
get plugins() {
|
|
130
|
-
|
|
131
|
-
return super.plugins = require('../plugins').fetch(DEV)
|
|
125
|
+
return super.plugins = require('../plugins').fetch()
|
|
132
126
|
}
|
|
133
127
|
|
|
134
128
|
|
|
@@ -390,7 +384,7 @@ class Config {
|
|
|
390
384
|
_fetch ({ type: conf.dialect || conf.kind })
|
|
391
385
|
|
|
392
386
|
function _fetch (predicate) {
|
|
393
|
-
for (let k
|
|
387
|
+
for (let k in predicate) {
|
|
394
388
|
const v = predicate[k]; if (!v) continue
|
|
395
389
|
const filter = k === 'tag' ? e => _array(e,'tags').includes(v) : e => e[k] === v
|
|
396
390
|
for (let stype in vcaps) {
|
|
@@ -472,7 +466,7 @@ function _merge (dst, src, _profiles) {
|
|
|
472
466
|
}
|
|
473
467
|
|
|
474
468
|
const v = pd.value
|
|
475
|
-
if (typeof v === 'object' && !Array.isArray(v)) {
|
|
469
|
+
if (typeof v === 'object' && !Array.isArray(v) && v != null) {
|
|
476
470
|
if (!dst[p]) dst[p] = {}
|
|
477
471
|
if (typeof dst[p] !== 'object') dst[p] = v
|
|
478
472
|
else _merge (dst[p], v, _profiles)
|
package/lib/env/cds-requires.js
CHANGED
|
@@ -14,7 +14,6 @@ exports = module.exports = {
|
|
|
14
14
|
'[production]': { kind: 'jwt-auth' }
|
|
15
15
|
},
|
|
16
16
|
|
|
17
|
-
|
|
18
17
|
/**
|
|
19
18
|
* This is the implementation for `cds.requires` which is `cds.env.requires`
|
|
20
19
|
* plus additional entries for all cds.required.<name>.service
|
|
@@ -36,18 +35,16 @@ exports = module.exports = {
|
|
|
36
35
|
|
|
37
36
|
const admin = [ 'cds.Subscriber', 'admin' ]
|
|
38
37
|
const builder = [ 'cds.ExtensionDeveloper', 'cds.UIFlexDeveloper' ]
|
|
39
|
-
|
|
40
38
|
const _authentication_strategies = {
|
|
41
39
|
|
|
42
40
|
"basic-auth": {
|
|
43
|
-
kind: 'basic
|
|
44
|
-
strategy: 'mock', // REVISIT: Can be removed when we switch to new auth middlewars
|
|
41
|
+
kind: 'basic',
|
|
45
42
|
users: {},
|
|
46
43
|
tenants: {}
|
|
47
44
|
},
|
|
48
45
|
"mocked-auth": {
|
|
49
|
-
|
|
50
|
-
kind: '
|
|
46
|
+
restrict_all_services: false,
|
|
47
|
+
kind: 'mocked',
|
|
51
48
|
users: {
|
|
52
49
|
alice: { tenant: 't1', roles: [ ...admin ] },
|
|
53
50
|
bob: { tenant: 't1', roles: [ ...builder ] },
|
|
@@ -65,25 +62,30 @@ const _authentication_strategies = {
|
|
|
65
62
|
}
|
|
66
63
|
},
|
|
67
64
|
"jwt-auth": {
|
|
68
|
-
|
|
69
|
-
kind: 'jwt-auth',
|
|
65
|
+
kind: 'jwt',
|
|
70
66
|
vcap: { label: 'xsuaa' }
|
|
71
67
|
},
|
|
72
68
|
"ias-auth": {
|
|
73
|
-
kind: 'ias
|
|
69
|
+
kind: 'ias',
|
|
74
70
|
vcap: { label: 'identity' }
|
|
75
71
|
},
|
|
76
|
-
"xsuaa": {
|
|
77
|
-
strategy: 'xsuaa', // REVISIT: Can be removed when we switch to new auth middlewars
|
|
72
|
+
"xsuaa-auth": {
|
|
78
73
|
kind: 'xsuaa',
|
|
79
74
|
vcap: { label: 'xsuaa' }
|
|
80
75
|
},
|
|
81
76
|
"dummy-auth": {
|
|
82
|
-
|
|
77
|
+
kind: 'dummy',
|
|
83
78
|
},
|
|
84
79
|
|
|
85
80
|
}
|
|
86
81
|
|
|
82
|
+
for (let each of Object.values(_authentication_strategies)) {
|
|
83
|
+
Object.defineProperty (each, 'strategy', {get() {
|
|
84
|
+
if (process.env.NODE_ENV !== 'production') console.trace('WARNING: auth.strategy is deprecated, use auth.kind instead')
|
|
85
|
+
return { jwt: 'JWT', mocked: 'mock' }[this.kind] || this.kind
|
|
86
|
+
}})
|
|
87
|
+
}
|
|
88
|
+
|
|
87
89
|
|
|
88
90
|
const _services = {
|
|
89
91
|
|
|
@@ -127,7 +129,6 @@ const _databases = {
|
|
|
127
129
|
impl: `${_runtime}/sqlite/Service.js`,
|
|
128
130
|
credentials: { url: 'db.sqlite' },
|
|
129
131
|
},
|
|
130
|
-
|
|
131
132
|
"better-sqlite": {
|
|
132
133
|
credentials: { url: ":memory:" },
|
|
133
134
|
impl: "@cap-js/sqlite",
|
|
@@ -162,16 +163,14 @@ const _databases = {
|
|
|
162
163
|
|
|
163
164
|
const _outbox = {
|
|
164
165
|
|
|
165
|
-
outbox:
|
|
166
|
-
kind: "persistent-outbox",
|
|
167
|
-
parallel: true
|
|
168
|
-
},
|
|
166
|
+
outbox: "persistent-outbox",
|
|
169
167
|
|
|
170
168
|
"in-memory-outbox": {},
|
|
171
169
|
"persistent-outbox": {
|
|
172
170
|
model: "@sap/cds/srv/outbox",
|
|
173
171
|
maxAttempts: 20,
|
|
174
172
|
chunkSize: 100,
|
|
173
|
+
parallel: true,
|
|
175
174
|
storeLastError: true
|
|
176
175
|
}
|
|
177
176
|
|
package/lib/env/compat.js
CHANGED
|
@@ -7,15 +7,6 @@ module.exports = function (conf) {
|
|
|
7
7
|
set(x) { _.log.levels.cli = x },
|
|
8
8
|
},
|
|
9
9
|
|
|
10
|
-
auth: {value:{
|
|
11
|
-
get passport() {
|
|
12
|
-
return _.requires.auth
|
|
13
|
-
},
|
|
14
|
-
set passport(v) {
|
|
15
|
-
_.requires.auth = v
|
|
16
|
-
}
|
|
17
|
-
}},
|
|
18
|
-
|
|
19
10
|
data: {value:{
|
|
20
11
|
get model(){
|
|
21
12
|
const db = _.requires.db; if (!db) return undefined
|
package/lib/env/defaults.js
CHANGED
|
@@ -5,8 +5,6 @@ const defaults = module.exports = {
|
|
|
5
5
|
|
|
6
6
|
production,
|
|
7
7
|
|
|
8
|
-
cov2ap: false, // REVISIT: workaround for bug in @cap-js-community/odata-v2-adapter/cds-plugin -> cds/tests/_runtime/remote/__tests__/integration/mocked-v2-consumption/v2.test.js
|
|
9
|
-
|
|
10
8
|
requires: require('./cds-requires'),
|
|
11
9
|
|
|
12
10
|
server: {
|
|
@@ -14,6 +12,13 @@ const defaults = module.exports = {
|
|
|
14
12
|
port: 4004,
|
|
15
13
|
},
|
|
16
14
|
|
|
15
|
+
protocols: {
|
|
16
|
+
'odata-v4' : { path: '/odata/v4' },
|
|
17
|
+
'odata-v2' : { path: '/odata/v2' },
|
|
18
|
+
'rest' : { path: '/rest' },
|
|
19
|
+
'hcql' : { path: '/hcql' },
|
|
20
|
+
},
|
|
21
|
+
|
|
17
22
|
// kept for backwards compatibility
|
|
18
23
|
schemas: {
|
|
19
24
|
'cds-rc.json': join(__dirname, 'schemas/cds-rc.json'),
|
|
@@ -56,21 +61,27 @@ const defaults = module.exports = {
|
|
|
56
61
|
|
|
57
62
|
log: {
|
|
58
63
|
Logger: undefined, //> use default
|
|
64
|
+
'[development]': { format: 'plain' },
|
|
65
|
+
'[production]': { format: 'json' },
|
|
59
66
|
levels: {
|
|
60
67
|
compile: 'warn',
|
|
61
68
|
cli: 'warn',
|
|
62
69
|
deploy: 'info',
|
|
63
70
|
serve: 'info',
|
|
64
|
-
server: 'info'
|
|
71
|
+
server: 'info'
|
|
65
72
|
},
|
|
66
73
|
service: false,
|
|
74
|
+
// the rest is only applicable for the json formatter
|
|
75
|
+
user: false,
|
|
76
|
+
mask_headers: ['/authorization/i', '/cookie/i'],
|
|
77
|
+
aspects: ['./aspects/cf', './aspects/als'], //> EXPERIMENTAL!!!
|
|
67
78
|
// adds custom fields in kibana's error rendering (unknown fields are ignored); key: index
|
|
68
|
-
|
|
79
|
+
// note: custom fields are a feature of Application Logging Service (ALS) and not Kibana per se
|
|
80
|
+
als_custom_fields: {
|
|
69
81
|
// sql
|
|
70
82
|
query: 0,
|
|
71
83
|
// generic validations
|
|
72
|
-
target: 1,
|
|
73
|
-
details: 2
|
|
84
|
+
target: 1, details: 2
|
|
74
85
|
}
|
|
75
86
|
},
|
|
76
87
|
|