@sap/cds 5.8.4 → 5.9.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.
- package/CHANGELOG.md +174 -77
- package/app/fiori/preview.js +16 -11
- package/app/index.js +1 -1
- package/bin/build/buildTaskFactory.js +3 -3
- package/bin/build/buildTaskProviderFactory.js +1 -1
- package/bin/build/constants.js +1 -1
- package/bin/build/provider/buildTaskHandlerEdmx.js +12 -7
- package/bin/build/provider/buildTaskHandlerInternal.js +1 -1
- package/bin/build/provider/buildTaskProviderInternal.js +8 -2
- package/bin/build/provider/hana/2migration.js +27 -24
- package/bin/build/provider/hana/index.js +17 -18
- package/bin/build/provider/hana/migrationtable.js +9 -10
- package/bin/build/provider/java-cf/index.js +4 -5
- package/bin/build/provider/node-cf/index.js +99 -6
- package/bin/cds.js +17 -18
- package/bin/deploy/to-hana/cfUtil.js +16 -19
- package/bin/deploy/to-hana/hana.js +7 -24
- package/bin/deploy/to-hana/hdiDeployUtil.js +8 -4
- package/bin/mtx/in-cds.js +2 -2
- package/bin/serve.js +10 -3
- package/bin/utils/modules.js +7 -0
- package/bin/version.js +56 -3
- package/lib/compile/cdsc.js +26 -3
- package/lib/compile/etc/_localized.js +36 -25
- package/lib/compile/etc/csv.js +8 -8
- package/lib/compile/for/drafts.js +9 -0
- package/lib/compile/for/java.js +16 -0
- package/lib/compile/for/nodejs.js +12 -0
- package/lib/compile/for/odata.js +1 -1
- package/lib/compile/index.js +3 -0
- package/lib/compile/minify.js +16 -2
- package/lib/compile/parse.js +2 -2
- package/lib/compile/resolve.js +35 -18
- package/lib/compile/to/json.js +3 -1
- package/lib/compile/to/sql.js +2 -2
- package/lib/compile/to/srvinfo.js +4 -2
- package/lib/connect/index.js +1 -1
- package/lib/core/entities.js +15 -14
- package/lib/core/index.js +39 -36
- package/lib/core/reflect.js +4 -2
- package/lib/deploy.js +114 -127
- package/lib/env/defaults.js +1 -0
- package/lib/env/index.js +165 -165
- package/lib/env/presets.js +1 -0
- package/lib/env/requires.js +120 -49
- package/lib/index.js +1 -0
- package/lib/log/format/kibana.js +2 -2
- package/lib/ql/SELECT.js +10 -0
- package/lib/ql/parse.js +1 -0
- package/lib/req/cds-context.js +4 -1
- package/lib/req/context.js +50 -56
- package/lib/req/event.js +1 -6
- package/lib/req/locale.js +6 -5
- package/lib/req/request.js +2 -0
- package/lib/req/user.js +7 -5
- package/lib/serve/Service-api.js +10 -7
- package/lib/serve/Service-dispatch.js +9 -11
- package/lib/serve/Service-methods.js +30 -41
- package/lib/serve/Transaction.js +10 -7
- package/lib/serve/adapters.js +7 -5
- package/lib/serve/index.js +24 -12
- package/lib/utils/data.js +1 -1
- package/lib/utils/index.js +27 -30
- package/lib/utils/resources/index.js +101 -0
- package/lib/utils/resources/tar.js +71 -0
- package/lib/utils/resources/utils.js +11 -0
- package/libx/_runtime/audit/Service.js +36 -39
- package/libx/_runtime/audit/generic/personal/access.js +3 -4
- package/libx/_runtime/audit/generic/personal/modification.js +3 -4
- package/libx/_runtime/audit/utils/v2.js +1 -2
- package/libx/_runtime/auth/index.js +126 -84
- package/libx/_runtime/auth/strategies/JWT.js +12 -19
- package/libx/_runtime/auth/strategies/dummy.js +1 -5
- package/libx/_runtime/auth/strategies/dwc.js +11 -9
- package/libx/_runtime/auth/strategies/mock.js +0 -4
- package/libx/_runtime/auth/strategies/{utils/xssec.js → xssecUtils.js} +7 -4
- package/libx/_runtime/auth/strategies/xsuaa.js +12 -19
- package/libx/_runtime/auth/utils.js +22 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +104 -98
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/language.js +2 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +4 -29
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +2 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +3 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +4 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +24 -21
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +8 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/DeserializerFactory.js +2 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/DispatcherCommand.js +2 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -12
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +33 -9
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/dispatcherUtils.js +50 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +10 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +9 -11
- package/libx/_runtime/cds-services/adapter/rest/RestRequest.js +6 -3
- package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +4 -2
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/utils.js +1 -1
- package/libx/_runtime/cds-services/adapter/rest/utils/binary.js +1 -1
- package/libx/_runtime/cds-services/adapter/rest/utils/key-value-utils.js +2 -3
- package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +6 -4
- package/libx/_runtime/cds-services/adapter/rest/utils/result.js +1 -0
- package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +8 -5
- package/libx/_runtime/cds-services/services/Service.js +40 -0
- package/libx/_runtime/cds-services/services/utils/columns.js +4 -3
- package/libx/_runtime/cds-services/services/utils/compareJson.js +4 -4
- package/libx/_runtime/cds-services/services/utils/differ.js +3 -3
- package/libx/_runtime/cds-services/services/utils/handlerUtils.js +4 -4
- package/libx/_runtime/cds-services/services/utils/restrictions.js +78 -0
- package/libx/_runtime/cds-services/util/assert.js +20 -14
- package/libx/_runtime/cds.js +9 -1
- package/libx/_runtime/common/aspects/any.js +5 -0
- package/libx/_runtime/common/aspects/entity.js +25 -7
- package/libx/_runtime/common/aspects/utils.js +2 -2
- package/libx/_runtime/common/composition/data.js +6 -0
- package/libx/_runtime/common/composition/insert.js +3 -2
- package/libx/_runtime/common/composition/tree.js +4 -10
- package/libx/_runtime/common/composition/update.js +4 -4
- package/libx/_runtime/common/constants/draft.js +29 -26
- package/libx/_runtime/common/error/constants.js +2 -2
- package/libx/_runtime/common/error/frontend.js +7 -15
- package/libx/_runtime/common/generic/auth/capabilities.js +59 -0
- package/libx/_runtime/common/generic/auth/constants.js +20 -0
- package/libx/_runtime/common/generic/auth/expand.js +54 -0
- package/libx/_runtime/common/generic/auth/index.js +32 -0
- package/libx/_runtime/common/generic/auth/insertOnly.js +15 -0
- package/libx/_runtime/common/generic/auth/readOnly.js +26 -0
- package/libx/_runtime/common/generic/auth/requires.js +34 -0
- package/libx/_runtime/common/generic/auth/restrict.js +296 -0
- package/libx/_runtime/common/generic/auth/utils.js +213 -0
- package/libx/_runtime/common/generic/crud.js +8 -6
- package/libx/_runtime/common/generic/etag.js +1 -1
- package/libx/_runtime/common/generic/input.js +35 -35
- package/libx/_runtime/common/generic/sorting.js +2 -3
- package/libx/_runtime/common/generic/temporal.js +2 -2
- package/libx/_runtime/common/i18n/messages.properties +1 -1
- package/libx/_runtime/common/toggles/handler.js +21 -0
- package/libx/_runtime/common/utils/copy.js +10 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +100 -29
- package/libx/_runtime/common/utils/csn.js +63 -1
- package/libx/_runtime/common/utils/dollar.js +10 -1
- package/libx/_runtime/common/utils/draft.js +46 -7
- package/libx/_runtime/common/utils/entityFromCqn.js +13 -9
- package/libx/_runtime/common/utils/extensibilityUtils.js +18 -0
- package/libx/_runtime/common/utils/foreignKeyPropagations.js +88 -104
- package/libx/_runtime/common/utils/generateOnCond.js +4 -1
- package/libx/_runtime/common/utils/quotingStyles.js +2 -0
- package/libx/_runtime/common/utils/resolveStructured.js +25 -9
- package/libx/_runtime/common/utils/resolveView.js +4 -1
- package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -16
- package/libx/_runtime/common/utils/structured.js +33 -37
- package/libx/_runtime/common/utils/template.js +17 -8
- package/libx/_runtime/common/utils/templateProcessor.js +28 -28
- package/libx/_runtime/db/data-conversion/post-processing.js +118 -417
- package/libx/_runtime/db/expand/expandCQNToJoin.js +45 -41
- package/libx/_runtime/db/expand/rawToExpanded.js +29 -8
- package/libx/_runtime/db/generic/index.js +1 -3
- package/libx/_runtime/db/generic/input.js +5 -10
- package/libx/_runtime/db/generic/rewrite.js +5 -2
- package/libx/_runtime/db/generic/structured.js +2 -2
- package/libx/_runtime/db/query/delete.js +2 -2
- package/libx/_runtime/db/query/insert.js +1 -1
- package/libx/_runtime/db/query/update.js +9 -14
- package/libx/_runtime/db/sql-builder/CreateBuilder.js +4 -3
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +14 -1
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +3 -2
- package/libx/_runtime/db/sql-builder/dataTypes.js +3 -3
- package/libx/_runtime/db/utils/columns.js +3 -3
- package/libx/_runtime/db/utils/normalizeTimeData.js +2 -2
- package/libx/_runtime/db/utils/propagateForeignKeys.js +6 -2
- package/libx/_runtime/extensibility/mps/index.js +5 -0
- package/libx/_runtime/extensibility/mps/service.js +111 -0
- package/libx/_runtime/extensibility/mps/tar.js +42 -0
- package/libx/_runtime/extensibility/mps/utils.js +11 -0
- package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformREAD.js +0 -0
- package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformRESULT.js +17 -5
- package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformWRITE.js +1 -0
- package/libx/_runtime/extensibility/uiflex/index.js +54 -0
- package/libx/_runtime/extensibility/uiflex/service.js +276 -0
- package/libx/_runtime/{fiori → extensibility}/uiflex/utils.js +22 -7
- package/libx/_runtime/fiori/generic/activate.js +2 -2
- package/libx/_runtime/fiori/generic/before.js +4 -4
- package/libx/_runtime/fiori/generic/new.js +3 -3
- package/libx/_runtime/fiori/generic/patch.js +1 -1
- package/libx/_runtime/fiori/generic/read.js +58 -66
- package/libx/_runtime/fiori/generic/readOverDraft.js +71 -16
- package/libx/_runtime/fiori/utils/handler.js +6 -13
- package/libx/_runtime/fiori/utils/where.js +6 -5
- package/libx/_runtime/hana/Service.js +4 -10
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +1 -1
- package/libx/_runtime/hana/driver.js +2 -2
- package/libx/_runtime/hana/execute.js +27 -74
- package/libx/_runtime/hana/pool.js +1 -1
- package/libx/_runtime/hana/streaming.js +2 -1
- package/libx/_runtime/index.js +6 -6
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +5 -21
- package/libx/_runtime/messaging/Outbox.js +2 -2
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +4 -14
- package/libx/_runtime/messaging/common-utils/connections.js +5 -7
- package/libx/_runtime/messaging/common-utils/normalizeIncomingMessage.js +30 -0
- package/libx/_runtime/messaging/enterprise-messaging-shared.js +2 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +36 -30
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +19 -12
- package/libx/_runtime/messaging/enterprise-messaging.js +8 -8
- package/libx/_runtime/messaging/file-based.js +5 -5
- package/libx/_runtime/messaging/message-queuing.js +14 -12
- package/libx/_runtime/messaging/outbox/utils.js +18 -19
- package/libx/_runtime/messaging/redis-messaging.js +91 -0
- package/libx/_runtime/messaging/service.js +8 -6
- package/libx/_runtime/remote/Service.js +44 -8
- package/libx/_runtime/remote/utils/client.js +20 -13
- package/libx/_runtime/remote/utils/data.js +11 -11
- package/libx/_runtime/sqlite/Service.js +6 -9
- package/libx/_runtime/sqlite/customBuilder/CustomFunctionBuilder.js +5 -2
- package/libx/_runtime/types/api.js +10 -2
- package/libx/common/utils/ucsn.js +109 -0
- package/libx/gql/resolvers/crud/update.js +5 -0
- package/libx/gql/resolvers/parse/ast2cqn/columns.js +3 -1
- package/libx/gql/schema/typeDefMap.js +2 -2
- package/libx/odata/afterburner.js +110 -16
- package/libx/odata/grammar.pegjs +9 -1
- package/libx/odata/parseToCqn.js +39 -0
- package/libx/odata/parser.js +1 -1
- package/libx/rest/RestAdapter.js +9 -1
- package/libx/rest/middleware/input.js +54 -0
- package/libx/rest/middleware/operation.js +14 -1
- package/libx/rest/middleware/parse.js +11 -7
- package/package.json +1 -1
- package/server.js +34 -19
- package/srv/audit-log.cds +2 -2
- package/srv/flex.cds +8 -2
- package/srv/flex.js +1 -1
- package/srv/mps.cds +23 -0
- package/srv/mps.js +1 -0
- package/libx/_runtime/auth/strategies/utils/uaa.js +0 -21
- package/libx/_runtime/common/generic/auth.js +0 -874
- package/libx/_runtime/common/toggles/alpha.js +0 -43
- package/libx/_runtime/db/generic/arrayed.js +0 -33
- package/libx/_runtime/fiori/uiflex/index.js +0 -35
- package/libx/_runtime/fiori/uiflex/service.js +0 -150
- package/libx/rest/utils/data.js +0 -60
|
@@ -12,53 +12,42 @@ module.exports = (srv) => {
|
|
|
12
12
|
|
|
13
13
|
const add_handler_for = (srv, def) => {
|
|
14
14
|
const event = def.name.match(/\w*$/)[0]
|
|
15
|
+
|
|
16
|
+
// Use existing methods as handler implementations
|
|
15
17
|
const method = srv[event]
|
|
16
18
|
if (method) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
srv.on (event, ({data}) => {
|
|
19
|
+
if (method._is_stub || method.name in srv.__proto__.__proto__) return
|
|
20
|
+
srv.on (event, function ({params,data}) {
|
|
20
21
|
const args = []; if (def.parent) args.push (def.parent)
|
|
22
|
+
for (let p in params) args.push(params[p])
|
|
21
23
|
for (let p in data) args.push(data[p])
|
|
22
|
-
return method.apply (
|
|
24
|
+
return method.apply (this,args)
|
|
23
25
|
})
|
|
24
|
-
|
|
25
|
-
} else {
|
|
26
|
-
// add method to emit request
|
|
27
|
-
const method = srv[event] = function (...args) {
|
|
28
|
-
const [$] = args, target = this.entities [ $ && $.name ? $.name.match(/\w*$/)[0] : $ ]
|
|
29
|
-
const data = {}
|
|
30
|
-
if (target) { //> it's a bound action
|
|
31
|
-
def = target.actions[event]; args.shift()
|
|
32
|
-
// In case of bound actions, first argument(s) are expected to be the target's primary key,
|
|
33
|
-
// which we need to fill in to named properties in data
|
|
34
|
-
// object variant of keys, ensure keys are present in args[0] because of complex param
|
|
35
|
-
if (typeof args[0] === 'object' && Object.keys(target.keys).every(k => k in args[0])) {
|
|
36
|
-
const keys = args.shift()
|
|
37
|
-
for (const p in target.keys) {
|
|
38
|
-
data[p] = keys[p]
|
|
39
|
-
}
|
|
40
|
-
} else { // positional
|
|
41
|
-
for (let p in target.keys) {
|
|
42
|
-
data[p] = args.shift()
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// object variant of params, ensure at least one param is present in args[0]
|
|
49
|
-
// REVISIT: still not bullet proof, but parameters might be optional
|
|
50
|
-
if (def.params) {
|
|
51
|
-
if (args[0] !== null && typeof args[0] === 'object' && args.length === 1 && Object.keys(def.params).some(p => p in args[0])) {
|
|
52
|
-
const params = args.shift()
|
|
53
|
-
for (const p in def.params) data[p] = params[p]
|
|
54
|
-
} else { // positional
|
|
55
|
-
for (let p in def.params) data[p] = args.shift()
|
|
56
|
-
}
|
|
57
|
-
}
|
|
26
|
+
}
|
|
58
27
|
|
|
59
|
-
|
|
60
|
-
|
|
28
|
+
// Add stub methods to send request via typed API
|
|
29
|
+
const stub = srv[event] = function (...args) {
|
|
30
|
+
const req = { event, data:{} }, $ = args[0]
|
|
31
|
+
const target = this.entities [ $ && $.name ? $.name.match(/\w*$/)[0] : $ ]
|
|
32
|
+
if (target) { //> bound action/function?
|
|
33
|
+
req.target = target; args.shift() // first argument is the target entity name
|
|
34
|
+
req.params = [ args.shift() ] // second argument is the target's primary key
|
|
61
35
|
}
|
|
62
|
-
|
|
36
|
+
const {params} = target ? target.actions[event] : def
|
|
37
|
+
if (params) req.data = _named(args,params) || _positional(args,params)
|
|
38
|
+
return this.send (req)
|
|
63
39
|
}
|
|
40
|
+
stub._is_stub = true
|
|
64
41
|
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
const _named = (args, declared) => {
|
|
45
|
+
if (args.length > 1) return
|
|
46
|
+
const a = args[0]
|
|
47
|
+
if (! a || typeof a !== 'object') return
|
|
48
|
+
if (Object.keys(a).every (k => k in declared)) return a
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const _positional = (args, declared) => Object.keys(declared).reduce (
|
|
52
|
+
(data,k,i) => { data[k] = args[i]; return data }, {}
|
|
53
|
+
)
|
package/lib/serve/Transaction.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const cds = require('../index'), { cds_tx_protection } = cds.env.features
|
|
2
2
|
const EventContext = require('../req/context')
|
|
3
|
+
class RootContext extends EventContext {}
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* This is the implementation of the `srv.tx(req)` method. It constructs
|
|
@@ -28,12 +30,10 @@ module.exports = function tx (ctx,fn) { const srv = this
|
|
|
28
30
|
// `ctx` is a plain context object or undefined
|
|
29
31
|
if (ctx) { // REVISIT: This is for compatibility with AFC only
|
|
30
32
|
if (ctx._txed_before) return NestedTransaction.for (srv, ctx._txed_before)
|
|
31
|
-
else {
|
|
32
|
-
|
|
33
|
-
return RootTransaction.for (srv, ctx._txed_before)
|
|
34
|
-
}
|
|
33
|
+
else Object.defineProperty(ctx, '_txed_before', { value: RootContext.for(ctx) }) // > must be non-enumerable
|
|
34
|
+
return RootTransaction.for (srv, ctx._txed_before)
|
|
35
35
|
}
|
|
36
|
-
return RootTransaction.for (srv,
|
|
36
|
+
return RootTransaction.for (srv, RootContext.for(ctx))
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
|
|
@@ -174,8 +174,11 @@ const _begin = async function (req) {
|
|
|
174
174
|
return this.ready = this.__proto__.dispatch.call (this,req)
|
|
175
175
|
// Protection against unintended tx.run() after tx.commit/rollback()
|
|
176
176
|
if (typeof this.ready === 'string' || !this.ready && this.context._done) {
|
|
177
|
-
if (cds_tx_protection)
|
|
178
|
-
else
|
|
177
|
+
if (!cds_tx_protection) this.ready = this.begin() // compatibiliy to former behavior, which allowed tx.run() after commit/rollback
|
|
178
|
+
else throw cds.error (
|
|
179
|
+
`Transaction is ${this.ready || this.context._done}, no subsequent .run allowed, without prior .begin`,
|
|
180
|
+
{ code: 'TRANSACTION_CLOSED' }
|
|
181
|
+
)
|
|
179
182
|
}
|
|
180
183
|
else if (!this.ready) this.ready = this.begin()
|
|
181
184
|
await this.ready
|
package/lib/serve/adapters.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const lib = require('../../libx/_runtime')
|
|
2
2
|
const registry = {
|
|
3
|
-
rest: lib.to.
|
|
3
|
+
rest: lib.to.old_rest,
|
|
4
|
+
new_rest: lib.to.new_rest,
|
|
4
5
|
odata: lib.to.odata_v4,
|
|
5
6
|
odata_v2: lib.to.odata_v4,
|
|
6
7
|
odata_v4: lib.to.odata_v4,
|
|
@@ -11,6 +12,7 @@ const registry = {
|
|
|
11
12
|
class ProtocolAdapter {
|
|
12
13
|
|
|
13
14
|
static at (protocol) {
|
|
15
|
+
if (protocol === 'rest' && global.cds.env.features.rest_new_adapter) protocol = 'new_rest'
|
|
14
16
|
const factory = registry[protocol]; if (factory) return factory
|
|
15
17
|
else throw new Error (`Service protocol ${protocol} is not supported`)
|
|
16
18
|
}
|
|
@@ -30,12 +32,12 @@ class ProtocolAdapter {
|
|
|
30
32
|
/**
|
|
31
33
|
* Mounts the adapter to an express app.
|
|
32
34
|
*/
|
|
33
|
-
in (app) {
|
|
34
|
-
const srv = this.service
|
|
35
|
+
in (app, at) {
|
|
36
|
+
const srv = this.service, path = at || srv.path
|
|
35
37
|
lib.perf (app)
|
|
36
38
|
lib.auth (srv, app, srv.options)
|
|
37
|
-
app.use (
|
|
38
|
-
app.use (
|
|
39
|
+
app.use (path+'/webapp/', (_,res)=> res.sendStatus(404))
|
|
40
|
+
app.use (path, this)
|
|
39
41
|
return srv
|
|
40
42
|
}
|
|
41
43
|
|
package/lib/serve/index.js
CHANGED
|
@@ -6,8 +6,14 @@ const _ready = Symbol(), _pending = cds.services._pending || {}
|
|
|
6
6
|
/** @param som - a service name or a model (name or csn) */
|
|
7
7
|
function cds_serve (som, _options) { // NOSONAR
|
|
8
8
|
|
|
9
|
-
if (
|
|
10
|
-
|
|
9
|
+
if (som && typeof som === 'object' && !is_csn(som)) {
|
|
10
|
+
[som,_options] = [undefined,
|
|
11
|
+
som._is_service_instance ? { service:som, from:'*' } :
|
|
12
|
+
som._is_service_class ? { service:som, from:'*' } :
|
|
13
|
+
som
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
else if (Array.isArray(som) && som.length === 1) som = som[0]
|
|
11
17
|
const o = {..._options} // we must not modify inbound data
|
|
12
18
|
|
|
13
19
|
// 1) Use fluent API to fill in remaining options...
|
|
@@ -40,6 +46,11 @@ function cds_serve (som, _options) { // NOSONAR
|
|
|
40
46
|
// 4) Pass 1: Construct service provider instances...
|
|
41
47
|
const all=[], provided = loaded.then (csn => { // NOSONAR
|
|
42
48
|
|
|
49
|
+
// Shortcut for directly passed service instances
|
|
50
|
+
if (o.service && o.service._is_service_instance) {
|
|
51
|
+
return all.push (o.service)
|
|
52
|
+
}
|
|
53
|
+
|
|
43
54
|
// Shortcut for directly passed service classes
|
|
44
55
|
if (o.service && o.service._is_service_class) {
|
|
45
56
|
const Service = o.service, d = { name: o.service.name }
|
|
@@ -47,19 +58,19 @@ function cds_serve (som, _options) { // NOSONAR
|
|
|
47
58
|
}
|
|
48
59
|
|
|
49
60
|
// Get relevant service definitions from model...
|
|
50
|
-
let {services} = csn = cds.
|
|
51
|
-
|
|
52
|
-
if (
|
|
61
|
+
let {services} = csn = cds.compile.for.nodejs (csn)
|
|
62
|
+
const required = cds.requires
|
|
63
|
+
if (o.service && o.service !== 'all') {
|
|
53
64
|
// skip services not chosen by o.service, if specified
|
|
54
|
-
|
|
55
|
-
services = services.filter (s => s.name.endsWith
|
|
56
|
-
if (!services.length) throw cds.error (`No such service: '${
|
|
65
|
+
const specified = o.service.split(/\s*,\s*/).map (s => required[s] && required[s].service || s )
|
|
66
|
+
services = services.filter (s => specified.some (n => s.name.endsWith(n)))
|
|
67
|
+
if (!services.length) throw cds.error (`No such service: '${o.service}'`)
|
|
57
68
|
}
|
|
58
69
|
services = services.filter (d => !(
|
|
59
70
|
// skip all services marked to be ignored
|
|
60
71
|
d['@cds.ignore'] || d['@cds.serve.ignore'] ||
|
|
61
72
|
// skip external services, unless asked to mock them and unbound
|
|
62
|
-
|
|
73
|
+
required[d.name] && (!o.mocked || required[d.name].credentials)
|
|
63
74
|
))
|
|
64
75
|
if (services.length > 1 && o.at) {
|
|
65
76
|
throw cds.error `You cannot specify 'path' for multiple services`
|
|
@@ -73,11 +84,12 @@ function cds_serve (som, _options) { // NOSONAR
|
|
|
73
84
|
// Note: doing that in a second pass guarantees all own services are in
|
|
74
85
|
// cds.services, so they'll be found when they cds.connect to each others.
|
|
75
86
|
let ready = provided.then (()=> Promise.all (all.map (async srv => {
|
|
87
|
+
if (o.service && o.service._is_service_instance) return srv
|
|
76
88
|
srv.init && await srv.prepend (srv.init)
|
|
77
89
|
srv.options.impl && await srv.prepend (srv.options.impl)
|
|
78
90
|
cds.services[srv.name] = cds.service.paths[srv.path] = srv
|
|
79
91
|
cds.service.providers.push (srv)
|
|
80
|
-
srv[_ready](srv)
|
|
92
|
+
if (srv[_ready]) srv[_ready](srv)
|
|
81
93
|
return srv
|
|
82
94
|
})))
|
|
83
95
|
|
|
@@ -93,7 +105,7 @@ function cds_serve (som, _options) { // NOSONAR
|
|
|
93
105
|
|
|
94
106
|
for (let each of all) {
|
|
95
107
|
each._edm = edms[each.name]
|
|
96
|
-
ProtocolAdapter.serve(each).in(app)
|
|
108
|
+
ProtocolAdapter.serve(each,o.to).in(app)
|
|
97
109
|
if (!o.silent) cds.emit ('serving',each)
|
|
98
110
|
}
|
|
99
111
|
})
|
|
@@ -105,7 +117,7 @@ function cds_serve (som, _options) { // NOSONAR
|
|
|
105
117
|
if (all.length === 0) return resolve()
|
|
106
118
|
let response={}
|
|
107
119
|
for (let each of all) {
|
|
108
|
-
response[each.name] = !each.definition ? each : ProtocolAdapter.serve(each).asRouter()
|
|
120
|
+
response[each.name] = !each.definition ? each : ProtocolAdapter.serve(each,o.to).asRouter()
|
|
109
121
|
}
|
|
110
122
|
if (all.length === 1 && all[0].name.endsWith (o.service)) {
|
|
111
123
|
response = Object.assign (all[0], response)
|
package/lib/utils/data.js
CHANGED
package/lib/utils/index.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
const cwd = process.env._original_cwd || process.cwd()
|
|
2
2
|
const path = require ('path'), { dirname, join, resolve, sep, relative } = path
|
|
3
|
-
const fs = require
|
|
4
|
-
const rw = fs.constants.R_OK | fs.constants.W_OK
|
|
3
|
+
const fs = require('fs')
|
|
5
4
|
const cds = global.cds
|
|
6
5
|
|
|
7
|
-
module.exports = exports = {
|
|
8
|
-
get
|
|
6
|
+
const all = module.exports = exports = { ...fs,
|
|
7
|
+
get inspect() { return $set (this, 'inspect', require('util').inspect) },
|
|
8
|
+
get uuid() { return $set (this, 'uuid', require('@sap/cds-foss').uuid) },
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
exports.
|
|
11
|
+
exports.fs = all
|
|
12
12
|
exports.path = path
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
exports.local = (file) => '.' + sep + relative(cwd,file)
|
|
14
15
|
|
|
15
16
|
exports.readdir = async function (x) {
|
|
16
17
|
const d = resolve (cds.root,x)
|
|
@@ -54,45 +55,41 @@ exports.read = async function read (file, _encoding) {
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
exports.write = function write (file, data, o) {
|
|
57
|
-
if (arguments.length === 1) return {to:
|
|
58
|
-
if (typeof data === 'object'
|
|
58
|
+
if (arguments.length === 1) return {to:(...path) => write(join(...path),file)}
|
|
59
|
+
if (typeof data === 'object' && !Buffer.isBuffer(data))
|
|
60
|
+
data = JSON.stringify(data, null, ' '.repeat(o && o.spaces))
|
|
59
61
|
const f = resolve (cds.root,file)
|
|
60
|
-
return mkdirp (dirname(f)).then (()=> fs.promises.writeFile (f,data))
|
|
62
|
+
return mkdirp (dirname(f)).then (()=> fs.promises.writeFile (f,data,o))
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
exports.mkdirp = async function
|
|
64
|
-
const d = resolve (cds.root
|
|
65
|
-
|
|
66
|
-
await mkdirp (dirname(d))
|
|
67
|
-
try { await fs.promises.mkdir(d) }
|
|
68
|
-
catch(e) { if (e.code !== 'EEXIST' /*may still happen with parallel calls*/) throw e }
|
|
69
|
-
}
|
|
65
|
+
exports.mkdirp = async function (...path) {
|
|
66
|
+
const d = resolve (cds.root,...path)
|
|
67
|
+
await fs.promises.mkdir (d,{recursive:true})
|
|
70
68
|
return d
|
|
71
69
|
}
|
|
72
70
|
|
|
73
|
-
exports.
|
|
74
|
-
const
|
|
75
|
-
return
|
|
71
|
+
exports.rmdir = (...path) => {
|
|
72
|
+
const d = resolve (cds.root,...path)
|
|
73
|
+
return (fs.promises.rm || fs.promises.rmdir) (d, {recursive:true})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
exports.rimraf = (...path) => {
|
|
77
|
+
const d = resolve (cds.root,...path)
|
|
78
|
+
return (fs.promises.rm || fs.promises.rmdir) (d, {recursive:true,force:true})
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
exports.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const entries = await readdir(d)
|
|
82
|
-
await Promise.all (entries.map (async each => {
|
|
83
|
-
const e = join (d,each)
|
|
84
|
-
const ls = await lstat(e)
|
|
85
|
-
return ls.isDirectory() ? rimraf(e) : unlink(e)
|
|
86
|
-
}))
|
|
87
|
-
return rmdir(d)
|
|
81
|
+
exports.rm = async function rm (x) {
|
|
82
|
+
const y = resolve (cds.root,x)
|
|
83
|
+
return (fs.promises.rm || fs.promises.unlink)(y)
|
|
88
84
|
}
|
|
89
85
|
|
|
90
86
|
exports.copy = async function copy (x,y) {
|
|
91
87
|
const src = resolve (cds.root,x)
|
|
92
88
|
const dst = resolve (cds.root,y)
|
|
89
|
+
if (fs.promises.cp) return fs.promises.cp (src,dst,{recursive:true})
|
|
93
90
|
await mkdirp (dirname(dst))
|
|
94
91
|
if (isdir(src)) {
|
|
95
|
-
const entries = await readdir(src)
|
|
92
|
+
const entries = await fs.promises.readdir(src)
|
|
96
93
|
return Promise.all (entries.map (async each => {
|
|
97
94
|
const e = join (src,each)
|
|
98
95
|
const f = join (src,each)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
|
|
4
|
+
const cds = require('../../../libx/_runtime/cds')
|
|
5
|
+
const { packArchive, packArchiveCLI, unpackArchive, unpackArchiveCLI } = require('./tar')
|
|
6
|
+
const { exists } = require('./utils')
|
|
7
|
+
|
|
8
|
+
// use tar command line interface
|
|
9
|
+
const TAR_CLI = true
|
|
10
|
+
const TEMP_DIR = fs.realpathSync(require('os').tmpdir())
|
|
11
|
+
|
|
12
|
+
const findCsvFiles = async (folder, deep = false) => {
|
|
13
|
+
const files = await fs.promises.readdir(folder)
|
|
14
|
+
const result = []
|
|
15
|
+
|
|
16
|
+
for (const file of files) {
|
|
17
|
+
const filePath = path.join(folder, file)
|
|
18
|
+
if (deep && (await fs.promises.stat(filePath)).isDirectory()) {
|
|
19
|
+
const files = await findCsvFiles(filePath)
|
|
20
|
+
result.push(...files)
|
|
21
|
+
} else {
|
|
22
|
+
if (path.extname(file) === '.csv') {
|
|
23
|
+
result.push(filePath)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return result
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const collectCsvFiles = async sources => {
|
|
32
|
+
const folders = sources.map(file => path.dirname(file))
|
|
33
|
+
const uniqueFolders = [...new Set(folders)].filter(folder => !/node_modules/.test(folder))
|
|
34
|
+
const db = (cds.env.folders && cds.env.folders.db) || 'db/'
|
|
35
|
+
let dbFolder = path.join(global.cds.root, db)
|
|
36
|
+
if (dbFolder.endsWith('/') || dbFolder.endsWith('\\')) dbFolder = dbFolder.slice(0, -1)
|
|
37
|
+
if (!uniqueFolders.includes(dbFolder)) uniqueFolders.push(dbFolder)
|
|
38
|
+
|
|
39
|
+
const result = []
|
|
40
|
+
for (const folder of uniqueFolders) {
|
|
41
|
+
const dataPath = path.join(folder, 'data')
|
|
42
|
+
const dataFiles = (await exists(dataPath)) ? await findCsvFiles(dataPath) : []
|
|
43
|
+
const csvPath = path.join(folder, 'csv')
|
|
44
|
+
const csvFiles = (await exists(csvPath)) ? await findCsvFiles(csvPath) : []
|
|
45
|
+
result.push(...dataFiles, ...csvFiles)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return result
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const packTarArchive = async (files, root, flat = false, cli = true) => {
|
|
52
|
+
let tgzBuffer, temp
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
temp = await fs.promises.mkdtemp(`${TEMP_DIR}${path.sep}tar-`)
|
|
56
|
+
if (flat) {
|
|
57
|
+
const files_ = []
|
|
58
|
+
for (const file of files) {
|
|
59
|
+
const destination = path.join(temp, path.basename(file))
|
|
60
|
+
await fs.promises.copyFile(file, destination)
|
|
61
|
+
files_.push(destination)
|
|
62
|
+
}
|
|
63
|
+
files = files_
|
|
64
|
+
root = temp
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const relativeFiles = files.map(file => path.relative(root, file))
|
|
68
|
+
if (cli) {
|
|
69
|
+
const output = path.relative(root, path.join(temp, `${cds.utils.uuid()}.tgz`))
|
|
70
|
+
tgzBuffer = await packArchiveCLI(relativeFiles, root, output)
|
|
71
|
+
} else {
|
|
72
|
+
tgzBuffer = await packArchive(relativeFiles, root)
|
|
73
|
+
}
|
|
74
|
+
} finally {
|
|
75
|
+
if (await exists(temp)) {
|
|
76
|
+
await (fs.promises.rm || fs.promises.rmdir)(temp, { recursive: true, force: true })
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return tgzBuffer
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const unpackTarArchive = async (buffer, folder, cli = true) => {
|
|
84
|
+
const temp = await fs.promises.mkdtemp(`${TEMP_DIR}${path.sep}tar-`)
|
|
85
|
+
const tgz = path.join(temp, 'resources.tgz')
|
|
86
|
+
await fs.promises.writeFile(tgz, buffer, 'binary')
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
cli ? await unpackArchiveCLI(tgz, folder) : await unpackArchive(tgz, folder)
|
|
90
|
+
} finally {
|
|
91
|
+
if (await exists(temp)) await (fs.promises.rm || fs.promises.rmdir)(temp, { recursive: true, force: true })
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = {
|
|
96
|
+
TAR_CLI,
|
|
97
|
+
findCsvFiles,
|
|
98
|
+
collectCsvFiles,
|
|
99
|
+
packTarArchive,
|
|
100
|
+
unpackTarArchive
|
|
101
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const tar = require('tar')
|
|
4
|
+
const exec = require('child_process').exec
|
|
5
|
+
|
|
6
|
+
const _createArchive = (files, root) => {
|
|
7
|
+
return tar.c(
|
|
8
|
+
{
|
|
9
|
+
gzip: true,
|
|
10
|
+
preservePaths: false,
|
|
11
|
+
cwd: root
|
|
12
|
+
},
|
|
13
|
+
files
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const _createArchiveCLI = (files, root, output) => {
|
|
18
|
+
const cmd = 'cd ' + root + ' && tar -czf ' + output + ' ' + files.join(' ')
|
|
19
|
+
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
exec(cmd, err => {
|
|
22
|
+
if (err) reject(err)
|
|
23
|
+
else resolve()
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const packArchive = (files, root) => {
|
|
29
|
+
_createArchive(files, root)
|
|
30
|
+
const stream = _createArchive(files, root)
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const chunks = []
|
|
33
|
+
stream.on('data', data => chunks.push(data))
|
|
34
|
+
stream.on('error', error => reject(error))
|
|
35
|
+
stream.on('end', () => {
|
|
36
|
+
resolve(Buffer.concat(chunks))
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const packArchiveCLI = async (files, root, output) => {
|
|
42
|
+
await _createArchiveCLI(files, root, output)
|
|
43
|
+
|
|
44
|
+
return fs.promises.readFile(path.join(root, output))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const unpackArchive = async (tgz, folder) => {
|
|
48
|
+
await tar.x({
|
|
49
|
+
file: tgz,
|
|
50
|
+
gzip: true,
|
|
51
|
+
C: folder
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const unpackArchiveCLI = async (tgz, folder) => {
|
|
56
|
+
const cmd = 'tar -xzf ' + tgz + ' -C ' + folder
|
|
57
|
+
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
exec(cmd, err => {
|
|
60
|
+
if (err) reject(err)
|
|
61
|
+
else resolve()
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {
|
|
67
|
+
packArchive,
|
|
68
|
+
packArchiveCLI,
|
|
69
|
+
unpackArchive,
|
|
70
|
+
unpackArchiveCLI
|
|
71
|
+
}
|
|
@@ -15,23 +15,23 @@ module.exports = class AuditLogService extends OutboxService {
|
|
|
15
15
|
// call OutboxService's init, which handles outboxing
|
|
16
16
|
await super.init()
|
|
17
17
|
|
|
18
|
-
// register handlers
|
|
19
|
-
this.on('dataAccessLog', this.dataAccessLog)
|
|
20
|
-
this.on('dataModificationLog', this.dataModificationLog)
|
|
21
|
-
this.on('securityLog', this.securityLog)
|
|
22
|
-
this.on('configChangeLog', this.configChangeLog)
|
|
23
|
-
|
|
24
18
|
// connect to audit log service
|
|
25
|
-
// REVISIT for GA: throw error on connect issue instead of warn and this.ready?
|
|
26
19
|
this.alc = await v2utils.connect(this.options.credentials)
|
|
27
|
-
|
|
20
|
+
|
|
21
|
+
// register handlers, if connected
|
|
22
|
+
if (this.alc) {
|
|
23
|
+
this.on('dataAccessLog', this._dataAccessLog)
|
|
24
|
+
this.on('dataModificationLog', this._dataModificationLog)
|
|
25
|
+
this.on('securityLog', this._securityLog)
|
|
26
|
+
this.on('configChangeLog', this._configChangeLog)
|
|
27
|
+
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
async emit(first, second) {
|
|
31
31
|
const { event, data } = typeof first === 'object' ? first : { event: first, data: second }
|
|
32
32
|
if (!this.options.outbox) return this.send(event, data)
|
|
33
33
|
|
|
34
|
-
if (this
|
|
34
|
+
if (this[event]) {
|
|
35
35
|
try {
|
|
36
36
|
// this will open a new tx -> preserve user
|
|
37
37
|
await super.send(new cds.Request({ method: event, data, user: cds.context.user }))
|
|
@@ -45,14 +45,34 @@ module.exports = class AuditLogService extends OutboxService {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
async send(event, data) {
|
|
48
|
-
if (this
|
|
48
|
+
if (this[event]) return super.send(event, data)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
* api (await AuditLogService.<event>(data))
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
async dataAccessLog(data) {
|
|
56
|
+
return super.send('dataAccessLog', data)
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
async
|
|
52
|
-
|
|
59
|
+
async dataModificationLog(data) {
|
|
60
|
+
return super.send('dataModificationLog', data)
|
|
61
|
+
}
|
|
53
62
|
|
|
54
|
-
|
|
63
|
+
async securityLog(data) {
|
|
64
|
+
return super.send('securityLog', data)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async configChangeLog(data) {
|
|
68
|
+
return super.send('configChangeLog', data)
|
|
69
|
+
}
|
|
55
70
|
|
|
71
|
+
/*
|
|
72
|
+
* impl
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
async _dataAccessLog({ data: { accesses } }) {
|
|
56
76
|
const { tenant, user } = _getTenantAndUser()
|
|
57
77
|
|
|
58
78
|
// build the logs
|
|
@@ -73,11 +93,7 @@ module.exports = class AuditLogService extends OutboxService {
|
|
|
73
93
|
}
|
|
74
94
|
|
|
75
95
|
// REVISIT: modification.action not used in auditlog v2
|
|
76
|
-
async
|
|
77
|
-
const modifications = arg.modifications || arg.data.modifications
|
|
78
|
-
|
|
79
|
-
if (!this.ready) throw new Error('AuditLogService not connected')
|
|
80
|
-
|
|
96
|
+
async _dataModificationLog({ data: { modifications } }) {
|
|
81
97
|
const { tenant, user } = _getTenantAndUser()
|
|
82
98
|
|
|
83
99
|
// build the logs
|
|
@@ -97,15 +113,7 @@ module.exports = class AuditLogService extends OutboxService {
|
|
|
97
113
|
}
|
|
98
114
|
}
|
|
99
115
|
|
|
100
|
-
async
|
|
101
|
-
let { action, data } = arg
|
|
102
|
-
if (arg.data && arg.data.action) {
|
|
103
|
-
action = arg.data.action
|
|
104
|
-
data = arg.data.data
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (!this.ready) throw new Error('AuditLogService not connected')
|
|
108
|
-
|
|
116
|
+
async _securityLog({ data: { action, data } }) {
|
|
109
117
|
let { tenant, user } = _getTenantAndUser()
|
|
110
118
|
|
|
111
119
|
// cds.context may not be proper on auth-related errors -> try to extract from data
|
|
@@ -132,18 +140,7 @@ module.exports = class AuditLogService extends OutboxService {
|
|
|
132
140
|
}
|
|
133
141
|
|
|
134
142
|
// REVISIT: action and success not used in auditlog v2
|
|
135
|
-
async
|
|
136
|
-
let { action, success, configurations } = arg
|
|
137
|
-
if (arg.data) {
|
|
138
|
-
// eslint-disable-next-line no-unused-vars
|
|
139
|
-
action = arg.data.action
|
|
140
|
-
// eslint-disable-next-line no-unused-vars
|
|
141
|
-
success = arg.data.success
|
|
142
|
-
configurations = arg.data.configurations
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (!this.ready) throw new Error('AuditLogService not connected')
|
|
146
|
-
|
|
143
|
+
async _configChangeLog({ data: { action, success, configurations } }) {
|
|
147
144
|
const { tenant, user } = _getTenantAndUser()
|
|
148
145
|
|
|
149
146
|
// build the logs
|
|
@@ -13,7 +13,7 @@ const {
|
|
|
13
13
|
resolveDataSubjectPromises
|
|
14
14
|
} = require('./utils')
|
|
15
15
|
|
|
16
|
-
let
|
|
16
|
+
let auditLogService
|
|
17
17
|
|
|
18
18
|
const _processorFnAccess = (accessLogs, model, req) => {
|
|
19
19
|
return ({ row, key, element, plain }) => {
|
|
@@ -70,15 +70,14 @@ const _getDataAccessLogs = (data, req, tx) => {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
const auditAccessHandler = async function (data, req) {
|
|
73
|
-
|
|
74
|
-
if (!als.ready) return
|
|
73
|
+
auditLogService = auditLogService || (await cds.connect.to('audit-log'))
|
|
75
74
|
|
|
76
75
|
const accessLogs = _getDataAccessLogs(data, req, this)
|
|
77
76
|
// REVISIT: a function called resolveDataSubjectPromises should not also convert an object to an array
|
|
78
77
|
let accesses = await resolveDataSubjectPromises(accessLogs)
|
|
79
78
|
accesses = accesses.filter(ele => ele.attributes.length)
|
|
80
79
|
|
|
81
|
-
if (accesses.length) await
|
|
80
|
+
if (accesses.length) await auditLogService.emit('dataAccessLog', { accesses })
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
module.exports = {
|