@sap/cds 5.9.8 → 6.0.3
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 +277 -20
- package/apis/services.d.ts +1 -1
- package/app/fiori/preview.js +2 -6
- package/app/index.js +3 -3
- package/bin/build/buildTaskEngine.js +17 -15
- package/bin/build/buildTaskFactory.js +29 -19
- package/bin/build/buildTaskHandler.js +27 -11
- package/bin/build/buildTaskProvider.js +2 -4
- package/bin/build/buildTaskProviderFactory.js +11 -16
- package/bin/build/constants.js +14 -6
- package/bin/build/csv-reader.js +2 -1
- package/bin/build/index.js +12 -18
- package/bin/build/provider/buildTaskHandlerEdmx.js +3 -39
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +149 -0
- package/bin/build/provider/buildTaskHandlerInternal.js +2 -3
- package/bin/build/provider/buildTaskProviderInternal.js +108 -239
- package/bin/build/provider/fiori/index.js +2 -2
- package/bin/build/provider/hana/2migration.js +11 -11
- package/bin/build/provider/hana/2tabledata.js +3 -3
- package/bin/build/provider/hana/index.js +89 -99
- package/bin/build/provider/hana/migrationtable.js +4 -3
- package/bin/build/provider/java/index.js +101 -0
- package/bin/build/provider/java-cf/index.js +1 -101
- package/bin/build/provider/mtx/index.js +83 -41
- package/bin/build/provider/mtx/resourcesTarBuilder.js +68 -0
- package/bin/build/provider/mtx-sidecar/index.js +110 -0
- package/bin/build/provider/node-cf/index.js +1 -308
- package/bin/build/provider/nodejs/index.js +189 -0
- package/bin/build/util.js +21 -31
- package/bin/cds.js +5 -3
- package/bin/deploy/to-hana/cfUtil.js +31 -6
- package/bin/deploy/to-hana/gitUtil.js +5 -3
- package/bin/deploy/to-hana/hana.js +15 -13
- package/bin/{build → deploy/to-hana}/mtaUtil.js +10 -9
- package/bin/mtx/in-cds.js +19 -7
- package/bin/serve.js +49 -22
- package/bin/utils/log.js +13 -30
- package/bin/version.js +4 -3
- package/common.cds +61 -16
- package/lib/compile/cdsc.js +3 -2
- package/lib/compile/etc/_localized.js +15 -14
- package/lib/compile/for/drafts.js +3 -4
- package/lib/compile/for/java.js +13 -10
- package/lib/compile/for/nodejs.js +8 -8
- package/lib/compile/for/odata.js +7 -12
- package/lib/compile/for/sql.js +5 -6
- package/lib/compile/index.js +5 -4
- package/lib/compile/load.js +9 -11
- package/lib/compile/minify.js +8 -5
- package/lib/compile/parse.js +4 -2
- package/lib/compile/resolve.js +18 -15
- package/lib/compile/to/edm.js +0 -1
- package/lib/compile/to/gql.js +3 -2
- package/lib/compile/to/json.js +24 -17
- package/lib/connect/bindings.js +3 -2
- package/lib/connect/index.js +5 -5
- package/lib/core/classes.js +74 -2
- package/lib/core/entities.js +52 -3
- package/lib/core/reflect.js +2 -1
- package/lib/deploy.js +10 -8
- package/lib/env/defaults.js +4 -3
- package/lib/env/index.js +71 -31
- package/lib/env/presets.js +1 -14
- package/lib/env/requires.js +71 -20
- package/lib/env/serviceBindings.js +147 -0
- package/lib/i18n/localize.js +22 -23
- package/lib/index.js +148 -144
- package/lib/log/errors.js +55 -12
- package/lib/log/format/kibana.js +1 -1
- package/lib/log/index.js +4 -0
- package/lib/ql/SELECT.js +7 -2
- package/lib/ql/Whereable.js +8 -2
- package/lib/ql/index.js +2 -2
- package/lib/req/assert.js +71 -0
- package/lib/req/cds-context.js +38 -70
- package/lib/req/context.js +34 -21
- package/lib/req/request.js +12 -18
- package/lib/req/response.js +6 -2
- package/lib/req/user.js +30 -22
- package/lib/serve/Service-api.js +17 -12
- package/lib/serve/Service-dispatch.js +5 -9
- package/lib/serve/Service-methods.js +4 -3
- package/lib/serve/Transaction.js +24 -21
- package/lib/serve/adapters.js +15 -5
- package/lib/serve/factory.js +22 -20
- package/lib/serve/index.js +51 -54
- package/lib/utils/axios.js +8 -12
- package/lib/utils/index.js +13 -4
- package/lib/utils/resources/index.js +1 -44
- package/lib/utils/resources/tar.js +2 -1
- package/lib/utils/tests.js +13 -15
- package/libx/_runtime/.eslintrc +1 -1
- package/libx/_runtime/audit/Service.js +6 -4
- package/libx/_runtime/audit/generic/personal/access.js +19 -43
- package/libx/_runtime/audit/generic/personal/index.js +40 -34
- package/libx/_runtime/audit/generic/personal/modification.js +11 -9
- package/libx/_runtime/audit/generic/personal/utils.js +13 -6
- package/libx/_runtime/audit/utils/v2.js +6 -3
- package/libx/_runtime/auth/index.js +71 -66
- package/libx/_runtime/auth/strategies/JWT.js +3 -2
- package/libx/_runtime/auth/strategies/mock.js +54 -53
- package/libx/_runtime/auth/strategies/xssecUtils.js +3 -4
- package/libx/_runtime/auth/strategies/xsuaa.js +3 -2
- package/libx/_runtime/auth/utils.js +2 -15
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +127 -41
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +9 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +93 -73
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +25 -45
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +10 -14
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +9 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +4 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +60 -53
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +21 -26
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +8 -15
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +29 -41
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +13 -13
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/selectToCQN.js +0 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +24 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/EdmEntityContainer.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriHelper.js +4 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/PrimitiveValueDecoder.js +4 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/ValueConverter.js +4 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/validator/ValueValidator.js +5 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/core/ResponseHeaderSetter.js +2 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/DebugSerializingCommand.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/PresetResponseHeadersCommand.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/SerializingCommand.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/SetResponseHeadersCommand.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ContextURLFactory.js +3 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ErrorJsonSerializer.js +3 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/SerializerFactory.js +1 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/TrustedResourceJsonSerializer.js +3 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +36 -25
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +97 -92
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +382 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/oDataConfiguration.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/omitValues.js +5 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +82 -21
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +3 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +91 -69
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +27 -6
- package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +7 -17
- package/libx/_runtime/cds-services/services/Service.js +17 -76
- package/libx/_runtime/cds-services/services/utils/columns.js +6 -4
- package/libx/_runtime/cds-services/services/utils/compareJson.js +1 -53
- package/libx/_runtime/cds-services/services/utils/differ.js +15 -19
- package/libx/_runtime/cds-services/util/assert.js +107 -34
- package/libx/_runtime/cds.js +1 -31
- package/libx/_runtime/common/aspects/Association.js +40 -54
- package/libx/_runtime/common/aspects/any.js +61 -6
- package/libx/_runtime/common/aspects/entity.js +19 -79
- package/libx/_runtime/common/composition/data.js +2 -2
- package/libx/_runtime/common/composition/delete.js +8 -7
- package/libx/_runtime/common/composition/tree.js +10 -10
- package/libx/_runtime/common/composition/update.js +3 -2
- package/libx/_runtime/common/constants/events.js +13 -0
- package/libx/_runtime/common/error/entry.js +9 -3
- package/libx/_runtime/common/error/frontend.js +13 -19
- package/libx/_runtime/common/error/index.js +8 -3
- package/libx/_runtime/common/generic/auth/capabilities.js +2 -1
- package/libx/_runtime/common/generic/auth/constants.js +1 -4
- package/libx/_runtime/common/generic/auth/requires.js +1 -1
- package/libx/_runtime/common/generic/auth/restrict.js +12 -28
- package/libx/_runtime/common/generic/auth/restrictions.js +12 -4
- package/libx/_runtime/common/generic/auth/utils.js +2 -1
- package/libx/_runtime/common/generic/crud.js +9 -60
- package/libx/_runtime/common/generic/etag.js +41 -7
- package/libx/_runtime/common/generic/input.js +128 -66
- package/libx/_runtime/common/generic/paging.js +9 -3
- package/libx/_runtime/common/generic/put.js +2 -2
- package/libx/_runtime/common/generic/sorting.js +7 -3
- package/libx/_runtime/common/generic/temporal.js +0 -5
- package/libx/_runtime/common/i18n/messages.properties +2 -1
- package/libx/_runtime/common/utils/binary.js +69 -0
- package/libx/_runtime/common/utils/cqn.js +39 -14
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +93 -59
- package/libx/_runtime/common/utils/csn.js +87 -85
- package/libx/_runtime/common/utils/dollar.js +8 -7
- package/libx/_runtime/common/utils/draft.js +1 -1
- package/libx/_runtime/common/utils/foreignKeyPropagations.js +23 -7
- package/libx/_runtime/common/utils/generateOnCond.js +2 -1
- package/libx/_runtime/common/utils/keys.js +30 -13
- package/libx/_runtime/common/utils/postProcessing.js +6 -1
- package/libx/_runtime/common/utils/quotingStyles.js +0 -23
- package/libx/_runtime/common/utils/resolveStructured.js +23 -26
- package/libx/_runtime/common/utils/resolveView.js +4 -1
- package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -0
- package/libx/_runtime/common/utils/search2cqn4sql.js +4 -13
- package/libx/_runtime/common/utils/searchToLike.js +9 -13
- package/libx/_runtime/common/utils/streamProp.js +35 -0
- package/libx/_runtime/common/utils/structured.js +12 -18
- package/libx/_runtime/common/utils/template.js +3 -5
- package/libx/_runtime/common/utils/templateProcessor.js +22 -14
- package/libx/_runtime/common/utils/unionCqnTemplate.js +4 -14
- package/libx/_runtime/db/Service.js +2 -1
- package/libx/_runtime/db/expand/expand-v2.js +2 -2
- package/libx/_runtime/db/expand/expandCQNToJoin.js +7 -6
- package/libx/_runtime/db/generic/input.js +14 -17
- package/libx/_runtime/db/generic/integrity.js +1 -2
- package/libx/_runtime/db/generic/update.js +14 -1
- package/libx/_runtime/db/query/read.js +0 -1
- package/libx/_runtime/db/query/update.js +1 -1
- package/libx/_runtime/db/sql-builder/BaseBuilder.js +1 -1
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +5 -31
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
- package/libx/_runtime/db/sql-builder/ReferenceBuilder.js +0 -9
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +11 -10
- package/libx/_runtime/db/sql-builder/UpdateBuilder.js +2 -2
- package/libx/_runtime/db/sql-builder/annotations.js +1 -2
- package/libx/_runtime/db/utils/coloredTxCommands.js +5 -0
- package/libx/_runtime/db/utils/columns.js +1 -1
- package/libx/_runtime/db/utils/propagateForeignKeys.js +10 -2
- package/libx/_runtime/extensibility/activate.js +69 -0
- package/libx/_runtime/extensibility/add.js +41 -0
- package/libx/_runtime/extensibility/addExtension.js +68 -0
- package/libx/_runtime/extensibility/defaults.js +39 -0
- package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformREAD.js +0 -0
- package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformRESULT.js +2 -2
- package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformWRITE.js +2 -2
- package/libx/_runtime/extensibility/push.js +61 -0
- package/libx/_runtime/extensibility/service.js +21 -0
- package/libx/_runtime/extensibility/{uiflex/utils.js → utils.js} +39 -3
- package/libx/_runtime/extensibility/validation.js +53 -0
- package/libx/_runtime/extensibility/views.js +12 -0
- package/libx/_runtime/fiori/generic/activate.js +2 -4
- package/libx/_runtime/fiori/generic/before.js +17 -29
- package/libx/_runtime/fiori/generic/cancel.js +2 -4
- package/libx/_runtime/fiori/generic/delete.js +2 -4
- package/libx/_runtime/fiori/generic/edit.js +4 -16
- package/libx/_runtime/fiori/generic/index.js +31 -0
- package/libx/_runtime/fiori/generic/new.js +5 -21
- package/libx/_runtime/fiori/generic/patch.js +10 -15
- package/libx/_runtime/fiori/generic/prepare.js +13 -22
- package/libx/_runtime/fiori/generic/read.js +148 -163
- package/libx/_runtime/fiori/generic/readOverDraft.js +10 -4
- package/libx/_runtime/fiori/utils/handler.js +10 -22
- package/libx/_runtime/fiori/utils/where.js +1 -4
- package/libx/_runtime/hana/Service.js +14 -7
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +1 -1
- package/libx/_runtime/hana/dynatrace.js +2 -2
- package/libx/_runtime/hana/localized.js +7 -6
- package/libx/_runtime/hana/pool.js +9 -6
- package/libx/_runtime/hana/search.js +2 -3
- package/libx/_runtime/hana/{searchToContains.js → search2Contains.js} +5 -2
- package/libx/_runtime/hana/search2cqn4sql.js +20 -17
- package/libx/_runtime/index.js +2 -6
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +30 -22
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +4 -3
- package/libx/_runtime/messaging/common-utils/appId.js +9 -0
- package/libx/_runtime/messaging/common-utils/authorizedRequest.js +2 -18
- package/libx/_runtime/messaging/common-utils/connections.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-shared.js +2 -2
- package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +305 -231
- package/libx/_runtime/messaging/enterprise-messaging-utils/cloudEvents.js +2 -2
- package/libx/_runtime/messaging/enterprise-messaging-utils/options-management.js +15 -8
- package/libx/_runtime/messaging/enterprise-messaging-utils/options-messaging.js +57 -14
- package/libx/_runtime/messaging/enterprise-messaging.js +14 -19
- package/libx/_runtime/messaging/file-based.js +3 -1
- package/libx/_runtime/messaging/http-utils/token.js +18 -6
- package/libx/_runtime/messaging/message-queuing-utils/options-management.js +22 -12
- package/libx/_runtime/messaging/message-queuing-utils/options-messaging.js +27 -14
- package/libx/_runtime/messaging/message-queuing.js +138 -85
- package/libx/_runtime/messaging/outbox/utils.js +13 -7
- package/libx/_runtime/messaging/redis-messaging.js +0 -1
- package/libx/_runtime/messaging/service.js +4 -1
- package/libx/_runtime/remote/Service.js +24 -18
- package/libx/_runtime/remote/utils/client.js +90 -48
- package/libx/_runtime/remote/utils/data.js +23 -6
- package/libx/_runtime/sqlite/Service.js +14 -13
- package/libx/_runtime/sqlite/convertAssocToOneManaged.js +2 -0
- package/libx/_runtime/sqlite/customBuilder/CustomSelectBuilder.js +1 -0
- package/libx/_runtime/sqlite/execute.js +3 -9
- package/libx/_runtime/types/api.js +23 -11
- package/libx/common/utils/ucsn.js +15 -9
- package/libx/odata/afterburner.js +109 -29
- package/libx/odata/cqn2odata.js +48 -9
- package/libx/odata/grammar.pegjs +263 -156
- package/libx/odata/index.js +21 -9
- package/libx/odata/parseToCqn.js +8 -5
- package/libx/odata/parser.js +1 -1
- package/libx/odata/utils.js +13 -3
- package/libx/rest/RestAdapter.js +173 -113
- package/libx/rest/RestRequest.js +3 -2
- package/libx/rest/middleware/create.js +8 -6
- package/libx/rest/middleware/delete.js +6 -13
- package/libx/rest/middleware/error.js +1 -1
- package/libx/rest/middleware/input.js +6 -6
- package/libx/rest/middleware/operation.js +8 -3
- package/libx/rest/middleware/parse.js +3 -3
- package/libx/rest/middleware/payload.js +12 -0
- package/libx/rest/middleware/read.js +12 -2
- package/libx/rest/middleware/update.js +3 -3
- package/package.json +4 -6
- package/server.js +3 -44
- package/srv/extensibility-service.cds +56 -0
- package/srv/extensibility-service.js +1 -0
- package/srv/extensions.cds +8 -0
- package/srv/model-provider.cds +59 -0
- package/srv/model-provider.js +163 -0
- package/srv/mtx.cds +2 -0
- package/srv/mtx.js +22 -0
- package/srv/outbox.cds +2 -0
- package/tasks/enterprise-messaging-deploy.js +19 -12
- package/lib/serve/Service-compat.js +0 -36
- package/libx/_runtime/audit/generic/personal/constants.js +0 -4
- package/libx/_runtime/auth/strategies/dwc.js +0 -45
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/dispatcherUtils.js +0 -56
- package/libx/_runtime/cds-services/adapter/rest/Rest.js +0 -183
- package/libx/_runtime/cds-services/adapter/rest/RestRequest.js +0 -67
- package/libx/_runtime/cds-services/adapter/rest/handlers/create.js +0 -82
- package/libx/_runtime/cds-services/adapter/rest/handlers/delete.js +0 -39
- package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +0 -63
- package/libx/_runtime/cds-services/adapter/rest/handlers/read.js +0 -52
- package/libx/_runtime/cds-services/adapter/rest/handlers/update.js +0 -81
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +0 -56
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/utils.js +0 -33
- package/libx/_runtime/cds-services/adapter/rest/to.js +0 -8
- package/libx/_runtime/cds-services/adapter/rest/utils/binary.js +0 -50
- package/libx/_runtime/cds-services/adapter/rest/utils/data.js +0 -117
- package/libx/_runtime/cds-services/adapter/rest/utils/header-checks.js +0 -14
- package/libx/_runtime/cds-services/adapter/rest/utils/key-value-utils.js +0 -30
- package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +0 -250
- package/libx/_runtime/cds-services/adapter/rest/utils/result.js +0 -26
- package/libx/_runtime/cds-services/services/utils/handlerUtils.js +0 -200
- package/libx/_runtime/common/aspects/utils.js +0 -152
- package/libx/_runtime/common/toggles/handler.js +0 -21
- package/libx/_runtime/common/utils/extensibilityUtils.js +0 -18
- package/libx/_runtime/extensibility/mps/index.js +0 -5
- package/libx/_runtime/extensibility/mps/service.js +0 -111
- package/libx/_runtime/extensibility/mps/tar.js +0 -42
- package/libx/_runtime/extensibility/mps/utils.js +0 -11
- package/libx/_runtime/extensibility/uiflex/index.js +0 -54
- package/libx/_runtime/extensibility/uiflex/service.js +0 -276
- package/libx/_runtime/messaging/common-utils/naming-conventions.js +0 -20
- package/libx/_runtime/remote/utils/client-types.d.ts +0 -7
- package/libx/gql/GraphQLAdapter.js +0 -33
- package/libx/gql/constants/adapter.js +0 -69
- package/libx/gql/constants/cds.js +0 -18
- package/libx/gql/constants/graphql.js +0 -33
- package/libx/gql/readme.md +0 -1
- package/libx/gql/resolvers/crud/create.js +0 -20
- package/libx/gql/resolvers/crud/delete.js +0 -29
- package/libx/gql/resolvers/crud/index.js +0 -6
- package/libx/gql/resolvers/crud/read.js +0 -30
- package/libx/gql/resolvers/crud/update.js +0 -42
- package/libx/gql/resolvers/crud/utils/index.js +0 -36
- package/libx/gql/resolvers/field.js +0 -5
- package/libx/gql/resolvers/index.js +0 -7
- package/libx/gql/resolvers/mutation.js +0 -23
- package/libx/gql/resolvers/parse/ast/enrich.js +0 -52
- package/libx/gql/resolvers/parse/ast/fragment.js +0 -11
- package/libx/gql/resolvers/parse/ast/fromObject.js +0 -39
- package/libx/gql/resolvers/parse/ast/index.js +0 -3
- package/libx/gql/resolvers/parse/ast/meta.js +0 -4
- package/libx/gql/resolvers/parse/ast/variable.js +0 -7
- package/libx/gql/resolvers/parse/ast2cqn/columns.js +0 -44
- package/libx/gql/resolvers/parse/ast2cqn/entries.js +0 -31
- package/libx/gql/resolvers/parse/ast2cqn/index.js +0 -8
- package/libx/gql/resolvers/parse/ast2cqn/limit.js +0 -6
- package/libx/gql/resolvers/parse/ast2cqn/orderBy.js +0 -24
- package/libx/gql/resolvers/parse/ast2cqn/utils/index.js +0 -3
- package/libx/gql/resolvers/parse/ast2cqn/where.js +0 -70
- package/libx/gql/resolvers/parse/utils/index.js +0 -8
- package/libx/gql/resolvers/query.js +0 -13
- package/libx/gql/resolvers/root.js +0 -34
- package/libx/gql/schema/generate.js +0 -18
- package/libx/gql/schema/index.js +0 -5
- package/libx/gql/schema/mutation.js +0 -76
- package/libx/gql/schema/query.js +0 -108
- package/libx/gql/schema/typeDefMap.js +0 -45
- package/libx/gql/schema/utils/index.js +0 -54
- package/libx/gql/utils/index.js +0 -12
- package/libx/rest/middleware/auth.js +0 -20
- package/libx/rest/middleware/content.js +0 -19
- package/srv/flex.cds +0 -21
- package/srv/flex.js +0 -1
- package/srv/mps.cds +0 -23
- package/srv/mps.js +0 -1
- 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:
|
|
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
|
|
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: {
|
|
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
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
(
|
|
43
|
-
|
|
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,
|
|
41
|
+
addDataSubjectForDetailsEntity(row, entry, req, entity, model)
|
|
47
42
|
}
|
|
48
43
|
}
|
|
49
44
|
}
|
|
50
45
|
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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,
|
|
53
|
+
const processFn = _processorFnAccess(accessLogs, this.model, req)
|
|
63
54
|
const data_ = Array.isArray(data) ? data : [data]
|
|
64
|
-
data_.forEach(row => {
|
|
65
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
25
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
22
|
-
|
|
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) =>
|
|
42
|
-
if (!
|
|
42
|
+
const _processorFnModification = (modificationLogs, model, req, beforeWrite) => elementInfo => {
|
|
43
|
+
if (!elementInfo.row._op) return
|
|
43
44
|
|
|
44
|
-
const { row, key, element, plain } =
|
|
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
|
|
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 (!
|
|
98
|
-
const existingLogs =
|
|
99
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
129
|
-
if (!
|
|
130
|
-
|
|
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).
|
|
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).
|
|
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).
|
|
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
|
|
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
|
-
|
|
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] ||
|
|
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 (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
//
|
|
164
|
-
|
|
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
|
-
|
|
173
|
-
|
|
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
|
-
|
|
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 (
|
|
181
|
-
//
|
|
182
|
-
|
|
165
|
+
if (config.impl) {
|
|
166
|
+
// mount custom authentication middleware
|
|
167
|
+
_mountCustomAuth(srv, app, config)
|
|
183
168
|
} else {
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
|
|
197
|
-
|
|
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
|
-
|
|
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
|
}
|