Skip to content

cap-java/cds-feature-attachments

Java Build with Maven Deploy new Version with Maven REUSE status

Attachments Plugin for SAP Cloud Application Programming Model (CAP)

The com.sap.cds:cds-feature-attachments dependency is a CAP Java plugin that provides out-of-the box attachments storage and handling by using an aspect Attachments.

Table of Contents

Additional Information

Support, Feedback, Contributing

This project is open to feature requests/suggestions, bug reports etc. via GitHub 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.

Minimum Version

The following version are the minimum versions for the usage of the plugin:

Component Minimum Version
CAP Java 3.4.1
UI5 1.131.0

Maven Central

The feature is released to Maven Central at: https://central.sonatype.com/artifact/com.sap.cds/cds-feature-attachments

Artifactory

Snapshots are deployed to SAP's Artifactory in DMZ: https://common.repositories.cloud.sap/artifactory/cap-java/com/sap/cds/cds-feature-attachments/

If you want to test snapshot versions of this plugin, you need to configure the Artifactory in your ${HOME}/.m2/settings.xml. See here for further details.

Usage

The usage of CAP Java plugins is described in the CAP Java Documentation. Following this documentation this plugin needs to be referenced in the srv/pom.xml of a CAP Java project:

<dependency>
    <groupId>com.sap.cds</groupId>
    <artifactId>cds-feature-attachments</artifactId>
    <version>${latest-version}</version>
</dependency>

The latest version can be found in the changelog or in the Maven Central Repository.

To be able to also use the CDS models defined in this plugin the cds-maven-plugin needs to be used with the resolve goal to make the CDS models available in the project:

<plugin>
    <groupId>com.sap.cds</groupId>
    <artifactId>cds-maven-plugin</artifactId>
    <version>${cds.services.version}</version>
    <executions>
        <execution>
            <id>cds.resolve</id>
            <goals>
                <goal>resolve</goal>
            </goals>
        </execution>
    </executions>
</plugin>

After that, the aspect Attachments can be used in the application's CDS model.

CDS Models

Depending on the location in the application's CDS model where the aspect Attachments shall be used, different approaches need to be implemented. If the aspect Attachments shall be used on an entity provided in the db module, the corresponding entity needs to be extended from a CDS file in the srv module. Therefore the entity from the db folder needs to be imported with an using statement. Then, this entity can be extended with a new field that is a Composition of many Attachments. The following example shows how to extend the db entity Books in a CDS file in the srv module:

using {my.bookshop as my} from '../db/index';
using {sap.attachments.Attachments} from 'com.sap.cds/cds-feature-attachments';

// Extends the Books entity with the Attachments composition
extend my.Books with {
  covers : Composition of many Attachments;
};

To use the aspect Attachments in the srv module, the following code needs to be added to the existing entity definition:

using {sap.attachments.Attachments} from `com.sap.cds/cds-feature-attachments`;

entity Items : cuid {
    ...
    attachments : Composition of many Attachments;
    ...
}

The aspect Attachments shall be used directly for the composition. It is very important to use the correct from clause for the using statement. Only if com.sap.cds/cds-feature-attachments is used and not concrete files of the feature are specified in the from-statement also the annotations and other definitions are found and used.

Model Texts

In the model several fields are annotated with the @title annotation. Starting with version 1.0.6 of the cds-feature-attachments, default texts are provided in 35 languages. 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 also header information (@UI.HeaderInfo) are annotated:

Header Info i18n Code
TypeName attachment
TypeNamePlural attachments

Status Texts

For the status of the attachment only the code value is stored at the moment. The status codes are:

  • Unscanned
  • Scanning
  • Clean
  • Infected
  • Failed

If a text for the status needs to be displayed on the UI the model needs to be enhanced with the texts. For this a new Statuses entity needs to be created like the following example:

entity Statuses @cds.autoexpose @readonly {
    key code : StatusCode;
        text : localized String(255);
}

For this entity csv files can be included in the project structure with texts and translations, to show the translated texts on the UI.

With this a text can be added in example above like:

extend Attachments with {
    statusText : Association to Statuses on statusText.code = $self.status;
}

With this an annotation can be added to the attachments entity to have the status text displayed in the UI:

status @(
    Common.Text: {
        $value: ![statusText.text],
        ![@UI.TextArrangement]: #TextOnly
    },
    ValueList: {entity:'Statuses'},
    sap.value.list: 'fixed-values'
);

UI

To enhance the UI with the attachments the following annotations are used for the UI.Facets annotations in your app:

    {
        $Type  : 'UI.ReferenceFacet',
        ID     : 'AttachmentsFacet',
        Label  : '{i18n>attachments}',
        Target : 'attachments/@UI.LineItem'
    }

A complete UI.Facets annotation could look like:

annotate service.Incidents with @(
    UI.Facets : [
        {
            $Type : 'UI.CollectionFacet',
            Label : '{i18n>Overview}',
            ID : 'Overview',
            Facets : [
                {
                    $Type : 'UI.ReferenceFacet',
                    Label : '{i18n>GeneralInformation}',
                    ID : 'i18nGeneralInformation',
                    Target : '@UI.FieldGroup#i18nGeneralInformation',
                },
                {
                    $Type : 'UI.ReferenceFacet',
                    Label : '{i18n>Details}',
                    ID : 'i18nDetails',
                    Target : '@UI.FieldGroup#i18nDetails',
                }
            ]
        },
        {
            $Type : 'UI.ReferenceFacet',
            Label : 'Conversations',
            ID : 'Conversations',
            Target : 'conversations/@UI.LineItem#Conversations',
        },
        {
            $Type  : 'UI.ReferenceFacet',
            ID     : 'AttachmentsFacet',
            Label  : '{i18n>attachments}',
            Target : 'attachments/@UI.LineItem'
        }
    ]
);

Outbox

In this plugin the persistent outbox is used to mark attachments as deleted. The enablement of the outbox is also included in the cds models of this plugin. In the capire documentation of the persistent outbox is it described how to overwrite the default outbox configuration.

If the default shall be used, nothing needs to be done.

Malware Scanner

This plugin checks for a binding to the SAP Malware Scanning Service. The concrete check if for a binding to a service with label malware-scanner.

The malware scanner is used in the default implementation of the technical service AttachmentService to scan attachments. If the default implementation of this service is overwritten, e.g. by using the plugin enhancement of the SAP Document Management Service, then this overwriting plugin is responsible for the malware scan and the plugin documentation needs to be checked for how the malware scan is done.

If the default implementation is used and the malware scanner is not available the attachments are marked as clean by setting the status of the attachment to:

  • Clean

Only attachments with the status Clean are accessible. Attachments with all other status codes are not accessible.

If the malware scanner is available but during the request to the scanner an error occurs the status of the attachment is set to:

  • Failed

Error Messages

If attachments are uploaded but not scanned by a malware scanner (if a scanner is available) or are marked as infected the direct access of the attachment is not possible. In case users try to access the content of the attachment the following errors messages are displayed:

Error Message Error Message i18n Code
Attachment is not clean not_clean
Attachment is not scanned, try again in a few minutes not_scanned

By adding the error message i18n code to the i18n.properties file the error message can be overwritten translated. More information can be found in the capire documentation for i18n.

Restore Endpoint

The attachment service has an event RESTORE_ATTACHMENTS. This event can be called with a timestamp to restore external stored attachments.

Motivation

Documents which are marked as deleted can be restored.

The use case behind this feature is:

If backups of databases are restored the attachments stored in external storages also needs to be restored. To have a possibility to restore attachments which are marked as deleted a restore endpoint is available.

In the default implementation of the technical service AttachmentService this is not needed as the attachments are stored directly in the database and are restored with the database.

If the default implementation is overwritten, e.g. by using the plugin enhancement of the SAP Document Management Service, then this overwriting plugin needs to handle the restore of attachments.

In such cases the restore endpoint can be used to restore attachments.

How long attachments are marked as deleted before they get deleted dependents on the configuration of the used storage.

HTTP Endpoint

There is no predefined endpoint for the restore action. To call the action of the service from outside the application a service could be defined like the following example:

service RestoreAttachments {
  action restoreAttachments (restoreTimestamp: Timestamp);
}

The action restoreAttachments could get in a timestamp from which the attachments need to be restored. The action could be called with a POST request to the endpoint:

  • OData v4: /odata/v4/RestoreAttachments/restoreAttachments
  • OData v2: /odata/v2/RestoreAttachments/restoreAttachments

With the body:

{
  "restoreTimestamp": "2024-04-17T10:36:38.813491100Z"
}

The action needs to be implemented and can call the attachment service as in the following example:

@ServiceName(RestoreAttachments_.CDS_NAME)
public class RestoreAttachmentsHandler implements EventHandler {

	private final AttachmentService attachmentService;

	public RestoreAttachmentsHandler(AttachmentService attachmentService) {
		this.attachmentService = attachmentService;
	}

	@On(event = RestoreAttachmentsContext.CDS_NAME)
	public void restoreAttachments(RestoreAttachmentsContext context) {
		attachmentService.restoreAttachment(context.getRestoreTimestamp());
		context.setCompleted();
	}

}

In the Spring Boot context the AttachmentService can be autowired in the handler.

Security

To secure the endpoint security annotations can be used e.g. like the following example:

using {sap.attachments.Attachments} from `com.sap.cds/cds-feature-attachments`;

entity Items : cuid {
    ...
    attachments : Composition of many Attachments;
    ...
}

annotate RestoreAttachments with @(requires: 'internal-user');

Here the RestoreAttachments service is annotated with the requires annotation to secure the service. Also, other annotations can be used to secure the service.

More information about the CAP Java security concept can be found in the CAP Java Documentation.

About

Support for attachments

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 12