Skip to content

Commit

Permalink
Merge branch 'main' into troubleshoot-readiness-check
Browse files Browse the repository at this point in the history
  • Loading branch information
sjvans authored Jan 15, 2025
2 parents 4cf40ea + 5072bd1 commit fa6955c
Show file tree
Hide file tree
Showing 23 changed files with 411 additions and 75 deletions.
7 changes: 5 additions & 2 deletions .github/cli/grab-cli-texts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ pushd `dirname ${proj}` && cds init `basename ${proj}` && pushd `basename ${proj

echo
echo "Grabbing CLI texts..."
${dir}/grab-cli-texts.js @sap/cds-dk "cds add --help" ${proj} > ${dir}/../../tools/assets/help/cds-add.out.md
${dir}/grab-cli-texts.js @cap-js/cds-typer "cds-typer --help" ${proj} > ${dir}/../../tools/assets/help/cds-typer.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds --help" ${proj} > ${dir}/../../tools/assets/help/cds-help.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds watch --help" ${proj} > ${dir}/../../tools/assets/help/cds-watch.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds add --help" ${proj} > ${dir}/../../tools/assets/help/cds-add.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds compile --help" ${proj} > ${dir}/../../tools/assets/help/cds-compile.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds env --help" ${proj} > ${dir}/../../tools/assets/help/cds-env.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds init --help" ${proj} > ${dir}/../../tools/assets/help/cds-init.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds repl --help" ${proj} > ${dir}/../../tools/assets/help/cds-repl.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds watch --help" ${proj} > ${dir}/../../tools/assets/help/cds-watch.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds version" ${proj} > ${dir}/../../tools/assets/help/cds-version.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds version --markdown" ${proj} > ${dir}/../../tools/assets/help/cds-version-md.out.md
${dir}/grab-cli-texts.js @sap/cds-dk "cds env requires.db" ${proj} > ${dir}/../../tools/assets/help/cds-env-requires-db.out.md
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/PR-SAP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
node-version: 22
cache: 'npm'
cache-dependency-path: docs/package-lock.json
- run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/PR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
node-version: 22
cache: 'npm'
- name: Run CDS snippet checker
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
node-version: 22
cache: 'npm'
cache-dependency-path: docs/package-lock.json
- run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
node-version: 22
cache: 'npm'
- run: npm ci
- run: npm test
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ We as members, contributors, and leaders pledge to make participation in our com

## Licensing

Copyright 2023-2024 SAP SE or an SAP affiliate company and CAP contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/SAP/cap-js/docs).
Copyright 2023-2025 SAP SE or an SAP affiliate company and CAP contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/SAP/cap-js/docs).
2 changes: 1 addition & 1 deletion cds/cdl.md
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ In CAP Java, run a select statement against the view with named [parameter value

::: code-group
```js [Node]
SELECT.from({ id: 'UsingView'. args: { bar: { val: true }}})
SELECT.from({ ref: [{ id: 'UsingView', args: { bar: { val: true }}} ]} )
```
```Java [Java]
var params = Map.of("bar", true);
Expand Down
2 changes: 1 addition & 1 deletion get-started/in-a-nutshell.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ cds db/schema.cds -2 yml
cds db/schema.cds -2 sql
```

[Learn more about the command line interface by executing `cds help`.](#cli){.learn-more}
[Learn more about the command line interface by executing `cds help`.](../tools/cds-cli#cds-help){.learn-more}



Expand Down
35 changes: 18 additions & 17 deletions guides/data-privacy/audit-logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,25 @@ npm add @cap-js/audit-logging

1. Sets <Config>cds.requires.audit-log: true</Config>

2. Which in turn activates the `audit-log` configuration **presets**:
2. Which in turn activates the effective `audit-log` configuration via **presets**:
```jsonc
{
"audit-log": {
"handle": [ "READ", "WRITE" ],
"outbox": true
"[development]": {
"impl": "@cap-js/audit-logging/srv/log2console"
},
"[hybrid]": {
"impl": "@cap-js/audit-logging/srv/log2restv2",
"vcap": { "label": "auditlog" }
},
"[production]": {
"impl": "@cap-js/audit-logging/srv/log2restv2",
"vcap": { "label": "auditlog" }
}
}
"audit-log": {
"handle": ["READ", "WRITE"],
"outbox": true,
"[development]": { "kind": "audit-log-to-console" },
"[hybrid]": { "kind": "audit-log-to-restv2" },
"[production]": { "kind": "audit-log-to-restv2" }
},
"kinds": {
"audit-log-to-console": {
"impl": "@cap-js/audit-logging/srv/log2console"
},
"audit-log-to-restv2": {
"impl": "@cap-js/audit-logging/srv/log2restv2",
"vcap": { "label": "auditlog" }
}
}
}
```

Expand Down Expand Up @@ -182,7 +183,7 @@ There are two options to access audit logs:
### Behind the Scenes...
The generic audit logging implementation does the following:
For all [defined services](../providing-services#service-definitions), the generic audit logging implementation does the following:
- Intercept all write operations potentially involving personal data.
- Intercept all read operations potentially involving sensitive data.
Expand Down
16 changes: 11 additions & 5 deletions guides/databases.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,10 @@ This set of functions are by large the same as specified in OData:
* `startswith(x,y)` — checks whether `y` starts with `x`
* `endswith(x,y)` — checks whether `y` ends with `x`
* `matchespattern(x,y)` — checks whether `x` matches regex `y`
* `substring(x,i,n?)` <sup>1</sup> — extracts a substring from `x` starting at `i` (may be negative) with length `n` (optional; may be negative)
* `substring(x,i,n?)` <sup>1</sup>
Extracts a substring from `x` starting at index `i` (0-based) with optional length `n`.
* **`i`**: Positive starts at `i`, negative starts `i` before the end.
* **`n`**: Positive extracts `n` items; omitted extracts to the end; negative is invalid.
* `indexof(x,y)` <sup>1</sup> — returns the index of the first occurrence of `y` in `x`
* `length(x)` — returns the length of string `x`
* `tolower(x)` — returns all-lowercased `x`
Expand All @@ -375,12 +378,15 @@ This set of functions are by large the same as specified in OData:
* `floor(x)` — rounds the input numeric parameter down to the nearest numeric value
* `round(x)` — rounds the input numeric parameter to the nearest numeric value.
The mid-point between two integers is rounded away from zero, i.e. 0.5 is rounded to 1 and ‑0.5 is rounded to -1.
* `year(x)` `month(x)`, `day(x)`, `hour(x)`, `minute(x)`, `second(x)`, `fractionalseconds(x)`, `time(x)`, `date(x)`
* `year(x)` `month(x)`, `day(x)`, `hour(x)`, `minute(x)`, `second(x)`
returns parts of a datetime for a given `cds.DateTime` / `cds.Date` / `cds.Time`
* `maxdatetime(x)`, `mindatetime(x)`return the maximum or minimum datetime for a given `cds.DateTime` / `cds.Date` / `cds.Time`
* `totalseconds(x)` — returns the total seconds of a datetime for a given `cds.DateTime` / `cds.Time`
* `time(x)`, `date(x)` - returns a string representing the `time` / `date` for a given `cds.DateTime` / `cds.Date` / `cds.Time`
* `fractionalseconds(x)` - returns a a `Decimal` representing the fractions of a second for a given `cds.Timestamp`
* `maxdatetime()` - returns the latest possible point in time: `'9999-12-31T23:59:59.999Z'`
* `mindatetime()` — returns the earliest possible point in time: `'0001-01-01T00:00:00.000Z'`
* `totalseconds(x)` — returns the duration of the value in total seconds, including fractional seconds. The [OData spec](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_totalseconds) defines the input as EDM.Duration: `P12DT23H59M59.999999999999S`
* `now()` — returns the current datetime
* `min(x)` `max(x)` `sum(x)` `avg(x)` `count(x)`, `countdistinct(x)` — aggregate functions
* `min(x)` `max(x)` `sum(x)` `average(x)` `count(x)`, `countdistinct(x)` — aggregate functions
* `search(xs,y)` — checks whether `y` is contained in any of `xs`, may be fuzzy → [see Searching Data](../guides/providing-services#searching-data)
* `session_context(v)` — with standard variable names → [see Session Variables](#session-variables)
> <sup>1</sup> These functions work zero-based. E.g., `substring('abcdef', 1, 3)` returns 'bcd'
Expand Down
2 changes: 1 addition & 1 deletion guides/deployment/cicd.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ SAP Continuous Integration and Delivery is a service on SAP BTP, which lets you

SAP Continuous Integration and Delivery has a ready-to-use pipeline for CAP, that is applicable to Node.js, Java and multitarget application (MTA) based projects. It does not require you to host your own Jenkins instance and it provides an easy, UI-guided way to configure your pipelines.

Try the tutorial [Configure and Run a Predefined SAP Continuous Integration and Delivery (CI/CD) Pipeline](https://developers.sap.com/tutorials/btp-app-ci-cd-btp.html) to configure a CI/CD pipeline that builds, tests, and deploys your code changes.
Try the tutorial [Get Started with SAP Continuous Integration and Delivery](https://developers.sap.com/tutorials/cicd-start-cap.html) to configure a CI/CD pipeline that builds, tests, and deploys your code changes.

[Learn more about SAP Continuous Integration and Delivery.](https://help.sap.com/viewer/SAP-Cloud-Platform-Continuous-Integration-and-Delivery){.learn-more}

Expand Down
21 changes: 16 additions & 5 deletions guides/security/authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ Depending on the configured [authentication](#prerequisite-authentication) strat
| CAP User Property | XSUAA JWT Property | IAS JWT Property |
|---------------------|----------------------------------|-------------------------|
| `$user` | `user_name` | `sub` |
| `$user.tenant` | `zid` | `zone_uuid` |
| `$user.tenant` | `zid` | `app_tid` |
| `$user.<attribute>` | `xs.user.attributes.<attribute>` | All non-meta attributes |

::: tip
Expand Down Expand Up @@ -489,12 +489,13 @@ A service level entity can't inherit a restriction with a `where` condition that

The [restrict annotation](#restrict-annotation) for an entity allows you to enforce authorization checks that statically depend on the event type and user roles. In addition, you can define a `where`-condition that further limits the set of accessible instances. This condition, which acts like a filter, establishes an *instance-based authorization*.

The condition defined in the `where`-clause typically associates domain data with static [user claims](#user-claims). Basically, it *either filters the result set in queries or accepts only write operations on instances that meet the condition*. This means that, the condition applies following standard CDS events only<sup>1</sup>:
The condition defined in the `where`-clause typically associates domain data with static [user claims](#user-claims). Basically, it *either filters the result set in queries or accepts only write operations on instances that meet the condition*. This means that, the condition applies to following standard CDS events only<sup>1</sup>:
- `READ` (as result filter)
- `UPDATE` (as reject condition)
- `DELETE` (as reject condition)
- `UPDATE` (as reject condition<sup>2</sup>)
- `DELETE` (as reject condition<sup>2</sup>)

> <sup>1</sup> Node.js supports _static expressions_ that *don't have any reference to the model* such as `where: $user.level = 2` for all events.
> <sup>1</sup> Node.js supports _static expressions_ that *don't have any reference to the model* such as `where: $user.level = 2` for all events.
> <sup>2</sup> CAP Java uses a filter condition by default.
For instance, a user is allowed to read or edit `Orders` (defined with the `managed` aspect) that they have created:

Expand All @@ -518,6 +519,16 @@ Supported features are:
* [Exists predicate](#exists-predicate) based on subselects.


<div class="impl java">

CAP Java offers the option to enable rejection conditions for `UPDATE`, `DELETE` and custom events. Enable it using the configuration option <Config java keyOnly label="reject-selected-unauthorized-entity">cds.security.authorization.instance-based.reject-selected-unauthorized-entity.enabled: true</Config>.

</div>

::: info Avoid enumerable keys
In case the filter condition is not met in an `UPDATE` or `DELETE` request, the runtime rejects the request (response code 403) even if the user is not even allowed to read the entity. To avoid to disclosure the existence of such entities to unauthorized users, make sure that the key is not efficiently enumerable.
:::

### User Attribute Values { #user-attrs}

To refer to attribute values from the user claim, prefix the attribute name with '`$user.`' as outlined in [static user claims](#user-claims). For instance, `$user.country` refers to the attribute with the name `country`.
Expand Down
3 changes: 1 addition & 2 deletions java/cqn-services/remote-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,7 @@ Use the following example if the remote API supports basic authentication:
```java
DefaultHttpDestination
.builder("https://example.org")
.user("user")
.password("password")
.basicCredentials("user", "password")
.name("my-destination").build();
```

Expand Down
26 changes: 13 additions & 13 deletions node.js/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ uacp: This page is linked from the Help Portal at https://help.sap.com/products/

# Authentication

{{$frontmatter?.synopsis}} This is done by [authentication middlewares](#strategies) setting the [`req.user` property](#cds-user) which is then used in [authorization enforcement](#enforcement) decisions.
{{$frontmatter?.synopsis}} This is done by [authentication middlewares](#strategies) setting the [`cds.context.user` property](#cds-user) which is then used in [authorization enforcement](#enforcement) decisions.

[[toc]]


## cds. User { #cds-user .class }
[user]: #cds-user
[`req.user`]: #cds-user
[`cds.context.user`]: #cds-user

Represents the currently logged-in user as filled into [`req.user`](events#user) by authentication middlewares.
Represents the currently logged-in user as filled into [`cds.context.user`](events#user) by authentication middlewares.
Simply create instances of `cds.User` or of subclasses thereof in custom middlewares.
For example:

```js
const cds = require('@sap/cds')
const DummyUser = new class extends cds.User { is:()=>true }
module.exports = (req,res,next) => {
req.user = new DummyUser('dummy')
cds.context.user = new DummyUser('dummy')
next()
}
```
Expand Down Expand Up @@ -112,7 +112,7 @@ By default, `cds.User.default` points to `cds.User.Anonymous`. However, you can
## Authorization Enforcement {#enforcement}
Applications can use the `req.user` APIs to do programmatic enforcement.
Applications can use the `cds.context.user` APIs to do programmatic enforcement.
For example, the authorization of the following CDS service:
```cds
Expand All @@ -132,7 +132,7 @@ can be programmatically enforced by means of the API as follows:
const cds = require('@sap/cds')
cds.serve ('CustomerService') .with (function(){
this.before ('*', req =>
req.user.is('authenticated') || req.reject(403)
req.user.is('authenticated') || req.reject(403)
)
this.before (['READ', 'CREATE'], 'Orders', req =>
req.user.is('admin') || req.reject(403)
Expand Down Expand Up @@ -298,7 +298,7 @@ In contrast to [mocked authentication](#mocked), no default users are automatica
This is the default strategy used in production. User identity, as well as assigned roles and user attributes, are provided at runtime, by a bound instance of the ['User Account and Authentication'](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/419ae2ef1ddd49dca9eb65af2d67c6ec.html) service (UAA). This is done in form of a JWT token in the `Authorization` header of incoming HTTP requests.
This authentication strategy also adds [`req.user.tokenInfo`](#user-token-info).
This authentication strategy also adds [`cds.context.user.tokenInfo`](#user-token-info).
**Prerequisites:** You need to add [@sap/xssec](https://help.sap.com/docs/HANA_CLOUD_DATABASE/b9902c314aef4afb8f7a29bf8c5b37b3/54513272339246049bf438a03a8095e4.html#loio54513272339246049bf438a03a8095e4__section_atx_2vt_vt) to your project:
```sh
Expand All @@ -322,7 +322,7 @@ npm add @sap/xssec
### XSUAA-based Authentication { #xsuaa }
Authentication kind `xsuaa` is a logical extension of kind [`jwt`](#jwt) that additionally offers access to SAML attributes through `req.user.attr` (for example, `req.user.attr.familyName`).
Authentication kind `xsuaa` is a logical extension of kind [`jwt`](#jwt) that additionally offers access to SAML attributes through `cds.context.user.attr` (for example, `cds.context.user.attr.familyName`).
**Prerequisites:** You need to add [@sap/xssec](https://help.sap.com/docs/HANA_CLOUD_DATABASE/b9902c314aef4afb8f7a29bf8c5b37b3/54513272339246049bf438a03a8095e4.html#loio54513272339246049bf438a03a8095e4__section_atx_2vt_vt) to your project:
```sh
Expand All @@ -348,7 +348,7 @@ npm add @sap/xssec
This is an additional authentication strategy using the [Identity Authentication Service](https://help.sap.com/docs/IDENTITY_AUTHENTICATION) (IAS) that can be used in production. User identity and user attributes are provided at runtime, by a bound instance of the IAS service. This is done in form of a JWT token in the `Authorization` header of incoming HTTP requests.
This authentication strategy also adds [`req.user.tokenInfo`](#user-token-info).
This authentication strategy also adds [`cds.context.user.tokenInfo`](#user-token-info).
To allow forwarding to remote services, JWT tokens issued by IAS service don't contain authorization information. In particular, no scopes are included. Closing this gap is up to you as application developer.
Expand Down Expand Up @@ -384,22 +384,22 @@ You can configure an own implementation by specifying an own `impl` as follows:
Essentially, custom authentication middlewares must do two things:
First, they _must_ [fulfill the `req.user` contract](#cds-user) by assigning an instance of `cds.User` or a look-alike to the incoming request at `req.user`.
First, they _must_ [fulfill the `cds.context.user` contract](#cds-user) by assigning an instance of `cds.User` or a look-alike to the continuation of the incoming request at `cds.context.user`.
Second, if running in a multitenant environment, `req.tenant` must be set to a string identifying the tenant that is addressed by the incoming request.
Second, if running in a multitenant environment, `cds.context.tenant` must be set to a string identifying the tenant that is addressed by the incoming request.
```js
module.exports = function custom_auth (req, res, next) {
// do your custom authentication
req.user = new cds.User({
cds.context.user = new cds.User({
id: '<user-id>',
roles: ['<role-a>', '<role-b>'],
attr: {
<user-attribute-a>: '<value>',
<user-attribute-b>: '<value>'
}
})
req.tenant = '<tenant>'
cds.context.tenant = '<tenant>'
}
```
Expand Down
Loading

0 comments on commit fa6955c

Please sign in to comment.