From 8beaa65a1c740fc82bfc97c92527c45cf95ac97d Mon Sep 17 00:00:00 2001 From: Rene Jeglinsky Date: Fri, 9 Feb 2024 11:46:04 +0100 Subject: [PATCH 1/6] tested new flow --- guides/data-privacy/annotations.md | 2 +- guides/data-privacy/audit-logging.md | 35 ++-- guides/data-privacy/pdm.md | 261 ++++++++++++++------------- node.js/core-services.md | 2 +- 4 files changed, 153 insertions(+), 147 deletions(-) diff --git a/guides/data-privacy/annotations.md b/guides/data-privacy/annotations.md index 904cdedea..b4508a845 100644 --- a/guides/data-privacy/annotations.md +++ b/guides/data-privacy/annotations.md @@ -34,7 +34,7 @@ Following the [best practice of separation of concerns](../domain-modeling#separ ::: code-group ```cds [srv/data-privacy.cds] -using { sap.capire.incidents as my } from '../db/extensions'; +using { sap.capire.incidents as my } from '../db/schema'; annotate my.Customers with @PersonalData : { DataSubjectRole : 'Customer', diff --git a/guides/data-privacy/audit-logging.md b/guides/data-privacy/audit-logging.md index fc61231b9..ca4ec81c3 100644 --- a/guides/data-privacy/audit-logging.md +++ b/guides/data-privacy/audit-logging.md @@ -26,7 +26,7 @@ _The following is mainly written from a Node.js perspective. For Java's perspect First identify entities and elements (potentially) holding personal data using `@PersonalData` annotations, as explained in detail in the [*Annotating Personal Data* chapter](annotations) of these guides. - +> We keep using the [Incidents Management reference sample app](https://github.com/cap-js/incidents-app). ## Add the Plugin { #setup } @@ -94,7 +94,7 @@ cds env requires.audit-log --profile production ## Test-drive Locally -The steps above is all we need to automatically log personal data-related events. Let's see that in action… +The previous step is all we need to do to automatically log personal data-related events. Let's see that in action… 1. **Start the server** as usual: @@ -103,39 +103,42 @@ The steps above is all we need to automatically log personal data-related events ``` 2. **Send an update** request that changes personal data: - - ```http - PATCH http://localhost:4004/admin/Customers(8e2f2640-6866-4dcf-8f4d-3027aa831cad) HTTP/1.1 + ::: code-group + ```http [test/audit-logging.http] + PATCH http://localhost:4004/admin/Customers(2b87f6ca-28a2-41d6-8c69-ccf16aa6389d) HTTP/1.1 Authorization: Basic alice:in-wonderland Content-Type: application/json { - "firstName": "Johnny", - "lastName": "Doey" + "firstName": "Jane", + "lastName": "Doe" } ``` + ::: + + [Find more sample requests in the Incident Management sample.](https://github.com/cap-js/incidents-app/blob/attachments/test/audit-logging.http){.learn-more} 3. **See the audit logs** in the server's console output: ```js { data_subject: { - type: 'AdminService.Customers', - id: { ID: '8e2f2640-6866-4dcf-8f4d-3027aa831cad' }, + id: { ID: '2b87f6ca-28a2-41d6-8c69-ccf16aa6389d' }, role: 'Customer', + type: 'AdminService.Customers' }, object: { - type: 'AdminService.Customers', - id: { ID: '8e2f2640-6866-4dcf-8f4d-3027aa831cad' } + type: 'AdminService.Customers', + id: { ID: '2b87f6ca-28a2-41d6-8c69-ccf16aa6389d' } }, attributes: [ - { name: 'firstName', old: 'John', new: 'Johnny' }, - { name: 'lastName', old: 'Doe', new: 'Doey' } + { name: 'firstName', old: 'Sunny', new: 'Jane' }, + { name: 'lastName', old: 'Sunshine', new: 'Doe' } ], - user: 'alice', + uuid: '5cddbc91-8edf-4ba2-989b-87869d94070d', tenant: 't1', - uuid: '1391A703E2CBE52E817269EC7527368C', - time: '2023-02-26T08:13:48.287Z' + user: 'alice', + time: 2024-02-08T09:21:45.021Z } ``` diff --git a/guides/data-privacy/pdm.md b/guides/data-privacy/pdm.md index df805da12..8730a417d 100644 --- a/guides/data-privacy/pdm.md +++ b/guides/data-privacy/pdm.md @@ -36,45 +36,49 @@ Following the CAP principles, we recommend adding a new dedicated CAP service th Following the [best practice of separation of concerns](../domain-modeling#separation-of-concerns), we create a dedicated service for the integration with SAP Personal Data Manager: ::: code-group -```cds [pdm-service.cds] -using { sap.capire.incidents as db } from '@capire/incidents'; +```cds [srv/pdm-service.cds] +using {sap.capire.incidents as db} from '../db/schema'; @requires: 'PersonalDataManagerUser' // security check -service PDMService { +service PDMService @(path: '/pdm') { // Data Privacy annotations on 'Customers' and 'Addresses' are derived from original entity definitions - entity Customers as projection on db.Customers; - entity Addresses as projection on db.Addresses; + entity Customers as projection on db.Customers; + entity Addresses as projection on db.Addresses; + entity Incidents as projection on db.Incidents // create view on Incidents and Conversations as flat projection entity IncidentConversationView as - select from Incidents { - ID, title, urgency, status, - key conversations.ID as conversation_ID, - conversations.timestamp as conversation_timestamp, - conversations.author as conversation_author, - conversations.message as conversation_message, - customer.ID as customer_ID, - customer.email as customer_email - }; + select from Incidents { + ID, + title, + urgency, + status, + key conversation.ID as conversation_ID, + conversation.timestamp as conversation_timestamp, + conversation.author as conversation_author, + conversation.message as conversation_message, + customer.ID as customer_ID, + customer.email as customer_email + }; // annotate new view annotate PDMService.IncidentConversationView with @(PersonalData.EntitySemantics: 'Other') { - customer_ID @PersonalData.FieldSemantics: 'DataSubjectID'; + customer_ID @PersonalData.FieldSemantics: 'DataSubjectID'; }; // annotations for Personal Data Manager - Search Fields annotate Customers with @(Communication.Contact: { - n : { - surname : lastName, - given : firstName - }, - email : { - address : email - } + n : { + surname: lastName, + given : firstName + }, + email: EMailAddress //how to use the type here? }); -}; + }; + + ``` ::: @@ -114,40 +118,6 @@ To restrict access to this sensitive data, the `PDMservice` is protected by the -### Activate Access Checks in _xs-security.json_ - -Because we protected the `PDMservice`, we need to establish the security check properly. In particular, you need the _xs-security.json_ file to make the security check active. The following _xs-security.json_ is from our sample. - -```json -{ - "xsappname": "incidents-mgmt", - "tenant-mode": "shared", - "scopes": [ - { - "name": "$XSAPPNAME.PersonalDataManagerUser", - "description": "Authority for Personal Data Manager", - "grant-as-authority-to-apps": [ - "$XSSERVICENAME(pdm)" - ] - } - ] -} -``` - -Here you define that your personal data manager service instance, called `pdm`, is allowed to access your CAP application granting the `PersonalDataManagerUser` role. - - - -### Add `@sap/xssec` Library - -To make the authentication work, you have to enable the security strategy by installing the `@sap/xssec` package: - -```sh -npm install @sap/xssec -``` - -[Learn more about authorization in CAP using Node.js.](../../node.js/authentication#jwt){.learn-more} - At this point, you are done with your application. Let's set up the SAP Personal Data Manager and try it out. @@ -160,27 +130,6 @@ A more comprehensive guide, incl. tutorials, is currently under development. For further details, see the [SAP Personal Data Manager Developer Guide](https://help.sap.com/docs/personal-data-manager/4adcd96ce00c4f1ba29ed11f646a5944/what-is-personal-data-manager). - -### Build and Deploy Your Application - -The Personal Data Manager can't connect to your application running locally. Therefore, you first need to deploy your application. In our sample, we added two manifest files using `cds add cf-manifest` and SAP HANA configuration using `cds add hana`. - -The general deployment is described in detail in [Deploy Using Manifest Files](../deployment/to-cf). - -Make a production build: - -```sh -cds build --production -``` - -Deploy your application: - -```sh -cf create-service-push -``` - - - ### Subscribe to SAP Personal Data Manager Service [Subscribe to the service](https://help.sap.com/docs/PERSONAL_DATA_MANAGER/620a3ea6aaf64610accdd05cca9e3de2/ef10215655a540b6ba1c02a96e118d66.html) from the _Service Marketplace_ in the SAP BTP cockpit. @@ -190,86 +139,140 @@ cf create-service-push Follow the wizard to create your subscription. +### Build and Deploy Your Application -### Create Role Collections - -SAP Personal Data Manager comes with the following roles: - -Role Name | Role Template -----------|------ -PDM_Administrator | PDM_Administrator -PDM_CustomerServiceRepresentative | PDM_CustomerServiceRepresentative -PDM_OperatorsClerk | PDM_OperatorsClerk - -All of these roles have two different _Application Identifiers_. -::: tip -Application identifiers with **!b** are needed for the UI, and identifiers with **!t** are needed for executing the Postman collection. +:::info Working Notes +- Rework to MTA Deployment +- Adapt sample ::: -[Learn more about defining a role collection in SAP BTP cockpit](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/4b20383efab341f181becf0a947a5498.html){.learn-more} - +The Personal Data Manager can't connect to your application running locally. Therefore, you need to deploy your application. +The general deployment is described in detail in [Deploy Using Manifest Files](../deployment/to-cf). Here's for short what you need to do. -### Create a Service Instance +### Prepare for Deployment -You need a configuration file, like the following, to create a service instance for the Personal Data Manager. +Add SAP HANA Cloud configuration, as well as an approuter and an _mta.yaml_ to your project: -`pdm-instance-config.json` -```json -{ - "xs-security": { - "xsappname": "incidents-mgmt", - "authorities": ["$ACCEPT_GRANTED_AUTHORITIES"] - }, - "fullyQualifiedApplicationName": "incidents-mgmt", - "appConsentServiceEnabled": true -} +```sh +cds add hana,approuter,mta +``` +Add `@sap/xssec` library, to make the authentication work: +```sh +npm install @sap/xssec ``` -Create a service instance using the SAP BTP cockpit or execute the following command: +[Learn more about authorization in CAP using Node.js.](../../node.js/authentication#jwt){.learn-more} -```sh -cf create-service personal-data-manager-service standard incidents-mgmt-pdm -c ./pdm-instance-config.json +### Enhance mta.yaml with DPI + +```yaml +modules: + - name: incidents-srv + ... + requires: + ... + - name: incidents-information // [!code ++] +... +resources: + ... + - name: incidents-information // [!code ++] + type: org.cloudfoundry.managed-service // [!code ++] + requires: // [!code ++] + - name: srv-api // [!code ++] + parameters: // [!code ++] + service-name: incidents-information // [!code ++] + service: data-privacy-integration-service // [!code ++] + service-plan: data-privacy-internal // [!code ++] + path: ./pdm-config.json // [!code ++] + config: // [!code ++] + xs-security: // [!code ++] + xsappname: incidents-information-${org}-$ // [!code ++]{space} + authorities: // [!code ++] + - $ACCEPT_GRANTED_AUTHORITIES // [!code ++] ``` +### Configure PDM Service + +::: code-group +```json [pdm-config.json] +{ + "dataPrivacyConfiguration": { + "configType": "information", + "applicationConfiguration": { + "applicationName": "incidents-information", + "applicationDescription": "DPI NextGen Bookshop CAP Reference Application", + "applicationTitle": "DPI NextGen Bookshop" + }, + "informationConfiguration": { + "applicationConfiguration": { + "dataSubjectDeletionAgent": "retention-manager", + "retentionApplicationName": "incidents-retention", + "disableDataSubjectCorrection": true, + "cacheControl": "no-cache" + }, + "components": [ + { + "componentName": "incidents-srv", + "componentBaseURL": "~{srv-api/srv-url}", + "serviceEndPoints": [ + { + "serviceName": "dpi-service", + "serviceFormat": "odata-v4", + "annotationFormat": "v4", + "serviceEndPoint": "/pdm", + "appPaginationEnabled": true, + "cacheControl": "no-cache" + } + ] + } + ] + } + } +} +``` +::: -### Bind the Service Instance to Your Application. +### Activate Access Checks in _xs-security.json_ -With both the application deployed and the SAP Personal Data Manger service set up, you can now bind the service instance of the Personal Data Manager to your application. Use the URL of your application in a configuration file, such as the following example, which you need when binding a service instance. +Because we protected the `PDMservice`, we need to establish the security check properly. In particular, you need the _xs-security.json_ file to make the security check active. Add the following scope: -`pdm-binding-config.json` ```json { - "fullyQualifiedApplicationName": "incidents-mgmt", - "fullyQualifiedModuleName": "incidents-mgmt-srv", - "applicationTitle": "PDM Incidents", - "applicationTitleKey": "PDM Incidents", - "applicationURL": "https://incidents-mgmt-srv.cfapps.eu10.hana.ondemand.com/", // get the URL from the CF CLI command: cf apps - "endPoints": [ + "scopes": [ { - "type": "odatav4", - "serviceName": "pdm-service", - "serviceTitle": "Incidents Management", - "serviceTitleKey": "IncidentsManagement", - "serviceURI": "pdm", - "hasGdprV4Annotations": true, - "cacheControl": "no-cache" + "name": "$XSAPPNAME.PersonalDataManagerUser", + "description": "Authority for Personal Data Manager", + "grant-as-authority-to-apps": [ + "$XSSERVICENAME(incidents-information)" + ] } ] } ``` -Here the `applicationURL`, the `fullyQualifiedModuleName`, and the `serviceURI` have to be those of your Cloud Foundry deployment and your CAP service definition (_services-manifest.yaml_). +Here you define that your personal data manager service instance, called `incidents-information`, is allowed to access your CAP application granting the `PersonalDataManagerUser` role. -Bind the service instance using the SAP BTP cockpit or execute the following command: -```sh -cf bind-service incidents-mgmt-srv incidents-mgmt-pdm -c ./pdm-binding-config.json -``` +### Create Role Collections + +SAP Personal Data Manager comes with the following roles: +Role Name | Role Template +----------|------ +PDM_Administrator | PDM_Administrator +PDM_CustomerServiceRepresentative | PDM_CustomerServiceRepresentative +PDM_OperatorsClerk | PDM_OperatorsClerk + +All of these roles have two different _Application Identifiers_. +::: tip +Application identifiers with **!b** are needed for the UI, and identifiers with **!t** are needed for executing the Postman collection. +::: + +[Learn more about defining a role collection in SAP BTP cockpit](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/4b20383efab341f181becf0a947a5498.html){.learn-more} ## Using the SAP Personal Data Manager Application diff --git a/node.js/core-services.md b/node.js/core-services.md index e1cccaa44..2b2c72e48 100644 --- a/node.js/core-services.md +++ b/node.js/core-services.md @@ -521,7 +521,7 @@ class BooksService extends cds.ApplicationService { **Argument `entity`** can be one of: - A `CSN definition` of an entity served by this service → as obtained from [`this.entities`](#entities) -- A `string` matching the name of an entity served by this service +- A `string` matching the name of an entity served by this service, → see [draft support](./fiori#draft-support) - A `path` navigating from a served entity to associated ones → e.g. `'Books/author'` - An `array` of the above to register the given handler for multiple entities / paths - The string `'*'` to register the given handler for *all* potential entities / paths From b6cbfb27cdcccaa5744c18e4f39716fe9a7e706f Mon Sep 17 00:00:00 2001 From: Rene Jeglinsky Date: Wed, 21 Feb 2024 14:52:18 +0100 Subject: [PATCH 2/6] fix email ref in pdm service --- guides/data-privacy/pdm.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/guides/data-privacy/pdm.md b/guides/data-privacy/pdm.md index 8730a417d..8527e031f 100644 --- a/guides/data-privacy/pdm.md +++ b/guides/data-privacy/pdm.md @@ -69,12 +69,12 @@ service PDMService @(path: '/pdm') { // annotations for Personal Data Manager - Search Fields annotate Customers with @(Communication.Contact: { - n : { - surname: lastName, - given : firstName - }, - email: EMailAddress //how to use the type here? - }); + n : { + surname: lastName, + given : firstName + }, + email: [{address: email}] + }); }; @@ -141,14 +141,9 @@ Follow the wizard to create your subscription. ### Build and Deploy Your Application -:::info Working Notes -- Rework to MTA Deployment -- Adapt sample -::: - The Personal Data Manager can't connect to your application running locally. Therefore, you need to deploy your application. -The general deployment is described in detail in [Deploy Using Manifest Files](../deployment/to-cf). Here's for short what you need to do. +The general deployment is described in detail in [Deploy to Cloud Foundry guide](../deployment/to-cf). Here's for short what you need to do. ### Prepare for Deployment From 31298c669fc10fe56c630ba75fb24e1ccc8bf9e4 Mon Sep 17 00:00:00 2001 From: Rene Jeglinsky Date: Wed, 13 Mar 2024 10:54:18 +0100 Subject: [PATCH 3/6] updates, new screenshot --- guides/data-privacy/assets/dpiCockpit.png | Bin 0 -> 20991 bytes guides/data-privacy/pdm.md | 179 +++++++++------------- 2 files changed, 76 insertions(+), 103 deletions(-) create mode 100644 guides/data-privacy/assets/dpiCockpit.png diff --git a/guides/data-privacy/assets/dpiCockpit.png b/guides/data-privacy/assets/dpiCockpit.png new file mode 100644 index 0000000000000000000000000000000000000000..0146078c35b30e1fd70d67c336ee83b3c9a04801 GIT binary patch literal 20991 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 +:::warning To follow this cookbook hands-on you need an enterprise account. The SAP Personal Data Manager service is currently only available for [enterprise accounts](https://discovery-center.cloud.sap/missiondetail/3019/3297/). An entitlement in trial accounts is not possible. ::: @@ -122,6 +122,7 @@ To restrict access to this sensitive data, the `PDMservice` is protected by the At this point, you are done with your application. Let's set up the SAP Personal Data Manager and try it out. + ## Connecting SAP Personal Data Manager @@ -130,126 +131,35 @@ A more comprehensive guide, incl. tutorials, is currently under development. For further details, see the [SAP Personal Data Manager Developer Guide](https://help.sap.com/docs/personal-data-manager/4adcd96ce00c4f1ba29ed11f646a5944/what-is-personal-data-manager). -### Subscribe to SAP Personal Data Manager Service - -[Subscribe to the service](https://help.sap.com/docs/PERSONAL_DATA_MANAGER/620a3ea6aaf64610accdd05cca9e3de2/ef10215655a540b6ba1c02a96e118d66.html) from the _Service Marketplace_ in the SAP BTP cockpit. - -![A screenshot of the tile in the cockpit for the SAP Personal Data Manager service.](assets/pdmCockpitCreate.png){width="300"} - -Follow the wizard to create your subscription. - ### Build and Deploy Your Application -The Personal Data Manager can't connect to your application running locally. Therefore, you need to deploy your application. +The Personal Data Manager can't connect to your application running locally. Therefore, you first need to deploy your application. In our sample, we added two manifest files using `cds add cf-manifest` and SAP HANA configuration using `cds add hana`. -The general deployment is described in detail in [Deploy to Cloud Foundry guide](../deployment/to-cf). Here's for short what you need to do. +The general deployment is described in detail in [Deploy Using Manifest Files](../deployment/to-cf). -### Prepare for Deployment - -Add SAP HANA Cloud configuration, as well as an approuter and an _mta.yaml_ to your project: +Make a production build: ```sh -cds add hana,approuter,mta +cds build --production ``` -Add `@sap/xssec` library, to make the authentication work: +Deploy your application: ```sh -npm install @sap/xssec +cf create-service-push ``` -[Learn more about authorization in CAP using Node.js.](../../node.js/authentication#jwt){.learn-more} - -### Enhance mta.yaml with DPI - -```yaml -modules: - - name: incidents-srv - ... - requires: - ... - - name: incidents-information // [!code ++] -... -resources: - ... - - name: incidents-information // [!code ++] - type: org.cloudfoundry.managed-service // [!code ++] - requires: // [!code ++] - - name: srv-api // [!code ++] - parameters: // [!code ++] - service-name: incidents-information // [!code ++] - service: data-privacy-integration-service // [!code ++] - service-plan: data-privacy-internal // [!code ++] - path: ./pdm-config.json // [!code ++] - config: // [!code ++] - xs-security: // [!code ++] - xsappname: incidents-information-${org}-$ // [!code ++]{space} - authorities: // [!code ++] - - $ACCEPT_GRANTED_AUTHORITIES // [!code ++] -``` -### Configure PDM Service - -::: code-group -```json [pdm-config.json] -{ - "dataPrivacyConfiguration": { - "configType": "information", - "applicationConfiguration": { - "applicationName": "incidents-information", - "applicationDescription": "DPI NextGen Bookshop CAP Reference Application", - "applicationTitle": "DPI NextGen Bookshop" - }, - "informationConfiguration": { - "applicationConfiguration": { - "dataSubjectDeletionAgent": "retention-manager", - "retentionApplicationName": "incidents-retention", - "disableDataSubjectCorrection": true, - "cacheControl": "no-cache" - }, - "components": [ - { - "componentName": "incidents-srv", - "componentBaseURL": "~{srv-api/srv-url}", - "serviceEndPoints": [ - { - "serviceName": "dpi-service", - "serviceFormat": "odata-v4", - "annotationFormat": "v4", - "serviceEndPoint": "/pdm", - "appPaginationEnabled": true, - "cacheControl": "no-cache" - } - ] - } - ] - } - } -} -``` -::: +### Subscribe to SAP Personal Data Manager Service -### Activate Access Checks in _xs-security.json_ +[Subscribe to the service](https://help.sap.com/docs/PERSONAL_DATA_MANAGER/620a3ea6aaf64610accdd05cca9e3de2/ef10215655a540b6ba1c02a96e118d66.html) from the _Service Marketplace_ in the SAP BTP cockpit. -Because we protected the `PDMservice`, we need to establish the security check properly. In particular, you need the _xs-security.json_ file to make the security check active. Add the following scope: +![A screenshot of the tile in the cockpit for the SAP Personal Data Manager service.](assets/pdmCockpitCreate.png){width="300"} -```json -{ - "scopes": [ - { - "name": "$XSAPPNAME.PersonalDataManagerUser", - "description": "Authority for Personal Data Manager", - "grant-as-authority-to-apps": [ - "$XSSERVICENAME(incidents-information)" - ] - } - ] -} -``` +Follow the wizard to create your subscription. -Here you define that your personal data manager service instance, called `incidents-information`, is allowed to access your CAP application granting the `PersonalDataManagerUser` role. ### Create Role Collections @@ -270,6 +180,69 @@ Application identifiers with **!b** are needed for the UI, and identifiers with [Learn more about defining a role collection in SAP BTP cockpit](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/4b20383efab341f181becf0a947a5498.html){.learn-more} + +### Create a Service Instance + +You need a configuration file, like the following, to create a service instance for the Personal Data Manager. + +`pdm-instance-config.json` +```json +{ + "xs-security": { + "xsappname": "incidents-mgmt", + "authorities": ["$ACCEPT_GRANTED_AUTHORITIES"] + }, + "fullyQualifiedApplicationName": "incidents-mgmt", + "appConsentServiceEnabled": true +} + + +``` + +Create a service instance using the SAP BTP cockpit or execute the following command: + +```sh +cf create-service personal-data-manager-service standard incidents-mgmt-pdm -c ./pdm-instance-config.json +``` + + + +### Bind the Service Instance to Your Application. + +With both the application deployed and the SAP Personal Data Manger service set up, you can now bind the service instance of the Personal Data Manager to your application. Use the URL of your application in a configuration file, such as the following example, which you need when binding a service instance. + +`pdm-binding-config.json` +```json +{ + "fullyQualifiedApplicationName": "incidents-mgmt", + "fullyQualifiedModuleName": "incidents-mgmt-srv", + "applicationTitle": "PDM Incidents", + "applicationTitleKey": "PDM Incidents", + "applicationURL": "https://incidents-mgmt-srv.cfapps.eu10.hana.ondemand.com/", // get the URL from the CF CLI command: cf apps + "endPoints": [ + { + "type": "odatav4", + "serviceName": "pdm-service", + "serviceTitle": "Incidents Management", + "serviceTitleKey": "IncidentsManagement", + "serviceURI": "pdm", + "hasGdprV4Annotations": true, + "cacheControl": "no-cache" + } + ] +} +``` + +Here the `applicationURL`, the `fullyQualifiedModuleName`, and the `serviceURI` have to be those of your Cloud Foundry deployment and your CAP service definition (_services-manifest.yaml_). + +Bind the service instance using the SAP BTP cockpit or execute the following command: + +```sh +cf bind-service incidents-mgmt-srv incidents-mgmt-pdm -c ./pdm-binding-config.json +``` + + + ## Using the SAP Personal Data Manager Application Open the SAP Personal Data Manager application from the _Instances and Subscriptions_ page in the SAP BTP cockpit. @@ -278,4 +251,4 @@ Open the SAP Personal Data Manager application from the _Instances and Subscript In the personal data manager application you can search for data subjects with _First Name_, _Last Name_, and _Date of Birth_, or alternatively with their _ID_. -![A screenshot of the SAP Personal Data Manager application.](assets/pdmApplication.png){width="500"} +![A screenshot of the SAP Personal Data Manager application.](assets/pdmApplication.png){width="500"} \ No newline at end of file From 841dd782a82bfb28c6aba5fd663d9a0d29f3c3a3 Mon Sep 17 00:00:00 2001 From: Rene Jeglinsky Date: Thu, 16 May 2024 08:33:10 +0200 Subject: [PATCH 4/6] added date of birth --- guides/data-privacy/annotations.md | 3 ++- guides/data-privacy/pdm.md | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/guides/data-privacy/annotations.md b/guides/data-privacy/annotations.md index b4508a845..3020eb243 100644 --- a/guides/data-privacy/annotations.md +++ b/guides/data-privacy/annotations.md @@ -33,7 +33,7 @@ Following the [best practice of separation of concerns](../domain-modeling#separ ::: code-group -```cds [srv/data-privacy.cds] +```cds [db/data-privacy.cds] using { sap.capire.incidents as my } from '../db/schema'; annotate my.Customers with @PersonalData : { @@ -45,6 +45,7 @@ annotate my.Customers with @PersonalData : { lastName @PersonalData.IsPotentiallyPersonal; email @PersonalData.IsPotentiallyPersonal; phone @PersonalData.IsPotentiallyPersonal; + dateOfBirth @PersonalData.IsPotentiallyPersonal; creditCardNo @PersonalData.IsPotentiallySensitive; }; diff --git a/guides/data-privacy/pdm.md b/guides/data-privacy/pdm.md index f02ffe41d..d3df9a287 100644 --- a/guides/data-privacy/pdm.md +++ b/guides/data-privacy/pdm.md @@ -74,7 +74,10 @@ service PDMService @(path: '/pdm') { surname: lastName, given : firstName }, - email: [{address: email}] + bday : dateOfBirth, + email: [{ + type : #preferred, + address: email}] }); }; From 83c95f064ec0e88bc24da7b320bd3a511638c2d1 Mon Sep 17 00:00:00 2001 From: Rene Jeglinsky Date: Thu, 16 May 2024 09:01:23 +0200 Subject: [PATCH 5/6] new screenshot --- guides/data-privacy/assets/dpingCockpit.png | Bin 0 -> 28339 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 guides/data-privacy/assets/dpingCockpit.png diff --git a/guides/data-privacy/assets/dpingCockpit.png b/guides/data-privacy/assets/dpingCockpit.png new file mode 100644 index 0000000000000000000000000000000000000000..a5b0a3398f85fb48ef5db63fc08f54c5b9968acc GIT binary patch literal 28339 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 literal 0 HcmV?d00001 From d229f20aa879bb8680cb4690e88395ed656aeebf Mon Sep 17 00:00:00 2001 From: Rene Jeglinsky Date: Thu, 16 May 2024 09:01:36 +0200 Subject: [PATCH 6/6] re-added sections --- guides/data-privacy/pdm.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/guides/data-privacy/pdm.md b/guides/data-privacy/pdm.md index d3df9a287..42dae378e 100644 --- a/guides/data-privacy/pdm.md +++ b/guides/data-privacy/pdm.md @@ -134,7 +134,39 @@ Next, we will briefly detail the integration to SAP Personal Data Manager. A more comprehensive guide, incl. tutorials, is currently under development. For further details, see the [SAP Personal Data Manager Developer Guide](https://help.sap.com/docs/personal-data-manager/4adcd96ce00c4f1ba29ed11f646a5944/what-is-personal-data-manager). +### Activate Access Checks in _xs-security.json_ +Because we protected the `PDMservice`, we need to establish the security check properly. In particular, you need the _xs-security.json_ file to make the security check active. The following _xs-security.json_ is from our sample. + +```json +{ + "xsappname": "incidents-mgmt", + "tenant-mode": "shared", + "scopes": [ + { + "name": "$XSAPPNAME.PersonalDataManagerUser", + "description": "Authority for Personal Data Manager", + "grant-as-authority-to-apps": [ + "$XSSERVICENAME(pdm)" + ] + } + ] +} +``` + +Here you define that your personal data manager service instance, called `pdm`, is allowed to access your CAP application granting the `PersonalDataManagerUser` role. + + + +### Add `@sap/xssec` Library + +To make the authentication work, you have to enable the security strategy by installing the `@sap/xssec` package: + +```sh +npm install @sap/xssec +``` + +[Learn more about authorization in CAP using Node.js.](../../node.js/authentication#jwt){.learn-more} ### Build and Deploy Your Application