From de62cfbf6bb669f9b0954daa75c28333571ade2d Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Tue, 30 Sep 2025 13:47:21 +0200 Subject: [PATCH 01/58] Initial structural change, still Java elements remaining --- README.md | 345 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 287 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index e550f6d3..8c625016 100755 --- a/README.md +++ b/README.md @@ -2,59 +2,63 @@ # Attachments Plugin -The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/node.js/cds-plugins#cds-plugin-packages) that provides out-of-the box asset storage and handling by using an *aspect* `Attachments`. It also provides a CAP-level, easy to use integration of the SAP Object Store. +The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/node.js/cds-plugins#cds-plugin-packages) that provides out-of-the box asset storage and handling by using an [*aspect*](https://cap.cloud.sap/docs/cds/cdl#aspects) called `Attachments`. It also provides a CAP-level, easy-to-use integration of the [SAP Object Store](http://help.sap.com/docs/object-store/object-store-service-on-sap-btp/what-is-object-storeC). ### Table of Contents -- [Setup](#setup) -- [Use `Attachments`](#use-attachments) -- [Test-drive Locally](#test-drive-locally) -- [Using SAP Object Store](#using-sap-object-store) -- [Using SAP Malware Scanning service](#using-sap-malware-scanning-service) -- [Multitenancy](#multi-tenancy) -- [Contributing](#contributing) -- [Code of Conduct](#code-of-conduct) -- [Licensing](#licensing) - - -## Setup - - - -To enable attachments, simply add this self-configuring plugin package to your project: - + + +* [Quick Start](#quick-start) +* [Local Walk-Through](#local-walk-through) +* [Usage](#usage) + * [Package Setup](#package-setup) + * [Changes in the CDS Models](#changes-in-the-cds-models) + * [Storage Targets](#storage-targets) + * [Malware Scanner](#malware-scanner) + * [Outbox](#outbox) ? + * [Restore Endpoint](#restore-endpoint) ? + * [Motivation](#motivation) + * [HTTP Endpoint](#http-endpoint) + * [Security](#security) + * [Visibility Control](#visibility-control-for-attachments-ui-facet-generation) + * [Non-Draft Uploading](non-draft-upload) +* [Releases](#releases) ? +* [Minimum UI5 and CAP NodeJS Version](#minimum-ui5-and-cap-nodejs-version) +* [Architecture Overview](#architecture-overview) + * [Design](#design) ? + * [Multitenancy](#multitenancy) + * [Object Stores](#object-stores) ? + * [Model Texts](#model-texts) ? +* [Support, Feedback, Contributing ](#support-feedback-and-contributing) +* [Code of Conduct](#code-of-conduct) +* [Licensing](#licensing) + + +## Quick Start + +For a quick setup with in-memory storage: + +- The plugin is self-configuring as described in [Package Setup]. To enable attachments, simply add the plugin package to your project: ```sh npm add @cap-js/attachments -``` - -In this guide, we use the [Incidents Management reference sample app](https://github.com/cap-js/incidents-app) as the base application, to add `Attachments` type to the CDS model. - -> [!Note] -> To be able to use the Fiori *uploadTable* feature, you must ensure 1.121.0/ 1.122.0/ ^1.125.0 SAPUI5 version is updated in the application's _index.html_ - - -## Use Attachments - -> [!Note] -> To be able to use the plugin with Fiori elements UI, make sure *draft* is enabled for the entity. - -> The plugin currently supports file uploads up to **400 MB** in size per attachment. - -To use Attachments, simply add an element referring to the pre-defined `Attachments` type as follows: - + ``` +- To use Attachments, simply extend a CDS model by adding an element that refers to the pre-defined Attachments type (see [Changes in the CDS Models](changes-in-the-cds-models) for more details): ```cds using { Attachments } from '@cap-js/attachments'; -entity Incidents { - // ... - attachments: Composition of many Attachments; +entity Entity { + // ... + attachments: Composition of many Attachments; } ``` +In this guide, we use the [Incidents Management reference sample app](https://github.com/cap-js/incidents-app) as the base application to provide a demonstration how to use this plugin. + +For object store integration, see [Object Stores](#object-stores). -## Test-drive Locally -With the steps above, we have successfully set up asset handling for our reference application. Let's see that in action. -We can try out the scenarios where the attachments contents are stored locally in the database. + +## Local Walk-Through +With the steps above, we have successfully set up asset handling for our reference application. Let's see that in action by extending the Incidents Entity in the schema.cds file. We can try out the scenarios where the attachments contents are stored locally in the database. 1. **Start the server**: @@ -70,14 +74,65 @@ We can try out the scenarios where the attachments contents are stored locally i 3. The `Attachments` type has generated an out-of-the-box Attachments table (see 1) at the bottom of the Object page: Attachments Table -4. **Upload a file** by going into Edit mode and either using the **Upload** button on the Attachments table or by drag/drop. Then click the **Save** button to have that file stored that file in the dedicated resource (database, S3 bucket, etc.). We demonstrate this by uploading the PDF file from [_xmpl/db/content/Solar Panel Report.pdf_](./xmpl/db/content/Solar%20Panel%20Report.pdf): +4. **Upload a file** by going into Edit mode and either by clicking the **Upload** button above the Attachments table or by draging and droping the file into the Attachments table direcly. Then click the **Save** button to have that file stored in the dedicated resource (database, S3 bucket, etc.). The PDF file from [_xmpl/db/content/Solar Panel Report.pdf_](./xmpl/db/content/Solar%20Panel%20Report.pdf) can be used as an example: Upload an attachment -6. **Delete a file** by going into Edit mode and selecting the file(s) and by using the **Delete** button on the Attachments table. Then click the **Save** button to have that file deleted from the resource (database, S3 bucket, etc.). We demonstrate this by deleting the previously uploaded PDF file: `Solar Panel Report.pdf` +6. **Delete a file** by going into Edit mode, selecting the file, and pressing the **Delete** button above the Attachments table. Clicking the **Save** button will then delete that file from the resource (database, S3 bucket, etc.). Delete an attachment +## Usage + +### Package Setup + +The attachments plugin needs to be referenced in the package.json of the consuming CAP NodeJS application: -## Using SAP Object Store +```cds +“devDependencies”: { + “@cap-js/attachments”: ${latest-version}, + //... +} +``` + +This is done automatically by running `npm add @cap-js/attachments`. With this, the aspect Attachments can be used in the application's CDS model. + + +### Changes in the CDS Models + +To use the aspect `Attachments` on an existing entity, the corresponding entity needs to either include attachments as an element in the model definition or be extended in a CDS file in the `srv` module. In the quick start, the former was done, adding an element to the model definition: +```cds +using { Attachments } from '@cap-js/attachments'; + +entity Entity { + // ... + attachments: Composition of many Attachments; +} +``` + +The entity Incidents can also be extended in the `srv` module, as seen in the following example: +```cds +using { Attachments } from '@cap-js/attachments'; + +extend my.Incidents with { + attachments: Composition of many Attachments; +} + +service ProcessorService { + entity Incidents as projection on my.Incidents +} +``` + +Both methods directly add the respective UI Facet. Take note that in order to use the plugin with Fiori elements UI, be sure that *draft* is enabled for the entity using `@odata.draft.enabled`. + + +### Storage Targets + +By default, the plugin operates without a dedicated storage target, storing attachments directly in the underlying database. + +Other available storage targets: +- AWS +- Local file system as a storage backend (only for testing scenarios) + +When using a dedicated storage target, the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file is kept in the database, as defined in the CDS model. For using SAP Object Store, you must already have a SAP Object Store service instance with a bucket which you can access. To connect it, follow this setup. @@ -95,31 +150,53 @@ For using SAP Object Store, you must already have a SAP Object Store service ins cds bind objectstore -2 : --kind s3 ``` -## Using SAP Malware Scanning Service - -For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serviceCatalog/malware-scanning-service), you must already have a service instance which you can access. +### Malware Scanner -1. To bind to the service continue with the steps below. +The malware scanner is used in the AttachmentService to scan attachments. +For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serviceCatalog/malware-scanning-service), you must already have a service instance which you can access and run the following command: ```sh cds bind malware-scanner -2 : ``` By default, malware scanning is enabled for all profiles except development profile. You can configure malware scanning by setting: - ```json "attachments": { "scan": true } ``` +If there is no malware scanner available, the attachments are automatically marked as Clean. + +Scan status codes: +- Clean: Only attachments with the status Clean are accessible. +- Scanning: Immediately after upload, the attachment is marked as Scanning. Depending on processing speed, it may already appear as Clean when the page is reloaded. +- Unscanned: Attachment is still unscanned. +- Failed: Scanning failed. +- Infected: The attachment is infected. + +> [!Note] +> The plugin currently supports file uploads up to 400 MB in size per attachment. + + +### Outbox + +In this plugin the [persistent outbox](https://cap.cloud.sap/docs/java/outbox#persistent) is used to mark attachments as deleted. When using this plugin, the persistent outbox is enabled by default. In the capire documentation of the [persistent outbox](https://cap.cloud.sap/docs/java/outbox#persistent) is it described how to overwrite the default outbox configuration. + +If the default is used, nothing must be done. + -## Visibility control for Attachments UI Facet generation +### Restore Endpoint -By setting the `@attachments.disable_facet` property to `true`, developers can hide the plugin from the UI achieving visibility. -This feature is particularly useful in scenarios where the visibility of the plugin needs to be dynamically controlled based on certain conditions. +The attachment service has an event `RESTORE_ATTACHMENTS`. +This event can be called with a timestamp to restore externally stored attachments. -### Example Usage + +### Visibility Control for Attachments UI Facet Generation + +By setting the `@attachments.disable_facet` property to `true`, developers can hide the visibility of the plugin in the UI. This feature is particularly useful in scenarios where the visibility of the plugin needs to be dynamically controlled based on certain conditions. + +#### Example Usage ```cds entity Incidents { @@ -130,21 +207,44 @@ entity Incidents { ``` In this example, the `@attachments.disable_facet` is set to `true`, which means the plugin will be hidden by default. -## Non-Draft Upload Example +### Non-Draft Upload -For scenarios where the entity is not draft-enabled, see [`tests/non-draft-request.http`](./tests/non-draft-request.http) for sample `.http` requests to perform metadata creation and content upload. +For scenarios where the entity is not draft-enabled, see the sample [`tests/non-draft-request.http`](./tests/non-draft-request.http) to perform `.http` requests for metadata creation and content upload. The typical sequence includes: 1. **POST** to create attachment metadata 2. **PUT** to upload file content using the ID returned -> This is useful for non-draft-enabled entity sets. Make sure to replace `{{host}}`, `{{auth}}`, and IDs accordingly. +> Make sure to replace `{{host}}`, `{{auth}}`, and IDs accordingly. + +## Releases + +- The plugin is released to [WHERE?]. +- See the [changelog](./CHANGELOG.md) for the latest changes. + +## Minimum UI5 and CAP NodeJS Version + +| Component | Minimum Version | +|-----------|-----------------| +| CAP Node | 3.10.3 | +| UI5 | 1.136.0 | -## Multitenancy +To be able to use the Fiori `uploadTable` feature, you must ensure 1.121.0/ 1.122.0/ ^1.125.0 SAPUI5 version is updated in the application's `index.html` + + +## Architecture Overview +### Design +- [Design Details](./doc/Design.md) +- [Process of Creating, Reading and Deleting an Attachment](./doc/Processes.md) + +### Multitenancy The plugin supports multitenancy scenarios, allowing both shared and tenant-specific object store instances. +- When using SAP HANA as the storage target, multitenancy support depends on the consuming application. In most cases, multitenancy is achieved by using a dedicated schema for each tenant, providing strong data isolation at the database level. +- When using an [object store](storage-targets/cds-feature-attachments-oss) as the storage target, true multitenancy is not yet implemented (as of version 1.2.1). In this case, all blobs are stored in a single bucket, and tenant data is not separated. + > [!Note] > Starting from version 2.1.0, **separate mode** for object store instances is the default setting for multitenancy. > As of version 2.2.0, both the `standard` and `S3-standard` plans of the SAP Object Store offering are supported. @@ -172,7 +272,136 @@ To configure a shared object store instance, modify both the package.json files ``` To ensure tenant identification when using a shared object store instance, the plugin prefixes attachment URLs with the tenant ID. -## Contributing + +### Object Stores + +This artifact uses the an Object Store as the storage target instead of the underlying database. + +Then, the attachment is not stored in the underlying database; instead, it is saved in the respective Object Store, and only a reference to the file is kept in the database, as defined in the [CDS model](../../cds-feature-attachments/src/main/resources/cds/com.sap.cds/cds-feature-attachments/attachments.cds#L20). + +To do this, replace the `cds-feature-attachments` dependency in the `pom.xml` with: + +```xml + + com.sap.cds + cds-feature-attachments-oss + ${latest-version} + +``` + +A valid Object Store service binding is required for this, typically one provisioned through SAP BTP. See [Local development](#local-development) and [Deployment to Cloud Foundry](#deployment-to-cloud-foundry) on how to use this object store service binding. + +#### Local development + +For local development, bind to an Object Store service using the `cds bind` command as described in the [CAP documentation for hybrid testing](https://cap.cloud.sap/docs/advanced/hybrid-testing#services-on-cloud-foundry): + +```bash +cds bind +``` + +This will create an entry in the `.cdsrc-private.json` file with the service binding configuration. Then start the application with: + +```bash +cds bind --exec mvn spring-boot:run +``` + +If such a binding is not available, use the underlying database as the storage target instead of an Object Store, so use the dependency `cds-feature-attachments` (not `cds-feature-attachments-oss`). + +#### Deployment to Cloud Foundry +The corresponding entry in the [mta-file](https://cap.cloud.sap/docs/guides/deployment/to-cf#add-mta-yaml) possibly looks like: + +``` +_schema-version: '0.1' +ID: consuming-app +version: 1.0.0 +description: "App consuming the attachments plugin with an object store" +parameters: + ... +modules: + - name: consuming-app-srv +# ------------------------------------------------------------ + type: java + path: srv + parameters: + ... + properties: + ... + build-parameters: + ... + requires: + - name: consuming-app-hdi-container + - name: consuming-app-uaa + - name: cf-logging + - name: **object-store-service** +... +resources: + ... + - name: **object-store-service** + type: org.cloudfoundry.managed-service + parameters: + service: objectstore + service-plan: standard +``` + + +##### Tests + +The unit tests in this module do not need a binding to the respective object stores, run them with `mvn clean install`. + +The integration tests need a binding to a real object store. Run them with `mvn clean install -Pintegration-tests-oss`. +To set the binding, provide the following environment variables: +- AWS_S3_BUCKET +- AWS_S3_REGION +- AWS_S3_ACCESS_KEY_ID +- AWS_S3_SECRET_ACCESS_KEY + +##### Implementation details + +This artifact provides custom handlers for events from the [AttachmentService](../../cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/service/AttachmentService.java). + +##### Supported Storage Backends + +- **AWS S3** + +##### Multitenancy + +Multitenancy is not directly supported. All attachments are stored in a flat structure within the provided bucket, which might be shared across tenants. + + +### Model Texts + +In the model, several fields are annotated with the `@title` annotation. Default texts are provided in [35 languages](https://github.com/cap-java/cds-feature-attachments/tree/main/cds-feature-attachments/src/main/resources/cds/com.sap.cds/cds-feature-attachments/_i18n). If these defaults are not sufficient for an application, they can be overwritten by applications with custom texts or translations. + +The following table gives an overview of the fields and the i18n codes: + +| Field Name | i18n Code | +|------------|-----------------------| +| `content` | `attachment_content` | +| `mimeType` | `attachment_mimeType` | +| `fileName` | `attachment_fileName` | +| `status` | `attachment_status` | +| `note` | `attachment_note` | + +In addition to the field names, header information (`@UI.HeaderInfo`) are also annotated: + +| Header Info | i18n Code | +|------------------|---------------| +| `TypeName` | `attachment` | +| `TypeNamePlural` | `attachments` | + + +## Monitoring & Logging + +To configure logging for the attachments plugin, add the following line to the `/srv/src/main/resources/application.yaml` of the consuming application: +``` +logging: + level: + ... + '[com.sap.cds.feature.attachments]': DEBUG +... +``` + +## Support, Feedback, and Contributing This project is open to feature requests/suggestions, bug reports etc. via [GitHub issues](https://github.com/cap-js/attachments/issues). Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](CONTRIBUTING.md). From dd21ae318038ca2532bf1b519452725e2a3fc38d Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Wed, 1 Oct 2025 16:03:25 +0200 Subject: [PATCH 02/58] Minor changes --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8c625016..e30fa6d6 100755 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ For using SAP Object Store, you must already have a SAP Object Store service ins ### Malware Scanner -The malware scanner is used in the AttachmentService to scan attachments. +The malware scanner is used in the `AttachmentService` to scan attachments. For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serviceCatalog/malware-scanning-service), you must already have a service instance which you can access and run the following command: ```sh @@ -250,13 +250,10 @@ The plugin supports multitenancy scenarios, allowing both shared and tenant-spec > As of version 2.2.0, both the `standard` and `S3-standard` plans of the SAP Object Store offering are supported. > **Important:** The `S3-standard` plan is no longer available for new subscriptions. For new object store instances, use the `standard` plan. -For multitenant applications, make sure to include `@cap-js/attachments` in the dependencies of both the application-level and mtx/sidecar package.json files. +For multitenant applications, `@cap-js/attachments` must be included in the dependencies of both the application-level and mtx/sidecar package.json files. ### Shared Object Store Instance -> [!Note] -> Ensure the shared object store instance is bound to the `mtx` application module before deployment. - To configure a shared object store instance, modify both the package.json files as follows: ```json @@ -270,7 +267,7 @@ To configure a shared object store instance, modify both the package.json files } } ``` -To ensure tenant identification when using a shared object store instance, the plugin prefixes attachment URLs with the tenant ID. +To ensure tenant identification when using a shared object store instance, the plugin prefixes attachment URLs with the tenant ID. Be sure the shared object store instance is bound to the `mtx` application module before deployment. ### Object Stores From 086c1396dcf57b132fc25d5328214eb5b3d5c301 Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Thu, 2 Oct 2025 09:29:31 +0200 Subject: [PATCH 03/58] Edits --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index e30fa6d6..06eba646 100755 --- a/README.md +++ b/README.md @@ -272,9 +272,7 @@ To ensure tenant identification when using a shared object store instance, the p ### Object Stores -This artifact uses the an Object Store as the storage target instead of the underlying database. - -Then, the attachment is not stored in the underlying database; instead, it is saved in the respective Object Store, and only a reference to the file is kept in the database, as defined in the [CDS model](../../cds-feature-attachments/src/main/resources/cds/com.sap.cds/cds-feature-attachments/attachments.cds#L20). +The attachment is not stored in the underlying database; instead, it is saved in the respective Object Store, and only a reference to the file is kept in the database, as defined in the [CDS model](../../cds-feature-attachments/src/main/resources/cds/com.sap.cds/cds-feature-attachments/attachments.cds#L20). To do this, replace the `cds-feature-attachments` dependency in the `pom.xml` with: From 32c91f29ec9c7abe29bae315ecd39298587ff4b8 Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Tue, 7 Oct 2025 16:45:58 +0200 Subject: [PATCH 04/58] Tiny edits --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 06eba646..2239c80c 100755 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ Other available storage targets: When using a dedicated storage target, the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file is kept in the database, as defined in the CDS model. -For using SAP Object Store, you must already have a SAP Object Store service instance with a bucket which you can access. To connect it, follow this setup. +For using SAP Object Store, you must already have an SAP Object Store service instance with a bucket which you can access. To connect it, follow this setup. 1. Log in to Cloud Foundry: @@ -142,7 +142,7 @@ For using SAP Object Store, you must already have a SAP Object Store service ins cf login -a -o -s ``` -2. To bind to the service continue with the steps below. +2. To bind to the service, continue with the steps below. In the project directory, you can generate a new file _.cdsrc-private.json by running: From 6bc679e8d650cec920a81b109a364d3165647412 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 10:40:34 +0200 Subject: [PATCH 05/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2239c80c..79d02530 100755 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Attachments Plugin -The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/node.js/cds-plugins#cds-plugin-packages) that provides out-of-the box asset storage and handling by using an [*aspect*](https://cap.cloud.sap/docs/cds/cdl#aspects) called `Attachments`. It also provides a CAP-level, easy-to-use integration of the [SAP Object Store](http://help.sap.com/docs/object-store/object-store-service-on-sap-btp/what-is-object-storeC). +The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/node.js/cds-plugins#cds-plugin-packages) that provides out-of-the box asset storage and handling by using an [*aspect*](https://cap.cloud.sap/docs/cds/cdl#aspects) called `Attachments`. It also provides a CAP-level, easy-to-use integration of the [SAP Object Store](https://help.sap.com/docs/object-store/object-store-service-on-sap-btp/what-is-object-storeC). ### Table of Contents From a0e55fff4179a50a67c3328964c5636eedf8fb53 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 10:41:04 +0200 Subject: [PATCH 06/58] Apply suggestion from @KoblerS Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 79d02530..b80f0890 100755 --- a/README.md +++ b/README.md @@ -33,7 +33,6 @@ The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/n * [Code of Conduct](#code-of-conduct) * [Licensing](#licensing) - ## Quick Start For a quick setup with in-memory storage: From f2577a243ed28f58f7e5e3f74c4c5541f6f728fc Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 10:51:49 +0200 Subject: [PATCH 07/58] Apply suggestion from @KoblerS Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b80f0890..a3e128cc 100755 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ To use the aspect `Attachments` on an existing entity, the corresponding entity ```cds using { Attachments } from '@cap-js/attachments'; -entity Entity { +entity Incidents { // ... attachments: Composition of many Attachments; } From 21fecdea831edf725a31991f48a2a1b40deeb2a1 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 10:51:57 +0200 Subject: [PATCH 08/58] Apply suggestion from @KoblerS Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a3e128cc..1a9f9f1d 100755 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ Other available storage targets: When using a dedicated storage target, the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file is kept in the database, as defined in the CDS model. -For using SAP Object Store, you must already have an SAP Object Store service instance with a bucket which you can access. To connect it, follow this setup. +For using SAP Object Store, you must already have an SAP Object Store service instance with a storage target which you can access. To connect it, follow this setup. 1. Log in to Cloud Foundry: From 6c36ce28e62065d831d53c603d4eb8aa6e8fb2b3 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 10:53:23 +0200 Subject: [PATCH 09/58] Apply suggestion from @KoblerS Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a9f9f1d..c0bff6ca 100755 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ With the steps above, we have successfully set up asset handling for our referen The attachments plugin needs to be referenced in the package.json of the consuming CAP NodeJS application: ```cds -“devDependencies”: { +"devDependencies": { “@cap-js/attachments”: ${latest-version}, //... } From 0509d7d66dba8c375ea95f469bcb09d196dda7c6 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 10:53:32 +0200 Subject: [PATCH 10/58] Apply suggestion from @KoblerS Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c0bff6ca..6d0648e6 100755 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ The attachments plugin needs to be referenced in the package.json of the consumi ```cds "devDependencies": { - “@cap-js/attachments”: ${latest-version}, + "@cap-js/attachments": "", //... } ``` From c0bcc5e06c9fda667a7686c99eaaa4c3fb3aea03 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 10:56:12 +0200 Subject: [PATCH 11/58] Apply suggestion from @KoblerS Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d0648e6..971c27e4 100755 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ By default, the plugin operates without a dedicated storage target, storing atta Other available storage targets: - AWS -- Local file system as a storage backend (only for testing scenarios) +- Local mock file system (only for testing scenarios) When using a dedicated storage target, the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file is kept in the database, as defined in the CDS model. From fc9aa95c7682fabb3a0c3e1af809ab1b31190dd9 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 11:21:42 +0200 Subject: [PATCH 12/58] Apply suggestion from @KoblerS Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 971c27e4..811cdb23 100755 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ Scan status codes: ### Outbox -In this plugin the [persistent outbox](https://cap.cloud.sap/docs/java/outbox#persistent) is used to mark attachments as deleted. When using this plugin, the persistent outbox is enabled by default. In the capire documentation of the [persistent outbox](https://cap.cloud.sap/docs/java/outbox#persistent) is it described how to overwrite the default outbox configuration. +In this plugin the [persistent outbox](https://cap.cloud.sap/docs/java/outbox#persistent) is used to mark attachments as deleted. When using this plugin, the persistent outbox is enabled by default. In the capire documentation of the [persistent outbox](https://cap.cloud.sap/docs/java/outbox#persistent) it is described how to overwrite the default outbox configuration. If the default is used, nothing must be done. From 1ebe5b8a8cb99340e2efac61a8fb2ed38476da7f Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 12:57:38 +0200 Subject: [PATCH 13/58] Apply suggestion from @KoblerS Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index af2c6574..b7c75cc3 100755 --- a/README.md +++ b/README.md @@ -285,7 +285,6 @@ To configure a shared object store instance, modify both the package.json files ``` To ensure tenant identification when using a shared object store instance, the plugin prefixes attachment URLs with the tenant ID. Be sure the shared object store instance is bound to the `mtx` application module before deployment. - ### Object Stores The attachment is not stored in the underlying database; instead, it is saved in the respective Object Store, and only a reference to the file is kept in the database, as defined in the [CDS model](../../cds-feature-attachments/src/main/resources/cds/com.sap.cds/cds-feature-attachments/attachments.cds#L20). From 92a88c9966e5cf18a5e74ff4d203a5a158382702 Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Wed, 8 Oct 2025 13:23:38 +0200 Subject: [PATCH 14/58] Edits from Simon comments --- README.md | 45 +++++++++++---------------------------------- 1 file changed, 11 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index b7c75cc3..3881ddfb 100755 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/n For a quick setup with in-memory storage: -- The plugin is self-configuring as described in [Package Setup]. To enable attachments, simply add the plugin package to your project: +- The plugin is self-configuring as described in [Package Setup](#package-setup). To enable attachments, simply add the plugin package to your project: ```sh npm add @cap-js/attachments ``` @@ -45,7 +45,7 @@ For a quick setup with in-memory storage: ```cds using { Attachments } from '@cap-js/attachments'; -entity Entity { +entity Incidents { // ... attachments: Composition of many Attachments; } @@ -120,7 +120,7 @@ service ProcessorService { } ``` -Both methods directly add the respective UI Facet. Take note that in order to use the plugin with Fiori elements UI, be sure that *draft* is enabled for the entity using `@odata.draft.enabled`. +Both methods directly add the respective UI Facet. Take note that in order to use the plugin with Fiori elements UI, be sure that [`draft` is enabled](https://cap.cloud.sap/docs/advanced/fiori#enabling-draft-with-odata-draft-enabled) for the entity using `@odata.draft.enabled`. ### Storage Targets @@ -138,7 +138,7 @@ For using SAP Object Store, you must already have an SAP Object Store service in 1. Log in to Cloud Foundry: ```sh - cf login -a -o -s + cf login -a -o -s --sso ``` 2. To bind to the service, continue with the steps below. @@ -158,7 +158,7 @@ For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serv cds bind malware-scanner -2 : ``` -By default, malware scanning is enabled for all profiles except development profile. You can configure malware scanning by setting: +By default, malware scanning is enabled for all profiles unless no storage provider has been specified. You can configure malware scanning by setting: ```json "attachments": { "scan": true @@ -175,7 +175,7 @@ Scan status codes: - Infected: The attachment is infected. > [!Note] -> The plugin currently supports file uploads up to 400 MB in size per attachment. +> The plugin currently supports file uploads [up to 400 MB in size per attachment](https://help.sap.com/docs/malware-scanning-servce/sap-malware-scanning-service/what-is-sap-malware-scanning-service). ### Outbox @@ -287,19 +287,7 @@ To ensure tenant identification when using a shared object store instance, the p ### Object Stores -The attachment is not stored in the underlying database; instead, it is saved in the respective Object Store, and only a reference to the file is kept in the database, as defined in the [CDS model](../../cds-feature-attachments/src/main/resources/cds/com.sap.cds/cds-feature-attachments/attachments.cds#L20). - -To do this, replace the `cds-feature-attachments` dependency in the `pom.xml` with: - -```xml - - com.sap.cds - cds-feature-attachments-oss - ${latest-version} - -``` - -A valid Object Store service binding is required for this, typically one provisioned through SAP BTP. See [Local development](#local-development) and [Deployment to Cloud Foundry](#deployment-to-cloud-foundry) on how to use this object store service binding. +A valid Object Store service binding is required, typically one provisioned through SAP BTP. See [Local development](#local-development) and [Deployment to Cloud Foundry](#deployment-to-cloud-foundry) on how to use this object store service binding. #### Local development @@ -312,11 +300,9 @@ cds bind This will create an entry in the `.cdsrc-private.json` file with the service binding configuration. Then start the application with: ```bash -cds bind --exec mvn spring-boot:run +cds watch --profile hybrid ``` -If such a binding is not available, use the underlying database as the storage target instead of an Object Store, so use the dependency `cds-feature-attachments` (not `cds-feature-attachments-oss`). - #### Deployment to Cloud Foundry The corresponding entry in the [mta-file](https://cap.cloud.sap/docs/guides/deployment/to-cf#add-mta-yaml) possibly looks like: @@ -330,7 +316,7 @@ parameters: modules: - name: consuming-app-srv # ------------------------------------------------------------ - type: java + type: nodejs path: srv parameters: ... @@ -356,28 +342,19 @@ resources: ##### Tests -The unit tests in this module do not need a binding to the respective object stores, run them with `mvn clean install`. +The unit tests in this module do not need a binding to the respective object stores, run them with `npm install`. To achieve a clean install, the comman `rm -rf node_modules` should be used before installation. -The integration tests need a binding to a real object store. Run them with `mvn clean install -Pintegration-tests-oss`. +The integration tests need a binding to a real object store. Run them with `npm install -Pintegration-tests-oss`. To set the binding, provide the following environment variables: - AWS_S3_BUCKET - AWS_S3_REGION - AWS_S3_ACCESS_KEY_ID - AWS_S3_SECRET_ACCESS_KEY -##### Implementation details - -This artifact provides custom handlers for events from the [AttachmentService](../../cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/service/AttachmentService.java). - ##### Supported Storage Backends - **AWS S3** -##### Multitenancy - -Multitenancy is not directly supported. All attachments are stored in a flat structure within the provided bucket, which might be shared across tenants. - - ### Model Texts In the model, several fields are annotated with the `@title` annotation. Default texts are provided in [35 languages](https://github.com/cap-java/cds-feature-attachments/tree/main/cds-feature-attachments/src/main/resources/cds/com.sap.cds/cds-feature-attachments/_i18n). If these defaults are not sufficient for an application, they can be overwritten by applications with custom texts or translations. From e0bb57df630f85eb76aa28ea8e6675b8015f0f0b Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 16:27:50 +0200 Subject: [PATCH 15/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3881ddfb..6f2d2691 100755 --- a/README.md +++ b/README.md @@ -344,7 +344,7 @@ resources: The unit tests in this module do not need a binding to the respective object stores, run them with `npm install`. To achieve a clean install, the comman `rm -rf node_modules` should be used before installation. -The integration tests need a binding to a real object store. Run them with `npm install -Pintegration-tests-oss`. +The integration tests need a binding to a real object store. Run them with `npm run test`. To set the binding, provide the following environment variables: - AWS_S3_BUCKET - AWS_S3_REGION From 514ee6eecd9000a6793f1812b9f2fe9ad16fddcf Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 16:28:13 +0200 Subject: [PATCH 16/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f2d2691..4431dcc5 100755 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Attachments Plugin -The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/node.js/cds-plugins#cds-plugin-packages) that provides out-of-the box asset storage and handling by using an [*aspect*](https://cap.cloud.sap/docs/cds/cdl#aspects) called `Attachments`. It also provides a CAP-level, easy-to-use integration of the [SAP Object Store](https://help.sap.com/docs/object-store/object-store-service-on-sap-btp/what-is-object-storeC). +The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/node.js/cds-plugins#cds-plugin-packages) that provides out-of-the box asset storage and handling by using an [*aspect*](https://cap.cloud.sap/docs/cds/cdl#aspects) called `Attachments`. It also provides a CAP-level, easy-to-use integration of the [SAP Object Store](https://help.sap.com/docs/object-store/object-store-service-on-sap-btp/what-is-object-store). ### Table of Contents From a4fba85a3c10b9712ce2c44407fdea76eeba314e Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 16:29:01 +0200 Subject: [PATCH 17/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4431dcc5..ff6982c5 100755 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ For a quick setup with in-memory storage: ```sh npm add @cap-js/attachments ``` -- To use Attachments, simply extend a CDS model by adding an element that refers to the pre-defined Attachments type (see [Changes in the CDS Models](changes-in-the-cds-models) for more details): +- To use Attachments, extend a CDS model by adding an element that refers to the pre-defined Attachments type (see [Changes in the CDS Models](#changes-in-the-cds-models) for more details): ```cds using { Attachments } from '@cap-js/attachments'; From e4e0fdb8c6205d96dbf12f3df036396e5a29f7f1 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 16:29:47 +0200 Subject: [PATCH 18/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ff6982c5..6cd65a29 100755 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ Other available storage targets: When using a dedicated storage target, the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file is kept in the database, as defined in the CDS model. -For using SAP Object Store, you must already have an SAP Object Store service instance with a storage target which you can access. To connect it, follow this setup. +For using SAP Object Store, you must already have an SAP Object Store service instance created. To bind it locally, follow this setup: 1. Log in to Cloud Foundry: From 2fe36232c0d9314cb75318866b48cf6a7f482c15 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 16:35:21 +0200 Subject: [PATCH 19/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6cd65a29..ddcbd25c 100755 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ The malware scanner is used in the `AttachmentService` to scan attachments. For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serviceCatalog/malware-scanning-service), you must already have a service instance which you can access and run the following command: ```sh - cds bind malware-scanner -2 : + cds bind --to ``` By default, malware scanning is enabled for all profiles unless no storage provider has been specified. You can configure malware scanning by setting: From 503d0ba711c622287cda7097b421d47726ec3e35 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 16:35:39 +0200 Subject: [PATCH 20/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ddcbd25c..18c5aefe 100755 --- a/README.md +++ b/README.md @@ -146,7 +146,7 @@ For using SAP Object Store, you must already have an SAP Object Store service in In the project directory, you can generate a new file _.cdsrc-private.json by running: ```sh - cds bind objectstore -2 : --kind s3 + cds bind --to ``` ### Malware Scanner From 38108bbb8b4d724de4e1b1813bb76f4feeca3be3 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 16:36:24 +0200 Subject: [PATCH 21/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 18c5aefe..fc06c39b 100755 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serv cds bind --to ``` -By default, malware scanning is enabled for all profiles unless no storage provider has been specified. You can configure malware scanning by setting: +By default, malware scanning is enabled for all profiles if a storage provider has been specified. You can configure malware scanning by setting: ```json "attachments": { "scan": true From 033ea6c723ec33236aa95e027c42b9bc33087dd6 Mon Sep 17 00:00:00 2001 From: Eric P Date: Wed, 8 Oct 2025 16:40:18 +0200 Subject: [PATCH 22/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fc06c39b..e3653de9 100755 --- a/README.md +++ b/README.md @@ -342,7 +342,7 @@ resources: ##### Tests -The unit tests in this module do not need a binding to the respective object stores, run them with `npm install`. To achieve a clean install, the comman `rm -rf node_modules` should be used before installation. +The unit tests in this module do not need a binding to the respective object stores, run them with `npm install`. To achieve a clean install, the command `rm -rf node_modules` should be used before installation. The integration tests need a binding to a real object store. Run them with `npm run test`. To set the binding, provide the following environment variables: From e3d12174adf75575ecb0b5434a3c7b61ce6ddf4d Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Wed, 8 Oct 2025 16:41:14 +0200 Subject: [PATCH 23/58] Edits --- README.md | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index e3653de9..65325142 100755 --- a/README.md +++ b/README.md @@ -17,9 +17,6 @@ The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/n * [Malware Scanner](#malware-scanner) * [Outbox](#outbox) ? * [Restore Endpoint](#restore-endpoint) ? - * [Motivation](#motivation) - * [HTTP Endpoint](#http-endpoint) - * [Security](#security) * [Visibility Control](#visibility-control-for-attachments-ui-facet-generation) * [Non-Draft Uploading](non-draft-upload) * [Releases](#releases) ? @@ -29,6 +26,7 @@ The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/n * [Multitenancy](#multitenancy) * [Object Stores](#object-stores) ? * [Model Texts](#model-texts) ? +* [Monitoring & Logging](#monitoring--logging) * [Support, Feedback, Contributing ](#support-feedback-and-contributing) * [Code of Conduct](#code-of-conduct) * [Licensing](#licensing) @@ -68,7 +66,7 @@ With the steps above, we have successfully set up asset handling for our referen 2. **Navigate to the object page** of the incident `Solar panel broken`: - Go to [Object page for incident **Solar panel broken**](http://localhost:4004/incidents/app/#/Incidents(ID=3583f982-d7df-4aad-ab26-301d4a157cd7,IsActiveEntity=true)) + Go to object page for incident **Solar panel broken** 3. The `Attachments` type has generated an out-of-the-box Attachments table (see 1) at the bottom of the Object page: Attachments Table @@ -76,7 +74,7 @@ With the steps above, we have successfully set up asset handling for our referen 4. **Upload a file** by going into Edit mode and either by clicking the **Upload** button above the Attachments table or by draging and droping the file into the Attachments table direcly. Then click the **Save** button to have that file stored in the dedicated resource (database, S3 bucket, etc.). The PDF file from [_xmpl/db/content/Solar Panel Report.pdf_](./xmpl/db/content/Solar%20Panel%20Report.pdf) can be used as an example: Upload an attachment -6. **Delete a file** by going into Edit mode, selecting the file, and pressing the **Delete** button above the Attachments table. Clicking the **Save** button will then delete that file from the resource (database, S3 bucket, etc.). +5. **Delete a file** by going into Edit mode, selecting the file, and pressing the **Delete** button above the Attachments table. Clicking the **Save** button will then delete that file from the resource (database, S3 bucket, etc.). Delete an attachment ## Usage @@ -153,7 +151,7 @@ For using SAP Object Store, you must already have an SAP Object Store service in The malware scanner is used in the `AttachmentService` to scan attachments. -For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serviceCatalog/malware-scanning-service), you must already have a service instance which you can access and run the following command: +For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serviceCatalog/malware-scanning-service), you must already have a service instance which you can access. To bind it, run the following command: ```sh cds bind --to ``` @@ -236,7 +234,7 @@ The typical sequence includes: ## Releases -- The plugin is released to [WHERE?]. +- The plugin is released to [NPM Registry](https://www.npmjs.com/package/@cap-js/attachments) and [GitHub Releases](https://github.com/cap-js/attachments/releases). - See the [changelog](./CHANGELOG.md) for the latest changes. ## Minimum UI5 and CAP NodeJS Version @@ -259,7 +257,7 @@ To be able to use the Fiori `uploadTable` feature, you must ensure 1.121.0/ The plugin supports multitenancy scenarios, allowing both shared and tenant-specific object store instances. - When using SAP HANA as the storage target, multitenancy support depends on the consuming application. In most cases, multitenancy is achieved by using a dedicated schema for each tenant, providing strong data isolation at the database level. -- When using an [object store](storage-targets/cds-feature-attachments-oss) as the storage target, true multitenancy is not yet implemented (as of version 1.2.1). In this case, all blobs are stored in a single bucket, and tenant data is not separated. +- When using an [object store](storage-targets/cds-feature-attachments-oss) as the storage target, true multitenancy is not yet implemented (as of version 2.1.0). In this case, all blobs are stored in a single bucket, and tenant data is not separated. > [!Note] > Starting from version 2.1.0, **separate mode** for object store instances is the default setting for multitenancy. @@ -268,7 +266,7 @@ The plugin supports multitenancy scenarios, allowing both shared and tenant-spec For multitenant applications, `@cap-js/attachments` must be included in the dependencies of both the application-level and mtx/sidecar package.json files. -### Shared Object Store Instance +#### Shared Object Store Instance To configure a shared object store instance, modify both the package.json files as follows: @@ -287,7 +285,7 @@ To ensure tenant identification when using a shared object store instance, the p ### Object Stores -A valid Object Store service binding is required, typically one provisioned through SAP BTP. See [Local development](#local-development) and [Deployment to Cloud Foundry](#deployment-to-cloud-foundry) on how to use this object store service binding. +A valid Object Store service binding is required, typically one provisioned through SAP BTP. See [Local Development](#local-development) and [Deployment to Cloud Foundry](#deployment-to-cloud-foundry) on how to use this object store service binding. #### Local development @@ -379,12 +377,18 @@ In addition to the field names, header information (`@UI.HeaderInfo`) are also a ## Monitoring & Logging -To configure logging for the attachments plugin, add the following line to the `/srv/src/main/resources/application.yaml` of the consuming application: +To configure logging for the attachments plugin, add the following line to the `package.json` of the consuming application: ``` -logging: - level: - ... - '[com.sap.cds.feature.attachments]': DEBUG +{ + "cds": { + "log": { + "levels": { + ... + '[com.sap.cds.attachments]': DEBUG + } + } + } +} ... ``` From 339b381e29849e2e35ee245b73ab89744fcc1d98 Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Wed, 8 Oct 2025 17:31:32 +0200 Subject: [PATCH 24/58] More edits --- README.md | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 65325142..a70ec3b9 100755 --- a/README.md +++ b/README.md @@ -163,7 +163,7 @@ By default, malware scanning is enabled for all profiles if a storage provider h } ``` -If there is no malware scanner available, the attachments are automatically marked as Clean. +If there is no malware scanner available and the scanner is not disabled, then the uploading will fail. Scan status codes: - Clean: Only attachments with the status Clean are accessible. @@ -176,24 +176,9 @@ Scan status codes: > The plugin currently supports file uploads [up to 400 MB in size per attachment](https://help.sap.com/docs/malware-scanning-servce/sap-malware-scanning-service/what-is-sap-malware-scanning-service). -### Outbox - -In this plugin the [persistent outbox](https://cap.cloud.sap/docs/java/outbox#persistent) is used to mark attachments as deleted. When using this plugin, the persistent outbox is enabled by default. In the capire documentation of the [persistent outbox](https://cap.cloud.sap/docs/java/outbox#persistent) it is described how to overwrite the default outbox configuration. - -If the default is used, nothing must be done. - - -### Restore Endpoint - -The attachment service has an event `RESTORE_ATTACHMENTS`. -This event can be called with a timestamp to restore externally stored attachments. - -By setting the `@UI.Hidden` property to `true`, developers can hide the plugin from the UI achieving visibility. -This feature is particularly useful in scenarios where the visibility of the plugin needs to be dynamically controlled based on certain conditions. - ### Visibility Control for Attachments UI Facet Generation -By setting the `@attachments.disable_facet` property to `true`, developers can hide the visibility of the plugin in the UI. This feature is particularly useful in scenarios where the visibility of the plugin needs to be dynamically controlled based on certain conditions. +By setting the `@UI.Hidden` property to `true`, developers can hide the visibility of the plugin in the UI. This feature is particularly useful in scenarios where the visibility of the plugin needs to be dynamically controlled based on certain conditions. #### Example Usage @@ -241,17 +226,12 @@ The typical sequence includes: | Component | Minimum Version | |-----------|-----------------| -| CAP Node | 3.10.3 | +| CAP Node | 8.0.0 | | UI5 | 1.136.0 | -To be able to use the Fiori `uploadTable` feature, you must ensure 1.121.0/ 1.122.0/ ^1.125.0 SAPUI5 version is updated in the application's `index.html` ## Architecture Overview -### Design -- [Design Details](./doc/Design.md) -- [Process of Creating, Reading and Deleting an Attachment](./doc/Processes.md) - ### Multitenancy The plugin supports multitenancy scenarios, allowing both shared and tenant-specific object store instances. @@ -355,7 +335,7 @@ To set the binding, provide the following environment variables: ### Model Texts -In the model, several fields are annotated with the `@title` annotation. Default texts are provided in [35 languages](https://github.com/cap-java/cds-feature-attachments/tree/main/cds-feature-attachments/src/main/resources/cds/com.sap.cds/cds-feature-attachments/_i18n). If these defaults are not sufficient for an application, they can be overwritten by applications with custom texts or translations. +In the model, several fields are annotated with the `@title` annotation. Default texts are provided in [2 languages](https://github.com/cap-js/attachments/tree/main/_i18n). If these defaults are not sufficient for an application, they can be overwritten by applications with custom texts or translations. The following table gives an overview of the fields and the i18n codes: @@ -384,7 +364,7 @@ To configure logging for the attachments plugin, add the following line to the ` "log": { "levels": { ... - '[com.sap.cds.attachments]': DEBUG + attachments: DEBUG } } } From 9b6f6a542f781eb59dcd6ef4fa99fe123a369b81 Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Thu, 9 Oct 2025 13:57:22 +0200 Subject: [PATCH 25/58] More edits --- README.md | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index a70ec3b9..d2f2782d 100755 --- a/README.md +++ b/README.md @@ -15,17 +15,14 @@ The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/n * [Changes in the CDS Models](#changes-in-the-cds-models) * [Storage Targets](#storage-targets) * [Malware Scanner](#malware-scanner) - * [Outbox](#outbox) ? - * [Restore Endpoint](#restore-endpoint) ? * [Visibility Control](#visibility-control-for-attachments-ui-facet-generation) * [Non-Draft Uploading](non-draft-upload) -* [Releases](#releases) ? +* [Releases](#releases) * [Minimum UI5 and CAP NodeJS Version](#minimum-ui5-and-cap-nodejs-version) * [Architecture Overview](#architecture-overview) - * [Design](#design) ? * [Multitenancy](#multitenancy) - * [Object Stores](#object-stores) ? - * [Model Texts](#model-texts) ? + * [Object Stores](#object-stores) + * [Model Texts](#model-texts) * [Monitoring & Logging](#monitoring--logging) * [Support, Feedback, Contributing ](#support-feedback-and-contributing) * [Code of Conduct](#code-of-conduct) @@ -126,7 +123,7 @@ Both methods directly add the respective UI Facet. Take note that in order to us By default, the plugin operates without a dedicated storage target, storing attachments directly in the underlying database. Other available storage targets: -- AWS +- AWS - Local mock file system (only for testing scenarios) When using a dedicated storage target, the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file is kept in the database, as defined in the CDS model. @@ -147,6 +144,8 @@ For using SAP Object Store, you must already have an SAP Object Store service in cds bind --to ``` +See [Object Stores](#object-stores) for further information on SAP Object Store. + ### Malware Scanner The malware scanner is used in the `AttachmentService` to scan attachments. @@ -339,20 +338,19 @@ In the model, several fields are annotated with the `@title` annotation. Default The following table gives an overview of the fields and the i18n codes: -| Field Name | i18n Code | -|------------|-----------------------| -| `content` | `attachment_content` | -| `mimeType` | `attachment_mimeType` | -| `fileName` | `attachment_fileName` | -| `status` | `attachment_status` | -| `note` | `attachment_note` | +| Field Name | i18n Code | +|------------|--------------| +| `mimeType` | `MediaType` | +| `fileName` | `FileName` | +| `status` | `ScanStatus` | +| `note` | `note` | In addition to the field names, header information (`@UI.HeaderInfo`) are also annotated: | Header Info | i18n Code | |------------------|---------------| -| `TypeName` | `attachment` | -| `TypeNamePlural` | `attachments` | +| `TypeName` | `Attachment` | +| `TypeNamePlural` | `Attachments` | ## Monitoring & Logging From 2dbb42b0addfcd1a503db506d02d7294442118ef Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Thu, 9 Oct 2025 14:59:36 +0200 Subject: [PATCH 26/58] Recommending to use incidents-app within tests folder and not xmpl --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d2f2782d..33cbc8da 100755 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ entity Incidents { } ``` -In this guide, we use the [Incidents Management reference sample app](https://github.com/cap-js/incidents-app) as the base application to provide a demonstration how to use this plugin. +In this guide, we use the [Incidents Management reference sample app](https://github.com/cap-js/incidents-app) as the base application to provide a demonstration how to use this plugin. A miniature version of this app can be found within the [tests](https://github.com/cap-js/attachments/tree/main/tests/incidents-app) directory for local testing. For object store integration, see [Object Stores](#object-stores). From d34b7aa7aba639e1e2852c33b691d2af622737d8 Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Thu, 9 Oct 2025 16:26:12 +0200 Subject: [PATCH 27/58] Lisa edits --- README.md | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 33cbc8da..5f6597c7 100755 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/n ## Quick Start -For a quick setup with in-memory storage: +For a quick local development setup with in-memory storage: - The plugin is self-configuring as described in [Package Setup](#package-setup). To enable attachments, simply add the plugin package to your project: ```sh @@ -46,13 +46,13 @@ entity Incidents { } ``` -In this guide, we use the [Incidents Management reference sample app](https://github.com/cap-js/incidents-app) as the base application to provide a demonstration how to use this plugin. A miniature version of this app can be found within the [tests](https://github.com/cap-js/attachments/tree/main/tests/incidents-app) directory for local testing. +In this guide, we use the [Incidents Management reference sample app](https://github.com/cap-js/incidents-app) as the base application to provide a demonstration how to use this plugin. A miniature version of this app can be found within the [tests](./tests/incidents-app) directory for local testing. -For object store integration, see [Object Stores](#object-stores). +For productive use, a valid object store binding is required, see [Object Stores](#object-stores). ## Local Walk-Through -With the steps above, we have successfully set up asset handling for our reference application. Let's see that in action by extending the Incidents Entity in the schema.cds file. We can try out the scenarios where the attachments contents are stored locally in the database. +With the steps above, we have successfully set up asset handling for our reference application. To test the application locally, use the following steps. For local testing, the attachments contents are stored in a local database. 1. **Start the server**: @@ -120,15 +120,12 @@ Both methods directly add the respective UI Facet. Take note that in order to us ### Storage Targets -By default, the plugin operates without a dedicated storage target, storing attachments directly in the underlying database. - -Other available storage targets: -- AWS -- Local mock file system (only for testing scenarios) +When testing locally, the plugin operates without a dedicated storage target, storing attachments directly in the underlying database. When using a dedicated storage target, the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file is kept in the database, as defined in the CDS model. -For using SAP Object Store, you must already have an SAP Object Store service instance created. To bind it locally, follow this setup: +For productive use, you need a valid object store binding. Currently, only the AWS S3 object store is supported. +For using an AWS S3 Object Store in BTP, you must already have an SAP Object Store service instance on an AWS landscape created. To bind it locally, follow this setup: 1. Log in to Cloud Foundry: @@ -136,14 +133,14 @@ For using SAP Object Store, you must already have an SAP Object Store service in cf login -a -o -s --sso ``` -2. To bind to the service, continue with the steps below. - - In the project directory, you can generate a new file _.cdsrc-private.json by running: +2. To bind to the service, generate a new file _.cdsrc-private.json in the project directory by running: ```sh cds bind --to ``` + Where `ObjectStoreLocalName` can be any name given by the user here. + See [Object Stores](#object-stores) for further information on SAP Object Store. ### Malware Scanner @@ -162,7 +159,7 @@ By default, malware scanning is enabled for all profiles if a storage provider h } ``` -If there is no malware scanner available and the scanner is not disabled, then the uploading will fail. +If there is no malware scanner available and the scanner is not disabled, then the upload will fail. Scan status codes: - Clean: Only attachments with the status Clean are accessible. @@ -235,7 +232,6 @@ The typical sequence includes: The plugin supports multitenancy scenarios, allowing both shared and tenant-specific object store instances. -- When using SAP HANA as the storage target, multitenancy support depends on the consuming application. In most cases, multitenancy is achieved by using a dedicated schema for each tenant, providing strong data isolation at the database level. - When using an [object store](storage-targets/cds-feature-attachments-oss) as the storage target, true multitenancy is not yet implemented (as of version 2.1.0). In this case, all blobs are stored in a single bucket, and tenant data is not separated. > [!Note] @@ -264,11 +260,11 @@ To ensure tenant identification when using a shared object store instance, the p ### Object Stores -A valid Object Store service binding is required, typically one provisioned through SAP BTP. See [Local Development](#local-development) and [Deployment to Cloud Foundry](#deployment-to-cloud-foundry) on how to use this object store service binding. +A valid object store service binding is required, typically one provisioned through SAP BTP. See [Local Development](#local-development) and [Deployment to Cloud Foundry](#deployment-to-cloud-foundry) on how to use this object store service binding. #### Local development -For local development, bind to an Object Store service using the `cds bind` command as described in the [CAP documentation for hybrid testing](https://cap.cloud.sap/docs/advanced/hybrid-testing#services-on-cloud-foundry): +For local development, bind to an object store service using the `cds bind` command as described in the [CAP documentation for hybrid testing](https://cap.cloud.sap/docs/advanced/hybrid-testing#services-on-cloud-foundry): ```bash cds bind @@ -334,7 +330,7 @@ To set the binding, provide the following environment variables: ### Model Texts -In the model, several fields are annotated with the `@title` annotation. Default texts are provided in [2 languages](https://github.com/cap-js/attachments/tree/main/_i18n). If these defaults are not sufficient for an application, they can be overwritten by applications with custom texts or translations. +In the model, several fields are annotated with the `@title` annotation. Default texts are provided in [2 languages](./_i18n). If these defaults are not sufficient for an application, they can be overwritten by applications with custom texts or translations. The following table gives an overview of the fields and the i18n codes: From aee6b3682a973ae1576daa8763e3d2a01d784add Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Fri, 10 Oct 2025 14:46:06 +0200 Subject: [PATCH 28/58] Remove incorrect multitenancy line --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 5f6597c7..091f1f23 100755 --- a/README.md +++ b/README.md @@ -169,7 +169,7 @@ Scan status codes: - Infected: The attachment is infected. > [!Note] -> The plugin currently supports file uploads [up to 400 MB in size per attachment](https://help.sap.com/docs/malware-scanning-servce/sap-malware-scanning-service/what-is-sap-malware-scanning-service). +> The plugin currently supports file uploads [up to 400 MB in size per attachment](https://help.sap.com/docs/malware-scanning-servce/sap-malware-scanning-service/what-is-sap-malware-scanning-service) even with the malware scanner disabled. ### Visibility Control for Attachments UI Facet Generation @@ -232,8 +232,6 @@ The typical sequence includes: The plugin supports multitenancy scenarios, allowing both shared and tenant-specific object store instances. -- When using an [object store](storage-targets/cds-feature-attachments-oss) as the storage target, true multitenancy is not yet implemented (as of version 2.1.0). In this case, all blobs are stored in a single bucket, and tenant data is not separated. - > [!Note] > Starting from version 2.1.0, **separate mode** for object store instances is the default setting for multitenancy. > As of version 2.2.0, both the `standard` and `S3-standard` plans of the SAP Object Store offering are supported. From f5718520395c75d2284796e456074b8471074e4d Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Wed, 15 Oct 2025 14:06:24 +0200 Subject: [PATCH 29/58] Object Store versioning fix --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 091f1f23..c3a6d2c6 100755 --- a/README.md +++ b/README.md @@ -234,8 +234,6 @@ The plugin supports multitenancy scenarios, allowing both shared and tenant-spec > [!Note] > Starting from version 2.1.0, **separate mode** for object store instances is the default setting for multitenancy. -> As of version 2.2.0, both the `standard` and `S3-standard` plans of the SAP Object Store offering are supported. -> **Important:** The `S3-standard` plan is no longer available for new subscriptions. For new object store instances, use the `standard` plan. For multitenant applications, `@cap-js/attachments` must be included in the dependencies of both the application-level and mtx/sidecar package.json files. From 274b033f5ac6cf0c359ff3d6b6d2d86bc97824d3 Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 12:59:34 +0200 Subject: [PATCH 30/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index c3a6d2c6..95528505 100755 --- a/README.md +++ b/README.md @@ -117,7 +117,6 @@ service ProcessorService { Both methods directly add the respective UI Facet. Take note that in order to use the plugin with Fiori elements UI, be sure that [`draft` is enabled](https://cap.cloud.sap/docs/advanced/fiori#enabling-draft-with-odata-draft-enabled) for the entity using `@odata.draft.enabled`. - ### Storage Targets When testing locally, the plugin operates without a dedicated storage target, storing attachments directly in the underlying database. From 5538dd6a0823f767719a4d9230becf1970817c5b Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 12:59:53 +0200 Subject: [PATCH 31/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 95528505..800854c0 100755 --- a/README.md +++ b/README.md @@ -272,6 +272,7 @@ cds watch --profile hybrid ``` #### Deployment to Cloud Foundry + The corresponding entry in the [mta-file](https://cap.cloud.sap/docs/guides/deployment/to-cf#add-mta-yaml) possibly looks like: ``` From 152b53f90fe6858a2fa4dd7a5a1909e2dd07a0b9 Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 13:00:34 +0200 Subject: [PATCH 32/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 800854c0..3db69846 100755 --- a/README.md +++ b/README.md @@ -224,8 +224,6 @@ The typical sequence includes: | CAP Node | 8.0.0 | | UI5 | 1.136.0 | - - ## Architecture Overview ### Multitenancy From 5e756222da7dd1fd83863264e9c443404897faf0 Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 13:02:35 +0200 Subject: [PATCH 33/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3db69846..f7cec268 100755 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ For using an AWS S3 Object Store in BTP, you must already have an SAP Object Sto cds bind --to ``` - Where `ObjectStoreLocalName` can be any name given by the user here. + Where `ObjectStoreLocalName` can be any name given by the user here and `ObjectStoreRemoteName` is the name of your object store instance in BTP. See [Object Stores](#object-stores) for further information on SAP Object Store. From 647ea4f3a9273d23f32efa93bf387ca849448d8b Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 13:03:47 +0200 Subject: [PATCH 34/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f7cec268..a40d93c3 100755 --- a/README.md +++ b/README.md @@ -161,11 +161,11 @@ By default, malware scanning is enabled for all profiles if a storage provider h If there is no malware scanner available and the scanner is not disabled, then the upload will fail. Scan status codes: -- Clean: Only attachments with the status Clean are accessible. -- Scanning: Immediately after upload, the attachment is marked as Scanning. Depending on processing speed, it may already appear as Clean when the page is reloaded. -- Unscanned: Attachment is still unscanned. -- Failed: Scanning failed. -- Infected: The attachment is infected. +- `Unscanned`: Attachment is still unscanned. +- `Scanning`: Immediately after upload, the attachment is marked as Scanning. Depending on processing speed, it may already appear as Clean when the page is reloaded. +- `Clean`: Only attachments with the status Clean are accessible. +- `Infected`: The attachment is infected. +- `Failed`: Scanning failed. > [!Note] > The plugin currently supports file uploads [up to 400 MB in size per attachment](https://help.sap.com/docs/malware-scanning-servce/sap-malware-scanning-service/what-is-sap-malware-scanning-service) even with the malware scanner disabled. From b9da5017dcf5426a6711b930505539b4712f6c45 Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 13:04:14 +0200 Subject: [PATCH 35/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a40d93c3..00a7ce3d 100755 --- a/README.md +++ b/README.md @@ -215,7 +215,7 @@ The typical sequence includes: ## Releases - The plugin is released to [NPM Registry](https://www.npmjs.com/package/@cap-js/attachments) and [GitHub Releases](https://github.com/cap-js/attachments/releases). -- See the [changelog](./CHANGELOG.md) for the latest changes. +- See the [changelog](./CHANGELOG.md) or [GitHub Releases](https://github.com/cap-js/attachments/releases) for the latest changes. ## Minimum UI5 and CAP NodeJS Version From cb32c028be92aa4861bc4ecca50f3b1d97116674 Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 13:04:33 +0200 Subject: [PATCH 36/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 00a7ce3d..41085be0 100755 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ The typical sequence includes: ## Releases -- The plugin is released to [NPM Registry](https://www.npmjs.com/package/@cap-js/attachments) and [GitHub Releases](https://github.com/cap-js/attachments/releases). +- The plugin is released to [NPM Registry](https://www.npmjs.com/package/@cap-js/attachments). - See the [changelog](./CHANGELOG.md) or [GitHub Releases](https://github.com/cap-js/attachments/releases) for the latest changes. ## Minimum UI5 and CAP NodeJS Version From 26ecf70b2a5938d80aa4f1f81590d81448d398ac Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 13:08:00 +0200 Subject: [PATCH 37/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 41085be0..288a0b73 100755 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ Scan status codes: - `Failed`: Scanning failed. > [!Note] -> The plugin currently supports file uploads [up to 400 MB in size per attachment](https://help.sap.com/docs/malware-scanning-servce/sap-malware-scanning-service/what-is-sap-malware-scanning-service) even with the malware scanner disabled. +> The plugin currently supports file uploads up to 400 MB in size per attachment as this is a limitation of the [malware scanning service](https://help.sap.com/docs/malware-scanning-servce/sap-malware-scanning-service/what-is-sap-malware-scanning-service). Please note: this limitation occurs even with the malware scanner disabled. ### Visibility Control for Attachments UI Facet Generation From 726f33318db38bb889625f679881216d0354f5bd Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Thu, 16 Oct 2025 13:35:28 +0200 Subject: [PATCH 38/58] Simon edits --- README.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 288a0b73..d4bf0da4 100755 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ Both methods directly add the respective UI Facet. Take note that in order to us When testing locally, the plugin operates without a dedicated storage target, storing attachments directly in the underlying database. -When using a dedicated storage target, the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file is kept in the database, as defined in the CDS model. +When using a dedicated storage target, the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file including metadata is kept in the database, as defined in the CDS model. For productive use, you need a valid object store binding. Currently, only the AWS S3 object store is supported. For using an AWS S3 Object Store in BTP, you must already have an SAP Object Store service instance on an AWS landscape created. To bind it locally, follow this setup: @@ -144,7 +144,7 @@ See [Object Stores](#object-stores) for further information on SAP Object Store. ### Malware Scanner -The malware scanner is used in the `AttachmentService` to scan attachments. +The BTP malware scanning service is used in the `AttachmentService` to scan attachments for vulnerabilities. For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serviceCatalog/malware-scanning-service), you must already have a service instance which you can access. To bind it, run the following command: ```sh @@ -153,9 +153,14 @@ For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serv By default, malware scanning is enabled for all profiles if a storage provider has been specified. You can configure malware scanning by setting: ```json -"attachments": { - "scan": true -} +{ + "cds": { + // (...) + "attachments": { + "scan": true + } + } +} ``` If there is no malware scanner available and the scanner is not disabled, then the upload will fail. @@ -168,7 +173,7 @@ Scan status codes: - `Failed`: Scanning failed. > [!Note] -> The plugin currently supports file uploads up to 400 MB in size per attachment as this is a limitation of the [malware scanning service](https://help.sap.com/docs/malware-scanning-servce/sap-malware-scanning-service/what-is-sap-malware-scanning-service). Please note: this limitation occurs even with the malware scanner disabled. +> The plugin currently supports file uploads up to 400 MB in size per attachment as this is a limitation of the [malware scanning service](https://help.sap.com/docs/malware-scanning-servce/sap-malware-scanning-service/what-is-sap-malware-scanning-service). Please note: this limitation remains even with the malware scanner disabled. ### Visibility Control for Attachments UI Facet Generation From f8747441701754a8c274ea0c89d8521a964a2873 Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 13:38:54 +0200 Subject: [PATCH 39/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d4bf0da4..c4de4a42 100755 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ entity Incidents { ### Non-Draft Upload -For scenarios where the entity is not draft-enabled, see the sample [`tests/non-draft-request.http`](./tests/non-draft-request.http) to perform `.http` requests for metadata creation and content upload. +For scenarios where the entity is not draft-enabled, for example [`tests/non-draft-request.http`](./tests/non-draft-request.http), separate http requests for metadata creation and asset uploading need to be performaned manually. The typical sequence includes: From 62c2299ba26c50bbc0a2596057372713181fc64f Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Thu, 16 Oct 2025 14:52:28 +0200 Subject: [PATCH 40/58] Combining object storage sections --- README.md | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index c4de4a42..b94a49fe 100755 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ With the steps above, we have successfully set up asset handling for our referen ## Usage +
### Package Setup The attachments plugin needs to be referenced in the package.json of the consuming CAP NodeJS application: @@ -89,6 +90,22 @@ The attachments plugin needs to be referenced in the package.json of the consumi This is done automatically by running `npm add @cap-js/attachments`. With this, the aspect Attachments can be used in the application's CDS model. +In addition, different profiles can be found in `package.json` as well, such as: + +```json +"cds": { + "requires": { + //... + "[hybrid]": { + "attachments": { + "kind": "s3" + //... + } + } + } +} +``` +
### Changes in the CDS Models @@ -115,13 +132,17 @@ service ProcessorService { } ``` -Both methods directly add the respective UI Facet. Take note that in order to use the plugin with Fiori elements UI, be sure that [`draft` is enabled](https://cap.cloud.sap/docs/advanced/fiori#enabling-draft-with-odata-draft-enabled) for the entity using `@odata.draft.enabled`. +Both methods directly add the respective UI Facet. Take note that in order to use the plugin with Fiori elements UI, be sure that [`draft` is enabled](https://cap.cloud.sap/docs/advanced/fiori#enabling-draft-with-odata-draft-enabled) for the entity using `@odata.draft.enabled`. For example: + +```cds +annotate service.Incidents with @odata.draft.enabled; +``` ### Storage Targets -When testing locally, the plugin operates without a dedicated storage target, storing attachments directly in the underlying database. +When testing locally, the plugin operates without a dedicated storage target, storing attachments directly in the underlying database using the `cds bind` command as described in the [CAP documentation for hybrid testing](https://cap.cloud.sap/docs/advanced/hybrid-testing#services-on-cloud-foundry). -When using a dedicated storage target, the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file including metadata is kept in the database, as defined in the CDS model. +Meanwhile, with a dedicated storage target the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file including metadata is kept in the database, as defined in the CDS model. For productive use, you need a valid object store binding. Currently, only the AWS S3 object store is supported. For using an AWS S3 Object Store in BTP, you must already have an SAP Object Store service instance on an AWS landscape created. To bind it locally, follow this setup: @@ -140,6 +161,12 @@ For using an AWS S3 Object Store in BTP, you must already have an SAP Object Sto Where `ObjectStoreLocalName` can be any name given by the user here and `ObjectStoreRemoteName` is the name of your object store instance in BTP. +3. To run the application locally, run the command: + +```bash +cds watch --profile hybrid +``` + See [Object Stores](#object-stores) for further information on SAP Object Store. ### Malware Scanner @@ -215,8 +242,6 @@ The typical sequence includes: 1. **POST** to create attachment metadata 2. **PUT** to upload file content using the ID returned -> Make sure to replace `{{host}}`, `{{auth}}`, and IDs accordingly. - ## Releases - The plugin is released to [NPM Registry](https://www.npmjs.com/package/@cap-js/attachments). @@ -260,20 +285,6 @@ To ensure tenant identification when using a shared object store instance, the p A valid object store service binding is required, typically one provisioned through SAP BTP. See [Local Development](#local-development) and [Deployment to Cloud Foundry](#deployment-to-cloud-foundry) on how to use this object store service binding. -#### Local development - -For local development, bind to an object store service using the `cds bind` command as described in the [CAP documentation for hybrid testing](https://cap.cloud.sap/docs/advanced/hybrid-testing#services-on-cloud-foundry): - -```bash -cds bind -``` - -This will create an entry in the `.cdsrc-private.json` file with the service binding configuration. Then start the application with: - -```bash -cds watch --profile hybrid -``` - #### Deployment to Cloud Foundry The corresponding entry in the [mta-file](https://cap.cloud.sap/docs/guides/deployment/to-cf#add-mta-yaml) possibly looks like: From 3756a66d71a1ac7f136fac3f91737aaad9cacb6b Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 15:00:49 +0200 Subject: [PATCH 41/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b94a49fe..bc8ce567 100755 --- a/README.md +++ b/README.md @@ -361,7 +361,7 @@ In addition to the field names, header information (`@UI.HeaderInfo`) are also a ## Monitoring & Logging -To configure logging for the attachments plugin, add the following line to the `package.json` of the consuming application: +To configure logging for the attachments plugin, add the following configuration to the `package.json` of the consuming application: ``` { "cds": { From 73b04ae940675c35aefd3f75238a7c3358e6f8e9 Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 16 Oct 2025 15:01:11 +0200 Subject: [PATCH 42/58] Update README.md Co-authored-by: Simon Kobler <32038731+KoblerS@users.noreply.github.com> --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bc8ce567..3b4e5714 100755 --- a/README.md +++ b/README.md @@ -362,13 +362,13 @@ In addition to the field names, header information (`@UI.HeaderInfo`) are also a ## Monitoring & Logging To configure logging for the attachments plugin, add the following configuration to the `package.json` of the consuming application: -``` +```json { "cds": { "log": { "levels": { - ... - attachments: DEBUG + // (...) + "attachments": "debug" } } } From fe22f2670a71ce32bff857dfa4459912c8b8e8f6 Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Fri, 17 Oct 2025 11:21:53 +0200 Subject: [PATCH 43/58] Fix links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3b4e5714..ecb35d61 100755 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ entity Incidents { In this guide, we use the [Incidents Management reference sample app](https://github.com/cap-js/incidents-app) as the base application to provide a demonstration how to use this plugin. A miniature version of this app can be found within the [tests](./tests/incidents-app) directory for local testing. -For productive use, a valid object store binding is required, see [Object Stores](#object-stores). +For productive use, a valid object store binding is required, see [Object Stores](#object-stores) and [Storage Targets](#storage-targets). ## Local Walk-Through @@ -283,7 +283,7 @@ To ensure tenant identification when using a shared object store instance, the p ### Object Stores -A valid object store service binding is required, typically one provisioned through SAP BTP. See [Local Development](#local-development) and [Deployment to Cloud Foundry](#deployment-to-cloud-foundry) on how to use this object store service binding. +A valid object store service binding is required, typically one provisioned through SAP BTP. See [Storage Targets](#storage-targets) and [Deployment to Cloud Foundry](#deployment-to-cloud-foundry) on how to use this object store service binding. #### Deployment to Cloud Foundry From 1b8ffefe7537f231bb3630734d5cf02c4e2905f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Jeglinsky?= Date: Tue, 21 Oct 2025 12:01:24 +0200 Subject: [PATCH 44/58] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ecb35d61..549b18d4 100755 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ With the steps above, we have successfully set up asset handling for our referen ## Usage
+ ### Package Setup The attachments plugin needs to be referenced in the package.json of the consuming CAP NodeJS application: From 021b00d7bea9603e359cb851a4cb6d903aa5a04d Mon Sep 17 00:00:00 2001 From: Eric P Date: Tue, 21 Oct 2025 15:36:39 +0200 Subject: [PATCH 45/58] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 549b18d4..28a5c54e 100755 --- a/README.md +++ b/README.md @@ -240,8 +240,8 @@ For scenarios where the entity is not draft-enabled, for example [`tests/non-dra The typical sequence includes: -1. **POST** to create attachment metadata -2. **PUT** to upload file content using the ID returned +1. **POST** -> create attachment metadata, returns ID +2. **PUT** -> upload file content using the ID ## Releases From 5d505c755664ba27f85b76b1867464175960710d Mon Sep 17 00:00:00 2001 From: Eric P Date: Tue, 21 Oct 2025 15:37:23 +0200 Subject: [PATCH 46/58] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 28a5c54e..0412633f 100755 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ entity Incidents { ### Non-Draft Upload -For scenarios where the entity is not draft-enabled, for example [`tests/non-draft-request.http`](./tests/non-draft-request.http), separate http requests for metadata creation and asset uploading need to be performaned manually. +For scenarios where the entity is not draft-enabled, for example [`tests/non-draft-request.http`](./tests/non-draft-request.http), separate HTTP requests for metadata creation and asset uploading need to be performed manually. The typical sequence includes: From 2c14a954bc51724bfa22ee04a0daa1f42a58cc0d Mon Sep 17 00:00:00 2001 From: Eric P Date: Tue, 21 Oct 2025 15:37:45 +0200 Subject: [PATCH 47/58] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0412633f..9001cfa7 100755 --- a/README.md +++ b/README.md @@ -157,7 +157,7 @@ For using an AWS S3 Object Store in BTP, you must already have an SAP Object Sto 2. To bind to the service, generate a new file _.cdsrc-private.json in the project directory by running: ```sh - cds bind --to + cds bind --to ``` Where `ObjectStoreLocalName` can be any name given by the user here and `ObjectStoreRemoteName` is the name of your object store instance in BTP. From 301e24a03e2b027a283626acdce4a35fa16636dc Mon Sep 17 00:00:00 2001 From: Eric P Date: Tue, 21 Oct 2025 15:37:54 +0200 Subject: [PATCH 48/58] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9001cfa7..abe5183a 100755 --- a/README.md +++ b/README.md @@ -160,7 +160,7 @@ For using an AWS S3 Object Store in BTP, you must already have an SAP Object Sto cds bind --to ``` - Where `ObjectStoreLocalName` can be any name given by the user here and `ObjectStoreRemoteName` is the name of your object store instance in BTP. + Where `LocalObjectStoreName` can be any name given by the user here and `RemoteObjectStoreName` is the name of your object store instance in SAP BTP. 3. To run the application locally, run the command: From c417274c3ab6dd91b81ef84362827d0ff3a2aa62 Mon Sep 17 00:00:00 2001 From: Eric P Date: Tue, 21 Oct 2025 15:38:05 +0200 Subject: [PATCH 49/58] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index abe5183a..60a2e9de 100755 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ The BTP malware scanning service is used in the `AttachmentService` to scan atta For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serviceCatalog/malware-scanning-service), you must already have a service instance which you can access. To bind it, run the following command: ```sh - cds bind --to + cds bind --to ``` By default, malware scanning is enabled for all profiles if a storage provider has been specified. You can configure malware scanning by setting: From 4f4fdb83863870d72d2b2a23a8834f24d9d36ad2 Mon Sep 17 00:00:00 2001 From: Eric P Date: Tue, 21 Oct 2025 15:42:27 +0200 Subject: [PATCH 50/58] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 60a2e9de..11351725 100755 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ service ProcessorService { } ``` -Both methods directly add the respective UI Facet. Take note that in order to use the plugin with Fiori elements UI, be sure that [`draft` is enabled](https://cap.cloud.sap/docs/advanced/fiori#enabling-draft-with-odata-draft-enabled) for the entity using `@odata.draft.enabled`. For example: +Both methods directly add the respective UI Facet. To use the plugin with an SAP Fiori elements UI, be sure that [`draft` is enabled](https://cap.cloud.sap/docs/advanced/fiori#enabling-draft-with-odata-draft-enabled) for the entity using `@odata.draft.enabled`. For example: ```cds annotate service.Incidents with @odata.draft.enabled; From 6f316c68deb56a58438a512b1185dad76036a089 Mon Sep 17 00:00:00 2001 From: Eric P Date: Tue, 21 Oct 2025 15:43:16 +0200 Subject: [PATCH 51/58] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 11351725..12a02fca 100755 --- a/README.md +++ b/README.md @@ -263,7 +263,7 @@ The plugin supports multitenancy scenarios, allowing both shared and tenant-spec > [!Note] > Starting from version 2.1.0, **separate mode** for object store instances is the default setting for multitenancy. -For multitenant applications, `@cap-js/attachments` must be included in the dependencies of both the application-level and mtx/sidecar package.json files. +For multitenant applications, `@cap-js/attachments` must be included in the dependencies of both the application-level and _mtx/sidecar/package.json_ files. #### Shared Object Store Instance From 692608930d5a6f12f9b31f0d02c7bc991698b672 Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Tue, 21 Oct 2025 15:50:33 +0200 Subject: [PATCH 52/58] Remove header from details --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 12a02fca..60c3b899 100755 --- a/README.md +++ b/README.md @@ -76,10 +76,10 @@ With the steps above, we have successfully set up asset handling for our referen ## Usage -
- ### Package Setup +
+ The attachments plugin needs to be referenced in the package.json of the consuming CAP NodeJS application: ```cds From b781ecb60c2f09d145812e05194fb5eae813b923 Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Wed, 22 Oct 2025 14:11:03 +0200 Subject: [PATCH 53/58] Refactor package information --- README.md | 67 ++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 6dab4fde..fba2d611 100755 --- a/README.md +++ b/README.md @@ -28,7 +28,9 @@ The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/n * [Code of Conduct](#code-of-conduct) * [Licensing](#licensing) -## Quick Start +## Usage + +### Quick Start For a quick local development setup with in-memory storage: @@ -36,6 +38,35 @@ For a quick local development setup with in-memory storage: ```sh npm add @cap-js/attachments ``` + +
+ +The attachments plugin needs to be referenced in the package.json of the consuming CAP NodeJS application: + +```cds +"devDependencies": { + "@cap-js/attachments": "", + //... +} +``` + +In addition, different profiles can be found in `package.json` as well, such as: + +```json +"cds": { + "requires": { + //... + "[hybrid]": { + "attachments": { + "kind": "s3" + //... + } + } + } +} +``` +
+ - To use Attachments, extend a CDS model by adding an element that refers to the pre-defined Attachments type (see [Changes in the CDS Models](#changes-in-the-cds-models) for more details): ```cds using { Attachments } from '@cap-js/attachments'; @@ -74,40 +105,6 @@ With the steps above, we have successfully set up asset handling for our referen 5. **Delete a file** by going into Edit mode, selecting the file, and pressing the **Delete** button above the Attachments table. Clicking the **Save** button will then delete that file from the resource (database, S3 bucket, etc.). Delete an attachment -## Usage - -### Package Setup - -
- -The attachments plugin needs to be referenced in the package.json of the consuming CAP NodeJS application: - -```cds -"devDependencies": { - "@cap-js/attachments": "", - //... -} -``` - -This is done automatically by running `npm add @cap-js/attachments`. With this, the aspect Attachments can be used in the application's CDS model. - -In addition, different profiles can be found in `package.json` as well, such as: - -```json -"cds": { - "requires": { - //... - "[hybrid]": { - "attachments": { - "kind": "s3" - //... - } - } - } -} -``` -
- ### Changes in the CDS Models To use the aspect `Attachments` on an existing entity, the corresponding entity needs to either include attachments as an element in the model definition or be extended in a CDS file in the `srv` module. In the quick start, the former was done, adding an element to the model definition: From b15d165890f74bcf781a2c649ddc5693e6d4942d Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Wed, 22 Oct 2025 23:58:37 +0200 Subject: [PATCH 54/58] Fixing TOC --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fba2d611..35576894 100755 --- a/README.md +++ b/README.md @@ -8,10 +8,9 @@ The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/n -* [Quick Start](#quick-start) -* [Local Walk-Through](#local-walk-through) * [Usage](#usage) - * [Package Setup](#package-setup) + * [Quick Start](#quick-start) + * [Local Walk-Through](#local-walk-through) * [Changes in the CDS Models](#changes-in-the-cds-models) * [Storage Targets](#storage-targets) * [Malware Scanner](#malware-scanner) @@ -82,7 +81,7 @@ In this guide, we use the [Incidents Management reference sample app](https:// For productive use, a valid object store binding is required, see [Object Stores](#object-stores) and [Storage Targets](#storage-targets). -## Local Walk-Through +### Local Walk-Through With the steps above, we have successfully set up asset handling for our reference application. To test the application locally, use the following steps. For local testing, the attachments contents are stored in a local database. 1. **Start the server**: From 91e3aeb0bb621141a24d4672eaa94d0f5db702ed Mon Sep 17 00:00:00 2001 From: Simon Kobler Date: Thu, 23 Oct 2025 13:14:43 +0200 Subject: [PATCH 55/58] Fix formatting and indentation in README.md for better readability --- README.md | 141 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 74 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 35576894..a350c4a9 100755 --- a/README.md +++ b/README.md @@ -33,80 +33,83 @@ The `@cap-js/attachments` package is a [CDS plugin](https://cap.cloud.sap/docs/n For a quick local development setup with in-memory storage: -- The plugin is self-configuring as described in [Package Setup](#package-setup). To enable attachments, simply add the plugin package to your project: -```sh - npm add @cap-js/attachments - ``` - -
- -The attachments plugin needs to be referenced in the package.json of the consuming CAP NodeJS application: - -```cds -"devDependencies": { - "@cap-js/attachments": "", - //... -} -``` - -In addition, different profiles can be found in `package.json` as well, such as: +- The plugin is self-configuring as described, see the following details section. To enable attachments, simply add the plugin package to your project: + ```sh + npm add @cap-js/attachments + ``` + +
+ The attachments plugin needs to be referenced in the package.json of the consuming CAP NodeJS application: + + ```cds + "devDependencies": { + "@cap-js/attachments": "", + // (...) + } + ``` -```json -"cds": { - "requires": { - //... - "[hybrid]": { - "attachments": { - "kind": "s3" - //... + In addition, different profiles can be found in `package.json` as well, such as: + + ```json + "cds": { + "requires": { + // (...) + "[hybrid]": { + "attachments": { + "kind": "s3" + // (...) + } + } } } - } -} -``` -
+ ``` +
- To use Attachments, extend a CDS model by adding an element that refers to the pre-defined Attachments type (see [Changes in the CDS Models](#changes-in-the-cds-models) for more details): -```cds -using { Attachments } from '@cap-js/attachments'; -entity Incidents { - // ... - attachments: Composition of many Attachments; -} -``` + ```cds + using { Attachments } from '@cap-js/attachments'; + + entity Incidents { + // (...) + attachments: Composition of many Attachments; + } + ``` In this guide, we use the [Incidents Management reference sample app](https://github.com/cap-js/incidents-app) as the base application to provide a demonstration how to use this plugin. A miniature version of this app can be found within the [tests](./tests/incidents-app) directory for local testing. For productive use, a valid object store binding is required, see [Object Stores](#object-stores) and [Storage Targets](#storage-targets). - ### Local Walk-Through -With the steps above, we have successfully set up asset handling for our reference application. To test the application locally, use the following steps. For local testing, the attachments contents are stored in a local database. + +With the steps above, we have successfully set up asset handling for our reference application. To test the application locally, use the following steps. + +> [!NOTE] +> For local testing, the attachment objects are stored in a [local database](https://cap.cloud.sap/docs/guides/databases-sqlite). 1. **Start the server**: - - *Default* scenario (In memory database): - ```sh - cds watch - ``` +- *Default* scenario (In memory database): + ```sh + cds watch + ``` 2. **Navigate to the object page** of the incident `Solar panel broken`: - - Go to object page for incident **Solar panel broken** +Go to object page for incident **Solar panel broken** 3. The `Attachments` type has generated an out-of-the-box Attachments table (see 1) at the bottom of the Object page: -Attachments Table + Attachments Table 4. **Upload a file** by going into Edit mode and either using the **Upload** button on the Attachments table or by drag/drop. Then click the **Save** button to have that file stored that file in the dedicated resource (database, S3 bucket, etc.). We demonstrate this by uploading the PDF file from [_tests/integration/content/sample.pdf_](./tests/integration/content/sample.pdf): -Upload an attachment + Upload an attachment 5. **Delete a file** by going into Edit mode, selecting the file, and pressing the **Delete** button above the Attachments table. Clicking the **Save** button will then delete that file from the resource (database, S3 bucket, etc.). -Delete an attachment + Delete an attachment ### Changes in the CDS Models To use the aspect `Attachments` on an existing entity, the corresponding entity needs to either include attachments as an element in the model definition or be extended in a CDS file in the `srv` module. In the quick start, the former was done, adding an element to the model definition: + ```cds using { Attachments } from '@cap-js/attachments'; @@ -116,7 +119,8 @@ entity Incidents { } ``` -The entity Incidents can also be extended in the `srv` module, as seen in the following example: +The entity Incidents can also be extended in the `srv` module, as seen in the following example: + ```cds using { Attachments } from '@cap-js/attachments'; @@ -142,23 +146,23 @@ When testing locally, the plugin operates without a dedicated storage target, st Meanwhile, with a dedicated storage target the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file including metadata is kept in the database, as defined in the CDS model. For productive use, you need a valid object store binding. Currently, only the AWS S3 object store is supported. -For using an AWS S3 Object Store in BTP, you must already have an SAP Object Store service instance on an AWS landscape created. To bind it locally, follow this setup: +For using an AWS S3 Object Store in BTP, you must already have an SAP Object Store service instance on an AWS landscape created. To bind it in a hybrid setup, follow this setup: 1. Log in to Cloud Foundry: - ```sh - cf login -a -o -s --sso - ``` +```sh +cf login -a -o -s --sso +``` 2. To bind to the service, generate a new file _.cdsrc-private.json in the project directory by running: - ```sh - cds bind --to - ``` +```sh +cds bind --to +``` - Where `LocalObjectStoreName` can be any name given by the user here and `RemoteObjectStoreName` is the name of your object store instance in SAP BTP. +Where `HybridObjectStoreName` can be any name given by the user here and `RemoteObjectStoreName` is the name of your object store instance in SAP BTP. -3. To run the application locally, run the command: +3. To run the application in hybrid mode, run the command: ```bash cds watch --profile hybrid @@ -171,11 +175,13 @@ See [Object Stores](#object-stores) for further information on SAP Object Store. The BTP malware scanning service is used in the `AttachmentService` to scan attachments for vulnerabilities. For using [SAP Malware Scanning Service](https://discovery-center.cloud.sap/serviceCatalog/malware-scanning-service), you must already have a service instance which you can access. To bind it, run the following command: - ```sh - cds bind --to - ``` + +```sh +cds bind --to +``` By default, malware scanning is enabled for all profiles if a storage provider has been specified. You can configure malware scanning by setting: + ```json { "cds": { @@ -213,8 +219,8 @@ entity Incidents { attachments: Composition of many Attachments; } ``` -In this example, the `@UI.Hidden` is set to `true`, which means the plugin will be hidden by default. You can also use dynamic expressions which are then added to the facet. +In this example, the `@UI.Hidden` is set to `true`, which means the plugin will be hidden by default. You can also use dynamic expressions which are then added to the facet. ```cds entity Incidents { @@ -267,13 +273,13 @@ To configure a shared object store instance, modify both the package.json files ```json "cds": { - "requires": { - "attachments": { - "objectStore": { - "kind": "shared" - } - } + "requires": { + "attachments": { + "objectStore": { + "kind": "shared" + } } + } } ``` To ensure tenant identification when using a shared object store instance, the plugin prefixes attachment URLs with the tenant ID. Be sure the shared object store instance is bound to the `mtx` application module before deployment. @@ -359,6 +365,7 @@ In addition to the field names, header information (`@UI.HeaderInfo`) are also a ## Monitoring & Logging To configure logging for the attachments plugin, add the following configuration to the `package.json` of the consuming application: + ```json { "cds": { From 44ae323ee0ab8ef34fa63e4606e463a99e5d5e43 Mon Sep 17 00:00:00 2001 From: Simon Kobler <32038731+KoblerS@users.noreply.github.com> Date: Fri, 24 Oct 2025 14:12:44 +0200 Subject: [PATCH 56/58] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a350c4a9..2f56583f 100755 --- a/README.md +++ b/README.md @@ -150,9 +150,8 @@ For using an AWS S3 Object Store in BTP, you must already have an SAP Object Sto 1. Log in to Cloud Foundry: -```sh -cf login -a -o -s --sso -``` + ```sh + cf login -a -o -s --sso 2. To bind to the service, generate a new file _.cdsrc-private.json in the project directory by running: From 6f07714eeb0f12bbf32ffd5d87b7088a18437fdd Mon Sep 17 00:00:00 2001 From: Simon Kobler <32038731+KoblerS@users.noreply.github.com> Date: Fri, 24 Oct 2025 14:13:03 +0200 Subject: [PATCH 57/58] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2f56583f..3644d05d 100755 --- a/README.md +++ b/README.md @@ -155,9 +155,8 @@ For using an AWS S3 Object Store in BTP, you must already have an SAP Object Sto 2. To bind to the service, generate a new file _.cdsrc-private.json in the project directory by running: -```sh -cds bind --to -``` + ```sh + cds bind --to Where `HybridObjectStoreName` can be any name given by the user here and `RemoteObjectStoreName` is the name of your object store instance in SAP BTP. From c39b42d271d4249150b299da86258e9fc777117b Mon Sep 17 00:00:00 2001 From: Simon Kobler <32038731+KoblerS@users.noreply.github.com> Date: Fri, 24 Oct 2025 14:42:26 +0200 Subject: [PATCH 58/58] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: René Jeglinsky --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3644d05d..24441abd 100755 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ annotate service.Incidents with @odata.draft.enabled; ### Storage Targets -When testing locally, the plugin operates without a dedicated storage target, storing attachments directly in the underlying database using the `cds bind` command as described in the [CAP documentation for hybrid testing](https://cap.cloud.sap/docs/advanced/hybrid-testing#services-on-cloud-foundry). +When testing locally, the plugin operates without a dedicated storage target, storing attachments directly in the underlying database. In a hybrid setup, a dedicated storage target is preferred. You can bind it by using the `cds bind` command as described in the [CAP documentation for hybrid testing].(https://cap.cloud.sap/docs/advanced/hybrid-testing#services-on-cloud-foundry). Meanwhile, with a dedicated storage target the attachment is not stored in the underlying database; instead, it is saved on the specified storage target and only a reference to the file including metadata is kept in the database, as defined in the CDS model.